【发布时间】:2014-01-07 08:13:12
【问题描述】:
通过使用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的内存峰值。 但是,它确实减少了磁盘上数据的大小(显然),但这对我没有帮助。UIImagePNGRepresentation代替UIImageJPEGRepresentation对此更糟。它速度较慢,并导致更高的尖峰。
this approach 和 ImageIO 是否可能更有效?如果有,为什么?
如果有人有任何建议,那就太好了。谢谢
编辑:
关于以下问题中概述的一些要点的注释。
a) 虽然我保存了多张图片,但我并没有将它们保存在一个循环中。我做了一些阅读和测试,发现自动释放池对我没有帮助。
b) 每张照片的大小都不是 60Mb。它们是在 iPhone 4S 上拍摄的。
考虑到这一点,我回去尝试克服我认为的问题;行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 上将照片保存到磁盘的最节省内存的方法?”,我没有把它作为问题的答案。但是,如果共识是应该的,我可以更新它。
谢谢。
【问题讨论】:
-
您说的是内存和磁盘数据。只有在内存中会导致应用程序被强制终止。你在内存中保留了哪些你不需要的东西。如果图像很大,那么您需要以不同的方式使用它...
-
我知道。我也在问题中说明了这一点。即“但是,它确实减少了磁盘上数据的大小(显然)但这对我没有帮助。”您的评论“如果图像很大,那么您需要以不同的方式使用它”没有帮助。
-
我认为
saveImage:withName不是问题。这可能是您调用此函数的方式。提供使用此功能的代码,人们可以帮助您。 -
因此,请关注内存中的情况,并详细说明有多少图像,在保存之前如何处理它们,它们有多大......
-
我同意。将其发布为答案;如果出现更好的情况,您可以随时移动复选标记。
标签: ios iphone objective-c uiimage avfoundation