如何在iOS上快速将ALAsset图像保存到磁盘?

7
我正在使用ALAsset来检索图像,就像这样:
[[asset defaultRepresentation] fullResolutionImage]]

这个返回CGImageRef,我希望尽快将其保存到磁盘上...
解决方案1:
UIImage *currentImage = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullResolutionImage]];
NSData *currentImageData = UIImagePNGRepresentation(currentImage);
[currentImageData writeToFile:filePath atomically:YES];

解决方案2:

CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:filePath];
CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL);
CGImageDestinationAddImage(destination, [[asset defaultRepresentation] fullResolutionImage], nil);
CGImageDestinationFinalize(destination);

问题在于这两种方法在设备上执行速度非常慢。每张图像的处理时间约为2秒。这显然太长了。
问题:如何加快图像保存过程?或者,是否有更好的解决方案?
更新: 两种解决方案中最佳的性能改进是将图像保存为JPEG格式,而不是PNG格式。 因此,对于解决方案1,我们已经用UIImageJPEGRepresentation替换了UIImagePNGRepresentation。 对于解决方案2,我们已经用kUTTypeJPEG替换了kUTTypePNG。
值得注意的是,第二种解决方案比第一种更省内存。
3个回答

9

你可以直接复制原始数据。
这样做的好处是不需要重新编码文件,不会使文件变得更大,不会通过额外压缩而失去质量,同时还能保留文件中的任何元数据。
这也应该是最快的方式。
假设你已经有了theAsset和一个保存路径filepath
还应该添加错误处理。

long long sizeOfRawDataInBytes = [[theAsset defaultRepresentation] size];
NSMutableData* rawData = [NSMutableData dataWithLength:(NSUInteger) sizeOfRawDataInBytes];
void* bufferPointer = [rawData mutableBytes];
NSError* error=nil;
[[theAsset defaultRepresentation] getBytes:bufferPointer 
                                fromOffset:0
                                    length:sizeOfRawDataInBytes
                                     error:&error];
if (error) 
{
    NSLog(@"Getting bytes failed with error: %@",error);
}
else 
{
    [rawData writeToFile:filepath 
              atomically:YES];
}

这个问题的关键是图像的方向信息丢失了。 - rydgaze

2

这是因为PNG压缩是一个较慢的过程,并且在iPhone处理器上需要一段时间,尤其是对于全尺寸的摄影照片。


我明白。但是有没有其他更有效的方法来做到这一点?我不需要PNG格式。实际上,任何格式都可以。我只需要将原始图像从ALAsset复制到我的自定义文件夹中...?谢谢 - Borut Tomazin
我刚刚尝试了JPEG表示法 - 它比PNG表示法快了一半(仍然需要约1秒)。这好多了。但仍不是我所期望的。还有其他的方法吗?那么两个我在问题中发布的解决方案之间的区别呢?它们是否有任何优势? - Borut Tomazin
最耗时的操作是图像压缩,因此两种方法应该需要大约相同的时间。如果您只需要一张图片,您可以保存 CGImage 的字节,并在之后加载它们,这样压缩就会被省略。 - Nickolay Olshevsky
不,我将保存多个图像。你有任何例子吗?另外,我不需要压缩。原始图像就可以了... - Borut Tomazin
我没有例子,例如可以看看这个问题:https://dev59.com/u3I-5IYBdhLWcg3w-92b - Nickolay Olshevsky
显示剩余2条评论

1

没有什么方法可以加快进程,但一个可能的解决方案是使用线程,这样你就不会阻塞主线程,为用户提供更好的体验:

dispatch_queue_t dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(dispatchQueue, ^(void) {
    // Your code here
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接