ios – 使用UIImagePickerController减少内存使用量

ios – 使用UIImagePickerController减少内存使用量,第1张

概述在我的应用程序中,用户可以使用UI ImagePickerController拍摄多个图像,然后在视图中逐个显示这些图像. 我在内存管理方面遇到了一些麻烦.随着今天手机上的摄像头以百万像素迅速上升,从UIImagePickerController返回的UIImages是记忆猪.在我的iPhone 4S上,UIImages约为5MB;我很难想象它们在新的和未来的模型上会是什么样的. 我的一位朋友说, 在我的应用程序中,用户可以使用UI ImagePickerController拍摄多个图像,然后在视图中逐个显示这些图像.

我在内存管理方面遇到了一些麻烦.随着今天手机上的摄像头以百万像素迅速上升,从UIImagePickerController返回的UIImages是记忆猪.在我的iPhone 4S上,UIImages约为5MB;我很难想象它们在新的和未来的模型上会是什么样的.

我的一位朋友说,处理UIImages的最佳方法是立即将它们保存到我应用程序文档目录中的JPEG文件中,并尽快释放原始的UIImage.所以这就是我一直在努力做的事情.不幸的是,即使将UIImage保存为JPEG并且在我的代码中没有引用它,它也不会被垃圾收集.

以下是我的代码的相关部分.我正在使用ARC.

// Entry point: UIImagePickerController delegate method-(voID) imagePickerController:(UIImagePickerController *)picker dIDFinishPickingMediawithInfo:(NSDictionary *)info {    // Process the image.  The method returns a pathname.    Nsstring* path = [self processImage:[info objectForKey:UIImagePickerControllerOriginalimage]];    // Add the image to the vIEw    [self addImage:path];}-(Nsstring*) processImage:(UIImage*)image {    // Get a @R_403_6852@ path    NSArray* paths = NSSearchPathForDirectorIEsInDomains(NSdocumentDirectory,NSUserDomainMask,YES);    Nsstring* documentsDirectory = [paths objectAtIndex:0];    Nsstring* @R_403_6852@name = [self makeImage@R_403_6852@name]; // implementation omitted    Nsstring* imagePath = [documentsDirectory stringByAppendingPathComponent:@R_403_6852@name];    // Get the image data (blocking; around 1 second)    NSData* imageData = UIImageJPEGRepresentation(image,0.1);    // Write the data to a @R_403_6852@    [imageData writeto@R_403_6852@:imagePath atomically:YES];    // Upload the image (non-blocking)    [self uploadImage:imageData with@R_403_6852@name:@R_403_6852@name];    return imagePath;}-(voID) uploadImage:(NSData*)imageData with@R_403_6852@name:(Nsstring*)@R_403_6852@name {    // this sends the upload job (implementation omitted) to a thread    // pool,which in this case is managed by PhoneGap    [self.commandDelegate runInBackground:^{        [self doUploadImage:imageData with@R_403_6852@name:@R_403_6852@name];    }];}-(voID) addImage:(Nsstring*)path {    // implementation omitted: make a UIImageVIEw (set bounds,etc).  Save it    // in the variable iv.    iv.image = [UIImage imageWithContentsOf@R_403_6852@:path];    [iv setNeedsdisplay];    NSLog(@"displaying image named %@",path);    self.imageCount++;}

注意processImage方法如何引用UIImage,但它只用于一件事:制作该图像的NSData *表示.因此,在processImage方法完成后,UIImage应该从内存中释放出来,对吧?

我该怎么做才能减少应用的内存使用量?

更新

我现在意识到分配探查器的屏幕截图有助于解释这个问题.

解决方法 您的processImage方法不是您的问题.

我们可以通过将其移植到Apple’s PhotoPicker demo app来测试您的图像保存代码

方便的是,Apple的示例项目与您的非常相似,有一种方法可以在计时器上重复拍摄照片.在示例中,图像不会保存到文件系统,而是累积在内存中.它伴随着这个警告:

/ *
     启动计时器每1.5秒拍摄一张照片.
