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

发布于 2025-01-04 16:03:20 字数 1128 浏览 4 评论 0原文

我正在使用 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,已将 UIImagePNGRepresentation 替换为 UIImageJPEGRepresentation。 对于解决方案 2,已将 kUTTypePNG 替换为 kUTTypeJPEG

另外值得注意的是,第二个解决方案比第一个解决方案的内存效率更高。

I am using ALAsset to retrieve images like that:

[[asset defaultRepresentation] fullResolutionImage]]

This return CGImageRef which I want to save to disk as fast as possible...

Solution 1:

UIImage *currentImage = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullResolutionImage]];
NSData *currentImageData = UIImagePNGRepresentation(currentImage);
[currentImageData writeToFile:filePath atomically:YES];

Solution 2:

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

The problem is that both methods are very slow performing on a device. I takes about 2 seconds per image to perform this. And this is absolutely to long.

Question: How can I speed up this image saving process? Or perhaps is there a better solution for this?

UPDATE:
The best performance improvements in both solutions is to save images to JPEG format instead of PNG.
So for solution 1 have replaced UIImagePNGRepresentation with UIImageJPEGRepresentation.
For solution 2 have replaced kUTTypePNG with kUTTypeJPEG.

Also worth noting that second solution is way more memory efficient that first one.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

眼波传意 2025-01-11 16:03:20

您可以只复制原始数据。
这样做的优点是不重新编码文件、不会使文件变大、不会因额外压缩而损失质量以及保留文件中的任何元数据。
应该也是最快的方法。
假设您有 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];
}

You could just copy the raw data instead.
This has the advantages of not re-encoding the file, not making the file bigger, not losing quality through additional compression and preserving any meta data in the file.
Should also be the fastest possible way.
Assuming you have theAsset and a filepath to save it to.
Should add error handling as well.

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];
}
徒留西风 2025-01-11 16:03:20

这是因为 PNG 压缩过程很慢,并且在 iPhone 的处理器上需要一段时间,特别是对于全尺寸摄影。

That's because of PNG compression is slow process, and takes a while on iPhone's processor, especially for full-size photography.

ゝ杯具 2025-01-11 16:03:20

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

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

There is no such a way to speed the process up, but a possible solution would be to use threads, this way you will not block the mainthread and you will offer the user a better experience:

dispatch_queue_t dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(dispatchQueue, ^(void) {
    // Your code here
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文