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

 萱筱璧 发布于 2022-12-19 19:17

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

Josh Heald.. 20

更新:

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

Apple定义的方法是CGRect在图像的坐标空间中传递a ,其中原点为(0,0),最大值为(1,1).你在传递这个RECT 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获取的方形缩略图.

首先,确保将contentMode您的属性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;
}];

指定PHImageRequestOptionsResizeModeExactresizeMode不是必需的,因为它不会给你一个裁剪的图像,除非您同时提供normalizedCropRect,并且因为没有好处不应该用在这里,并用它意味着你没有得到迅速恢复缓存图片的好处.

UIImage返回的result将是相同的纵横比为源,但在使用正确缩放UIImageView被设置为填补方面显示为一个正方形,所以如果你只是显示出来,这是要走的路.如果您需要裁剪图像以便在应用程序之外进行打印或导出,这不是您想要的 - 请查看其用途normalizedCropRect.(编辑 - 见下面的例子,应该有什么用......)

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

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

编辑以添加normalizedCropRect用法示例
警告 - 这不起作用,但应根据Apple的文档.

Apple定义的方法是CGRect在图像的坐标空间中传递a ,其中原点为(0,0),最大值为(1,1).你在传递这个RECT PHImageRequestOptions对象,有一起resizeModePHImageRequestOptionsResizeModeExact,然后你应该得到一个裁剪后的图像.问题是你没有,它以原始宽高比和完整图像的形式返回.

我已经验证了裁剪矩形是在图像的坐标空间中正确创建的,并且遵循了要使用的指令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提出雷达要求他们修复它!

2 个回答
  • 更新:

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

    Apple定义的方法是CGRect在图像的坐标空间中传递a ,其中原点为(0,0),最大值为(1,1).你在传递这个RECT 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获取的方形缩略图.

    首先,确保将contentMode您的属性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;
    }];
    

    指定PHImageRequestOptionsResizeModeExactresizeMode不是必需的,因为它不会给你一个裁剪的图像,除非您同时提供normalizedCropRect,并且因为没有好处不应该用在这里,并用它意味着你没有得到迅速恢复缓存图片的好处.

    UIImage返回的result将是相同的纵横比为源,但在使用正确缩放UIImageView被设置为填补方面显示为一个正方形,所以如果你只是显示出来,这是要走的路.如果您需要裁剪图像以便在应用程序之外进行打印或导出,这不是您想要的 - 请查看其用途normalizedCropRect.(编辑 - 见下面的例子,应该有什么用......)

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

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

    编辑以添加normalizedCropRect用法示例
    警告 - 这不起作用,但应根据Apple的文档.

    Apple定义的方法是CGRect在图像的坐标空间中传递a ,其中原点为(0,0),最大值为(1,1).你在传递这个RECT PHImageRequestOptions对象,有一起resizeModePHImageRequestOptionsResizeModeExact,然后你应该得到一个裁剪后的图像.问题是你没有,它以原始宽高比和完整图像的形式返回.

    我已经验证了裁剪矩形是在图像的坐标空间中正确创建的,并且遵循了要使用的指令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提出雷达要求他们修复它!

    2022-12-19 19:18 回答
  •   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];
    
        }];
    

    2022-12-19 19:18 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有