如何从PHImageManager获取平方的缩略图?
有没有人想法如何从PHImageManager取平方的拇指? PHImageContentModeAspectFill选项不起作用。
[[PHImageManager defaultManager] requestImageForAsset:(PHAsset *)_asset targetSize:CGSizeMake(80, 80) contentMode:PHImageContentModeAspectFill options:nil resultHandler:^(UIImage *result, NSDictionary *info) { // sadly result is not a squared image imageView.image = result; }];
更新:
从看起来这些错误仍然存在,并且包括iOS 8.4,我可以使用标准的iPhone 6s后置相机图像进行复制,拍摄出全尺寸的方形作物。 它们在iOS 9.0中正确固定,即使是6300万像素的大尺寸作物也能正常工作。 PHImageManager
中检索图像时裁剪图像的错误在iOS 8.3中得到修复,因此对于该版本的iOS及更高版本,我的原始示例如下所示:
Apple定义的方法是在图像的坐标空间中传递CGRect
,其中原点是(0,0),最大值是(1,1)。 你在PHImageRequestOptions
对象中传递这个矩形,再加上一个resizeMode
的PHImageRequestOptionsResizeModeExact
,然后你应该找回一个裁剪后的图像。
- (void)showSquareImageForAsset:(PHAsset *)asset { NSInteger retinaScale = [UIScreen mainScreen].scale; CGSize retinaSquare = CGSizeMake(100*retinaScale, 100*retinaScale); PHImageRequestOptions *cropToSquare = [[PHImageRequestOptions alloc] init]; cropToSquare.resizeMode = PHImageRequestOptionsResizeModeExact; CGFloat cropSideLength = MIN(asset.pixelWidth, asset.pixelHeight); CGRect square = CGRectMake(0, 0, cropSideLength, cropSideLength); CGRect cropRect = CGRectApplyAffineTransform(square, CGAffineTransformMakeScale(1.0 / asset.pixelWidth, 1.0 / asset.pixelHeight)); cropToSquare.normalizedCropRect = cropRect; [[PHImageManager defaultManager] requestImageForAsset:(PHAsset *)asset targetSize:retinaSquare contentMode:PHImageContentModeAspectFit options:cropToSquare resultHandler:^(UIImage *result, NSDictionary *info) { self.imageView.image = result; }]; }
这个例子使得其边长的cropRect
等于资产的宽度和高度的较小值,然后使用CGRectApplyAffineTransform
将其转换为图像的坐标空间。 您可能希望将square
的原点设置为除(0,0)之外的其他东西,因为您经常希望裁剪的方形沿正在裁剪的图像的轴居中,但是我会将其作为练习给读者。 🙂
原始答案:
约翰的回答让我感受到了大部分的方式,但是使用他的代码我得到了延伸和压扁的图像。 以下是我如何获取imageView以显示从PHImageManager中获取的方形缩略图。
首先,确保您的UIImageView
的contentMode
属性设置为ScaleAspectFill
。 默认是ScaleToFill
,无法正确显示来自PHImageManager
方形缩略图,因此无论您是在代码中还是在故事板中实例化UIImageView
,请确保更改此设置。
//view dimensions are based on points, but we're requesting pixels from PHImageManager NSInteger retinaMultiplier = [UIScreen mainScreen].scale; CGSize retinaSquare = CGSizeMake(imageView.bounds.size.width * retinaMultiplier, imageView.bounds.size.height * retinaMultiplier); [[PHImageManager defaultManager] requestImageForAsset:(PHAsset *)_asset targetSize:retinaSquare contentMode:PHImageContentModeAspectFill options:nil resultHandler:^(UIImage *result, NSDictionary *info) { // The result is not square, but correctly displays as a square using AspectFill imageView.image = result; }];
为resizeMode
指定PHImageRequestOptionsResizeModeExact
不是必需的,因为它不会给你一个裁剪的图像,除非你还提供了normalizedCropRect
,不应该在这里使用,因为没有任何好处,使用它意味着你没有得到快速返回的好处caching的图像。
在result
返回的UIImage
与源代码具有相同的纵横比,但是在UIImageView
正确使用,这个UIImageView
被设置为方面填充以显示为一个正方形,所以如果你只是显示它,这是要走的路。 如果您需要裁剪图像以便在应用程序之外进行打印或导出,则不是您想要的 – 请查看normalizedCropRect
的用法。 (编辑 – 看下面的例子应该是什么工作…)
除此之外,还要确保将UIImageView的内容模式设置为UIViewContentModeScaleAspectFill ,并且您将以下两行设置clipsToBounds = YES:
imageView.contentMode=UIViewContentModeScaleAspectFill; imageView.clipsToBounds=YES;
编辑以添加normalizedCropRect用法示例
警告 – 这不起作用,但应根据苹果的文件 。
Apple定义的方法是在图像的坐标空间中传递CGRect
,其中原点是(0,0),最大值是(1,1)。 你在PHImageRequestOptions
对象中传递这个矩形,再加上一个resizeMode
的PHImageRequestOptionsResizeModeExact
,然后你应该找回一个裁剪后的图像。 问题是,你不这样做,它会回到原来的长宽比和完整的形象。
我已经validation在图像的坐标空间中正确创build了裁切矩形,并遵循指令使用PHImageRequestOptionsResizeModeExact
,但是结果处理程序仍将以原始高宽比传递图像。 这似乎是在框架中的一个错误,当它被修复时,下面的代码应该工作。
- (void)showSquareImageForAsset:(PHAsset *)asset { NSInteger retinaScale = [UIScreen mainScreen].scale; CGSize retinaSquare = CGSizeMake(100*retinaScale, 100*retinaScale); PHImageRequestOptions *cropToSquare = [[PHImageRequestOptions alloc] init]; cropToSquare.resizeMode = PHImageRequestOptionsResizeModeExact; CGFloat cropSideLength = MIN(asset.pixelWidth, asset.pixelHeight); CGRect square = CGRectMake(0, 0, cropSideLength, cropSideLength); CGRect cropRect = CGRectApplyAffineTransform(square, CGAffineTransformMakeScale(1.0 / asset.pixelWidth, 1.0 / asset.pixelHeight)); cropToSquare.normalizedCropRect = cropRect; [[PHImageManager defaultManager] requestImageForAsset:(PHAsset *)asset targetSize:retinaSquare contentMode:PHImageContentModeAspectFit options:cropToSquare resultHandler:^(UIImage *result, NSDictionary *info) { self.imageView.image = result; }]; }
我可以build议的是,如果你有这个问题,你可以向苹果公司提出一个雷达 ,要求他们修复这个问题!
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; options.resizeMode = PHImageRequestOptionsResizeModeExact; NSInteger retinaMultiplier = [UIScreen mainScreen].scale; CGSize retinaSquare = CGSizeMake(imageView.bounds.size.width * retinaMultiplier, imageView.bounds.size.height * retinaMultiplier); [[PHImageManager defaultManager] requestImageForAsset:(PHAsset *)_asset targetSize:retinaSquare contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage *result, NSDictionary *info) { imageView.image =[UIImage imageWithCGImage:result.CGImage scale:retinaMultiplier orientation:result.imageOrientation]; }];
要得到一个精确的正方形,你必须通过传递选项来表示你想要一个确切的大小,如下所示:
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; // No, really, we want this exact size options.resizeMode = PHImageRequestOptionsResizeModeExact [[PHImageManager defaultManager] requestImageForAsset:(PHAsset *)_asset targetSize:CGSizeMake(160, 160) contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage *result, NSDictionary *info) { // Happily, result is now a squared image imageView.image = result; }];
这对我来说工作得很好:
__block UIImage* imgThumb; CGSize size=CGSizeMake(45, 45);// Size for Square image [self.imageManager requestImageForAsset:<your_current_phAsset> targetSize:size contentMode:PHImageContentModeAspectFill options:nil resultHandler:^(UIImage *result, NSDictionary *info) { imgThumb = result; }];