注意:出于本样本的目的,我们将继续无限期拍照.
     请注意,我们会快速耗尽内存.您必须确定允许从相机拍摄的照片的正确阈值数量.
     避免内存限制的一种解决方案是将每张拍摄的照片保存到磁盘,而不是将所有照片保存在内存中.
     在内存不足的情况下,有时我们会调用“dIDReceiveMemoryWarning”方法,在这种情况下,我们可以恢复一些内存并保持应用程序运行.
     * /

将您的方法添加到Apple的代码中,我们可以解决此问题.

imagePicker委托方法如下所示:

- (voID)imagePickerController:(UIImagePickerController *)picker dIDFinishPickingMediawithInfo:(NSDictionary *)info{    UIImage *image = [info valueForKey:UIImagePickerControllerOriginalimage];    [self.capturedImages removeAllObjects];   // (1)    [self.imagePaths addobject:[self processImage:image]]; //(2)    [self.capturedImages addobject:image];    if ([self.cameraTimer isValID])    {        return;    }    [self finishAndUpdate]; //(3)}

(1) – 我们的补充,用于刷新每个图像捕获事件的实时内存
(2) – 我们的补充,将图像保存到文件系统并构建文件系统路径列表.
(3) – 对于我们的测试,我们使用cameraTimer来拍摄重复图像,因此不会调用finishAndUpdate.

我已经使用了您的processImage:方法,其中包含以下行:
[self uploadImage:imageData with@R_403_6852@name:@R_403_6852@name];
评论说.

我还添加了一个小的makeImage@R_403_6852@name方法:

static int imagename = 0;-(Nsstring*)makeImage@R_403_6852@name {    imagename++;    return [Nsstring stringWithFormat:@"%d.jpg",imagename];}

这些是我对Apple代码的唯一补充.

这是Apple原始代码的内存占用(cameraTimer不带(1)和(2))

在拍摄了约40张图像后,内存攀升至约140MB

这是添加的内存占用(cameraTimer与(1)和(2)一起运行)

文件存储方法正在解决内存问题:内存是平坦的,每个图像捕获的峰值大约为30MB.

这些测试是在iPhone5S上运行的.未压缩的图像为3264 x 2448 px,应为24mB(24位RGB). Jpeg压缩(文件系统)大小范围在250kB(0.1质量,根据您的代码)到1-2mB(0.7质量)高达~6mB(1.0质量).

在对您的问题的评论中,您建议重新加载的图像将受益于该压缩.情况并非如此:当图像加载到内存中时,必须先将其解压缩.它的内存占用量大约等于像素x颜色x每个颜色的位深度 – 无论图像存储在磁盘上的方式如何.正如jrturton所指出的那样,这至少表明你应该避免以比你需要的显示更高的分辨率加载图像.假设您有一个832 x 640的全屏(视网膜)imageVIEw,如果您的用户无法放大,则会浪费内存加载大于该值的图像.这是一个约1.6mB的实时内存占用,对您的24mMB原始内容有很大的改进(但这是你主要问题的题外话).

由于processImage似乎不是导致内存故障的原因,因此您应该考虑其他可能性:

1 /您没有内存问题.你是如何分析应用程序的?
2 / addImage或uploadImage之一是保留内存.尝试依次评论每个,以确定哪个.
3 /问题出在其他地方(由PhoneGap管理的事情?)

至于那些内存峰值,这些是由图像到数据jpeg压缩线引起的:
NSData * imageData = UIImageJPEGRepresentation(image,0.1);

在引擎盖下,即ImageIO,使用ImagePickerController时可能无法避免.请参阅此处:Most memory efficient way to save a photo to disk on iPhone?如果您切换到AVFoundation,您可以将图像作为未转换的NSData获取,这样您就可以避免尖峰.

总结

以上是内存溢出为你收集整理的ios – 使用UIImagePickerController减少内存使用量全部内容,希望文章能够帮你解决ios – 使用UIImagePickerController减少内存使用量所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1057393.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存