大多数内存有效的方式来保存在iPhone上的照片到磁盘?

Instruments分析我了解到,我将图像保存到磁盘的方式导致内存峰值~60MB 。 这导致应用程序发出low memory warnings ,这(不一致)导致运行iOS7iPhone4S上的iOS7

我需要最有效的方法将图像保存到磁盘。

我目前正在使用这个代码

 + (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]; } 

笔记:

  1. 减lessUIImageJPEGRepresentation中的compressionQuality参数的值不会显着减less内存尖峰。 例如compressionQuality = 0.8 ,平均超过100写入,内存尖峰减less了3MB 。 但是,它确实减less了磁盘上的数据的大小(显然),但是这对我没有帮助。

  2. UIImagePNGRepresentation代替UIImageJPEGRepresentation对此更糟糕。 速度较慢,导致峰值较高。

ImageIO 这种方法可能会更有效吗? 如果是这样的话

如果有人有任何build议,这将是伟大的。 谢谢

编辑:

请注意以下问题中列出的一些要点。

a)尽pipe我保存了多个图像,但我并没有将它们保存在一个循环中。 我做了一些阅读和testing,发现一个autorelease池不会帮助我。

b)照片不是每个60Mb的大小。 他们是在iPhone 4S拍摄的照片。

考虑到这一点,我回到了试图克服我所认为的问题; 行NSData *data = UIImageJPEGRepresentation(image, 1.0);

在下面的屏幕截图中可以看到导致崩溃的内存尖峰。 它们对应于何时UIImageJPEGRepresentation 。 我也运行Time ProfilerSystem Usage ,指出我在同一个方向。

在这里输入图像说明

长话短说,我转移到AVFoundation并使用照片图像数据

photoData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];

它返回一个NSDatatypes的对象,然后我使用这个作为数据使用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要求您同时在内存中具有原始和最终的图像。 它也可能会caching完整的渲染图像一段时间,这将使用大量的内存。

你可以尝试使用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{}放到你的循环中。 这是很有可能的,你积累自动释放对象,这是导致穗。 在你的循环中添加一个池允许它stream失。

尝试使用NSAutoReleasePool,一旦完成写入数据,就会排空游泳池。