[英]Most memory efficient way to save a photo to disk on iPhone?
通过使用Instruments
性能分析,我了解到将图像保存到磁盘的方式导致内存峰值增加到~60MB
。 这导致该应用发出low memory warnings
,这(不一致)导致运行iOS7
的iPhone4S
崩溃。
我需要将映像保存到磁盘的最有效方法。
我目前正在使用此代码
+ (void)saveImage:(UIImage *)image withName:(NSString *)name {
NSData *data = UIImageJPEGRepresentation(image, 1.0);
DLog(@"*** SIZE *** : Saving file of size %lu", (unsigned long)[data length]);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
[fileManager createFileAtPath:fullPath contents:data attributes:nil];
}
笔记:
减少UIImageJPEGRepresentation
中的compressionQuality
参数的值不能充分减少内存峰值。 例如compressionQuality = 0.8
,在100
写入中平均减少了3MB
的内存峰值。 但是,它确实减小了磁盘上数据的大小(显然),但这对我没有帮助。
UIImageJPEGRepresentation
UIImagePNGRepresentation
代替UIImageJPEGRepresentation
更为糟糕。 它速度较慢,导致尖峰较高。
ImageIO
这种方法是否可能会更有效? 如果可以,为什么?
如果有人有任何建议,那就太好了。 谢谢
编辑:
注意以下问题中概述的一些要点。
a)尽管我保存了多张图像,但并未将它们循环保存。 我做了一些阅读和测试,发现自动释放池对我没有帮助。
b)每张照片的大小都不是60Mb。 它们是在iPhone 4S上拍摄的照片。
考虑到这一点,我回到尝试克服我认为问题所在的位置。 NSData *data = UIImageJPEGRepresentation(image, 1.0);
行NSData *data = UIImageJPEGRepresentation(image, 1.0);
。
导致崩溃的内存峰值可以在下面的屏幕截图中看到。 它们对应于UIImageJPEGRepresentation
调用时间。 我还运行了“ Time Profiler
和“ System Usage
,它们使我朝着相同的方向发展。
长话短说,我搬到了AVFoundation
并使用
photoData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
它返回一个NSData
类型的对象,然后我将其用作使用NSFileManager进行写入的数据。
这样可以完全消除内存中的峰值。
即
[self saveImageWithData:photoData];
哪里
+ (void)saveImageWithData:(NSData *)imageData withName:(NSString *)name {
NSData *data = imageData;
DLog(@"*** SIZE *** : Saving file of size %lu", (unsigned long)[data length]);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
[fileManager createFileAtPath:fullPath contents:data attributes:nil];
}
PS:如果人们认为它没有回答标题“将照片保存到iPhone上的磁盘的最有效存储方式?”,我没有将其作为问题的答案。 但是,如果共识是应该的,我可以对其进行更新。
谢谢。
使用UIImageJPEGRepresentation要求您同时将原始图像和最终图像存储在内存中。 它还可能会缓存完整渲染的图像一段时间,这会占用大量内存。
您可以尝试使用CGImageDestination 。 我不知道它的内存效率如何,但是它有潜力直接将图像流式传输到磁盘。
+(void) writeImage:(UIImage *)inImage toURL:(NSURL *)inURL withQuality:(double)inQuality {
CGImageDestinationRef destination = CGImageDestinationCreateWithURL( (CFURLRef)inURL , kUTTypeJPEG , 1 , NULL );
CFDictionaryRef properties = (CFDictionaryRef)[NSDictionary dictionaryWithObject:[NSNumber numberWithDouble:inQuality] forKey:kCGImageDestinationLossyCompressionQuality];
CGImageDestinationAddImage( destination , [inImage CGImage] , properties );
CGImageDestinationFinalize( destination );
CFRelease( destination );
}
每个图像实际压缩60MB吗? 如果是这样,如果要将它们另存为单个JPEG文件,则无能为力。 您可以尝试将其渲染为较小的图像,或将它们平铺并将其保存到单独的文件中。
我不希望您的ImageIO代码段能够改善任何情况。 如果存在两行修复,则UIImageJPEGRepresentation
将在内部使用它。
但我敢打赌,您不会从单个图像中获得60MB的空间。 我敢打赌,从循环保存的多张图片中您可以获得60MB的空间。 如果是这种情况,那么您可能可以做一些事情。 将@autoreleasepool{}
放入循环中。 您很可能会积累自动释放的对象,这会导致峰值。 在循环中添加一个池可以使其耗尽。
完成写入数据后,尝试使用NSAutoReleasePool并清空池。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.