如何从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; }]; 

更新:

PHImageManager中检索图像时裁剪图像的错误在iOS 8.3中得到修复,因此对于该版本的iOS及更高版本,我的原始示例如下所示:看起来这些错误仍然存​​在,并且包括iOS 8.4,我可以使用标准的iPhone 6s后置相机图像进行复制,拍摄出全尺寸的方形作物。 它们在iOS 9.0中正确固定,即使是6300万像素的大尺寸作物也能正常工作。

Apple定义的方法是在图像的坐标空间中传递CGRect ,其中原点是(0,0),最大值是(1,1)。 你在PHImageRequestOptions对象中传递这个矩形,再加上一个resizeModePHImageRequestOptionsResizeModeExact ,然后你应该找回一个裁剪后的图像。

 - (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中获取的方形缩略图。

首先,确保您的UIImageViewcontentMode属性设置为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对象中传递这个矩形,再加上一个resizeModePHImageRequestOptionsResizeModeExact ,然后你应该找回一个裁剪后的图像。 问题是,你不这样做,它会回到原来的长宽比和完整的形象。

我已经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; }];