如何从PHImageManager获取平方缩略图?

时间:2014-09-24 17:52:54

标签: ios ios8 photosframework

有人知道如何从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;
}];

5 个答案:

答案 0 :(得分:20)

<强>更新

PHImageManager检索图像时修剪图像的错误已在iOS 8.3中修复,因此对于该版本的iOS及更高版本,我的原始示例有效,如下所示: 看来这些错误仍然存​​在,包括iOS 8.4,我可以使用标准的iPhone 6s后置摄像头图像重现它们,采用全尺寸方形裁剪。它们在iOS 9.0中得到了适当的修复,即使是6300万像素全景的大型作物也能正常工作。

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

首先,确保contentMode的{​​{1}}属性设置为UIImageView。默认设置为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; }]; 指定PHImageRequestOptionsResizeModeExact,因为它不会为您提供裁剪的图像,除非您还提供了resizeMode,并且不应在此处使用,因为没有任何好处并且使用它意味着您无法获得快速返回的缓存图像的好处。

normalizedCropRect中返回的UIImage与源的宽高比相同,但可以正确缩放以用于result,其设置为宽高比填充以显示为正方形,所以如果你只是展示它,这就是你要走的路。如果您需要裁剪图像以进行打印或在应用程序之外导出,这不是您想要的 - 请查看UIImageView的使用情况。 (编辑 - 见以下例如应该起作用的内容......)

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

normalizedCropRect

编辑以添加normalizedCropRect用法示例
警告 - 这不起作用,但应根据Apple's documentation

Apple定义的方法是在图像的坐标空间中传递imageView.contentMode=UIViewContentModeScaleAspectFill; imageView.clipsToBounds=YES; ,其中原点为(0,0),最大值为(1,1)。您在CGRect对象中传递此矩形以及PHImageRequestOptions resizeMode,然后您应该返回裁剪后的图像。问题在于你没有,它以原始宽高比和完整图像的形式返回。

我已经验证了裁剪矩形是在图像的坐标空间中正确创建的,并且遵循指令使用PHImageRequestOptionsResizeModeExact,但结果处理程序仍将以原始宽高比传递图像。这似乎是框架中的一个错误,当它修复时,以下代码应该可以工作。

PHImageRequestOptionsResizeModeExact

我可以建议的是,如果您遇到此问题,请{+ 3}}与Apple联系,要求他们解决此问题!

答案 1 :(得分:6)

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

    }];

答案 2 :(得分:2)

要获得精确的方格,您必须通过传递选项来表明您想要一个确切的大小,如下所示:

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

答案 3 :(得分:2)

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.
}

答案 4 :(得分:0)

这对我来说很好:

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

  }];