繁体   English   中英

在iPhone上将照片保存到磁盘的最有效内存方式?

[英]Most memory efficient way to save a photo to disk on iPhone?

通过使用Instruments性能分析,我了解到将图像保存到磁盘的方式导致内存峰值增加到~60MB 这导致该应用发出low memory warnings ,这(不一致)导致运行iOS7iPhone4S崩溃。

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

我目前正在使用此代码

+ (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. 减少UIImageJPEGRepresentation中的compressionQuality参数的值不能充分减少内存峰值。 例如compressionQuality = 0.8 ,在100写入中平均减少了3MB的内存峰值。 但是,它确实减小了磁盘上数据的大小(显然),但这对我没有帮助。

  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM