13

我正在使用下面的代码来获取图像:

[[PHImageManager defaultManager] requestImageForAsset:asset 
targetSize:CGSizeMake(800, 600) 
contentMode:PHImageContentModeAspectFill 
options:options 
resultHandler:^(UIImage *result, NSDictionary *info) {
    NSLog(@"size:%@",NSStringFromCGSize(result.size));                
}];

我要求的图像尺寸为 800 x 600,但我得到的图像尺寸为 45 x 60,质量非常差。

我怎样才能得到请求的图像大小使用PhotoKit

4

2 回答 2

18

您(Unnati 的)自我回答会起作用,但是它错过了 Apple 在其框架中为您提供的一些优化,这些优化可以让您更快地显示图像。

您的原始代码非常正确,但是您包含了一个options您可能不需要的对象,如果您在其上设置resizeMode不正确,可能会导致您出现问题。这是应该为您工作的代码,我刚刚删除了您的选项对象。

[[PHImageManager defaultManager]
 requestImageForAsset:(PHAsset *)asset
 targetSize:CGSizeMake(800, 600)
 contentMode:PHImageContentModeAspectFit
 options:nil
 resultHandler:^(UIImage *result, NSDictionary *info) {
     NSLog(@"Image size:%@",NSStringFromCGSize(result.size));
 }];

这应该更简单,并为您免费提供 Apple 通过其框架提供的所有优化。这是您得到的解释:

以低质量图像快速响应

该框架将多次调用您的结果处理程序以提高图像质量,从而允许您在用户等待最终图像时向他们显示一些内容。从文档中

照片可能会多次调用您的结果处理程序块。照片首先调用该块以提供适合临时显示的低质量图像,同时准备高质量图像。(如果低质量图像数据立即可用,则第一次调用可能会在方法返回之前发生。)当高质量图像准备好时,Photos 会再次调用您的结果处理程序以提供它。

这意味着您的resultHandler块需要安全地多次调用 - 代码中的块只是记录大小,对于我的测试图像,我收到两条日志消息,第一条是低质量 40x26 像素图像,然后再次以高质量的图像。如果您打开 iOS 照片应用程序,您可以在它们看起来锐化之前非常短暂地看到低质量图像 - 这就是这里发生的事情。

使用options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat可以防止这种行为,并且您resultHandler只会在最终图像中调用一次,因此我建议不要设置此选项,除非您无法设计可以多次调用的处理程序块(在您的真实代码中)。

快速返回缓存的高质量图像

为了快速提供最终图像,框架将在对块的最终调用中提供接近请求大小的图像resultHandler,如果它已经缓存了一个。如果您使用的是UIImageView具有宽高比填充或适合的集合contentMode,这不会有问题,只需contentMode在您的图像请求中指定匹配即可。例如,针对我的测试图像,对我的第二次调用resultHandler是使用 1280x850 的图像,比我要求的大,但正确的球场。但是,设置options.resizeMode = PHImageRequestOptionsResizeModeExact将阻止这种行为并强制框架调整图像的新副本而不是使用缓存副本,这需要时间。

由于 Photos 框架不裁剪图像(即使您要求它,但这是一个错误 ;-)),即使使用该PHImageRequestOptionsResizeModeExact选项,您也不一定会获得您请求的确切尺寸。例如,如果您为不是 4:3 比例的图像请求 800x600,则照片无法返回该尺寸的图像,它只会尽可能接近 - 在我的最新图像上,这样的请求得到800x531 的图像。这意味着您需要能够处理不符合您要求的确切尺寸的图像,因此您不妨利用框架中的优化并避免使用PHImageRequestOptionsResizeModeExact. 再次从文档中

调整大小以完全匹配目标大小比使用快速调整大小选项效率低。

(您是否PHImageRequestOptionsResizeModeFast在原始options对象中设置了此设置,但问题中未包含该设置?这可能导致了您的问题。)

图像版本

可以请求图像的不同版本,就像您在自我回答中所做的那样options.version = PHImageRequestOptionsVersionCurrent。但是,这不是必需的,因为默认值是当前版本。

于 2014-11-15T07:29:05.287 回答
15

我能够使用以下代码获得大小为 800*600 的图像:

PHImageRequestOptions* options = [[[PHImageRequestOptions alloc] init] autorelease];
options.version = PHImageRequestOptionsVersionCurrent;
options.deliveryMode =  PHImageRequestOptionsDeliveryModeHighQualityFormat;
options.resizeMode = PHImageRequestOptionsResizeModeExact;

[PHImageManager defaultManager]
requestImageForAsset:(PHAsset *)asset
targetSize:CGSizeMake(800, 600)
contentMode:PHImageContentModeAspectFit
options:options
resultHandler:^(UIImage *result, NSDictionary *info) {
   NSLog(@"Image size:%@",NSStringFromCGSize(result.size));
}];

如果你想获得完整尺寸的图像,你可以使用PHImageManagerMaximumSizetargetSize。

于 2014-11-14T13:41:22.000 回答