如何从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对象中传递这个矩形,以及PHImageRequestOptionsResizeModeExact resizeMode,然后你应该得到一个裁剪的图像。

- (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,否则它不会为您提供裁剪的图像,并且不应在此处使用,因为没有任何好处,使用它意味着您无法获得快速返回缓存图像的好处。

result 中返回的UIImage将与源的纵横比相同,但缩放正确以在设置为宽高比填充以显示为正方形的UIImageView中使用,因此如果您只是显示它,这就是要走的路。如果您需要裁剪图像以打印或在应用程序外部导出,这不是您想要的 - 请查看normalizedCropRect的使用。(编辑 - 请参阅下面的示例,了解应该工作的内容...

除此之外,还要确保将UIImageView的内容模式设置为UIViewContentModeScaleAspectFill,并且通过以下2行设置clipsToBounds = YES:

imageView.contentMode=UIViewContentModeScaleAspectFill;
imageView.clipsToBounds=YES;

编辑以添加规范化裁剪矩形使用示例
警告 - 这不起作用,但应该根据Apple的文档

Apple 定义的方法是在图像的坐标空间中传递一个CGRect,其中原点为 (0,0(,最大值为 (1,1(。你在PHImageRequestOptions对象中传递这个矩形,以及PHImageRequestOptionsResizeModeExact 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;
     }];
}

我所能建议的是,如果您遇到此问题,请向Apple提交雷达,要求他们修复它!

  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;
    }];
let squareSize = CGSize(100, 100)
let options = PHImageRequestOptions()
options.resizeMode = .exact
options.deliveryMode = .highQualityFormat
PHImageManager.default().requestImage(for: asset, targetSize: squareSize, contentMode: .aspectFill, options: options) { (image, _) in
    // Use the image.
}

对我来说工作正常:

 __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;
  }];

最新更新