如何从PHImageManager获取平方缩略图? [英] How to fetch squared thumbnails from PHImageManager?

查看:1176
本文介绍了如何从PHImageManager获取平方缩略图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人知道如何从PHImageManager获取方形拇指吗? PHImageContentModeAspectFill选项无效。

Has anybody idea how to fetch squared thumbs from PHImageManager? PHImageContentModeAspectFill option has no effect.

[[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.3中修复了从 PHImageManager 中检索图像时出错的错误,因此对于该版本iOS和更高版本,我原来的例子如下:
似乎错误仍然存​​在并包括iOS 8.4,我可以使用标准iPhone 6s后置摄像头图像重现它们,需要一个完整的大小方形作物。它们在iOS 9.0中得到了适当的修复,即使是6300万像素全景的大型作物都能正常工作。

The bug in cropping images as they were retrieved from PHImageManager was fixed in iOS 8.3, so for that version of iOS and later, my original example works, as follows: It seems the bugs are still there up to and including iOS 8.4, I can reproduce them with standard iPhone 6s back camera images, taking a full size square crop. They are properly fixed in iOS 9.0, where even large crops of a 63 megapixel panorama work fine.

Apple定义的方法是传递 CGRect 在图像的坐标空间中,原点为(0,0),最大值为(1,1)。您在 PHImageRequestOptions 对象中传递此rect,以及的$ code> PHImageRequestOptionsResizeModeExact resizeMode c $ c>,然后你应该找回裁剪的图像。

The approach Apple defines is to pass a CGRect in the co-ordinate space of the image, where the origin is (0,0) and the maximum is (1,1). You pass this rect in the PHImageRequestOptions object, along with a resizeMode of PHImageRequestOptionsResizeModeExact, and then you should get back a cropped image.

- (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)以外的其他值,因为您通常希望裁剪方块沿着正在裁剪的图像的轴居中,但我会把它作为读者的练习。 : - )

This example makes its cropRect of side length equal to the smaller of the width and height of the asset, and then transforms it to the co-ordinate space of the image using CGRectApplyAffineTransform. You may want to set the origin of square to something other than (0,0), as often you want the crop square centred along the axis of the image which is being cropped, but I'll leave that as an exercise for the reader. :-)

原始答案:

John的回答让我大部分时间那里的方式,但使用他的代码,我得到拉伸和压扁的图像。这是我如何得到 imageView 来显示从PHImageManager获取的方形缩略图。

John's answer got me most of the way there, but using his code I was getting stretched and squashed images. Here's how I got an imageView to display square thumbnails fetched from the PHImageManager.

首先,确保 UIImageView contentMode 属性>设置为 ScaleAspectFill 。默认为 ScaleToFill ,它无法正常显示来自 PHImageManager 的方形缩略图,因此请确保更改这是否已在代码或故事板中实例化 UIImageView

Firstly, ensure that the contentMode property for your UIImageView is set to ScaleAspectFill. The default is to ScaleToFill, which doesn't work correctly for displaying square thumbnails from PHImageManager, so make sure you change this whether you've instantiated the UIImageView in code or in the storyboard.

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

为<$ c $指定 PHImageRequestOptionsResizeModeExact c> resizeMode 不是必需的,因为除非你还提供 normalizedCropRect ,否则它不会给你一个裁剪的图像,不应该在这里使用没有任何好处,使用它意味着您无法获得快速返回的缓存图像的好处。

Specifying PHImageRequestOptionsResizeModeExact for the resizeMode is not required, as it will not give you a cropped image unless you also supply a normalizedCropRect, and should not be used here as there's no benefit, and using it means you don't get the benefits of quickly returned cached images.

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

The UIImage returned in result will be the same aspect ratio as the source, but scaled correctly for use in a UIImageView which is set to aspect fill to display as a square, so if you're just displaying it, this is the way to go. If you need to crop the image for print or export outside of the app, this isn't what you want - look into the use of normalizedCropRect for that. (edit- see below for example of what should work...)

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

Except this also make sure that the you set the content mode of the UIImageView to UIViewContentModeScaleAspectFill and that you set clipsToBounds = YES by the following 2 lines :

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






编辑以添加normalizedCropRect用法示例

警告 - 这不起作用,但应根据 Apple的文档

Apple定义的方法是在图像的坐标空间中传递 CGRect ,其中原点为(0,0),最大值为(1,1) )。您在 PHImageRequestOptions 对象中传递此rect,以及的$ code> PHImageRequestOptionsResizeModeExact resizeMode c $ c>,然后你应该找回裁剪的图像。问题是你没有,它以原始宽高比和完整图像的形式返回。

The approach Apple defines is to pass a CGRect in the co-ordinate space of the image, where the origin is (0,0) and the maximum is (1,1). You pass this rect in the PHImageRequestOptions object, along with a resizeMode of PHImageRequestOptionsResizeModeExact, and then you should get back a cropped image. The problem is that you don't, it comes back as the original aspect ratio and the full image.

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

I've verified that the crop rect is created correctly in the image's co-ordinate space, and followed the instruction to use PHImageRequestOptionsResizeModeExact, but the result handler will still be passed an image in the original aspect ratio. This seems to be a bug in the framework, and when it is fixed, the following code should work.

- (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提交雷达请求他们修复它!

All I can suggest is that if you have this problem, you file a radar with Apple to request that they fix it!

这篇关于如何从PHImageManager获取平方缩略图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