使用UIImageJPEGRepresentation
(您通过 a 来回往返资产UIImage
)可能会出现问题,因为使用compressionQuality
1.0 的 a,结果NSData
实际上可能比原始文件大得多。(另外,您在 . 中持有该图像的第二个副本UIImage
。)
例如,我刚刚从 iPhone 的照片库中随机选择了一张图片,原始资源为 1.5mb,但a为 1.0 的NSData
制作者需要 6.2mb。并且将图像保存在本身可能会占用更多内存(因为如果未压缩,它可能需要,例如,每个像素四个字节)。UIImageJPEGRepresentation
compressionQuality
UIImage
相反,您可以使用以下方法获取原始资产getBytes
:
static NSInteger kBufferSize = 1024 * 10;
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSURL *url = info[UIImagePickerControllerReferenceURL];
[self.library assetForURL:url resultBlock:^(ALAsset *asset) {
ALAssetRepresentation *representation = [asset defaultRepresentation];
long long remaining = representation.size;
NSString *filename = representation.filename;
long long representationOffset = 0ll;
NSError *error;
NSMutableData *data = [NSMutableData data];
uint8_t buffer[kBufferSize];
while (remaining > 0ll) {
NSInteger bytesRetrieved = [representation getBytes:buffer fromOffset:representationOffset length:sizeof(buffer) error:&error];
if (bytesRetrieved <= 0) {
NSLog(@"failed getBytes: %@", error);
return;
} else {
remaining -= bytesRetrieved;
representationOffset += bytesRetrieved;
[data appendBytes:buffer length:bytesRetrieved];
}
}
// you can now use the `NSData`
} failureBlock:^(NSError *error) {
NSLog(@"assetForURL error = %@", error);
}];
}
这避免了在 a 中暂存图像,UIImage
并且结果NSData
可以(对于照片,无论如何)要小得多。请注意,这还有一个优点,即它也保留了与图像关联的元数据。
顺便说一句,虽然上面的内容代表了显着的内存改进,但您可能会看到更显着的内存减少机会:具体来说,与其NSData
一次将整个资产加载到 a 中,您现在可以流式传输资产(NSInputStream
使用此getBytes
例程的子类在需要时获取字节,而不是一次将整个内容加载到内存中)。这个过程有一些麻烦(请参阅BJ Homer 关于该主题的文章),但如果您正在寻找显着减少内存占用的方法,那就是这样。这里有几种方法(BJ,使用一些暂存文件并从中流式传输等),但关键是流式传输可以显着减少您的内存占用。
但是通过避免UIImage
in UIImageJPEGRepresentation
(这避免了图像占用的内存以及产生的较大内存NSData
)UIImageJPEGRepresentation
,您可能会取得相当大的进展。此外,您可能希望确保一次在内存中没有此图像数据的冗余副本(例如,不要将图像数据加载到 aNSData
中,然后NSData
为HTTPBody
...可以一举搞定)。如果情况变得更糟,您可以采用流媒体方法。