我正在为iphone创建一个图像编辑应用程序。我想让用户从图片库中选择一个图像,编辑它(灰度,棕褐色等),如果可能的话,保存回文件系统。我已经完成了选择图像(最简单的事情,如你所知使用imagepicker)以及创建灰度图像。但是,我陷入了棕褐色。我不知道如何实现这一点。是否可以获取图像的每个像素的值,以便我们可以改变它以获得所需的效果。还是有任何其他可能的方法?请帮忙......
答案 0 :(得分:1)
Apple图像选择器代码很可能只保存RAM中图像的文件名和一些低分辨率渲染,直到用户选择图像的最后一刻。
当您要求图像的完整帧缓冲区时,CPU突然不得不在全分辨率解码图像时做更多的工作,但它可能甚至像触发它一样简单它关闭:
CFDataRef CopyImagePixels(CGImageRef inImage)
{
return CGDataProviderCopyData(CGImageGetDataProvider(inImage));
}
/* IN MAIN APPLICATION FLOW - but see EDIT 2 below */
const char* pixels = [[((NSData*)CopyImagePixels([myImage CGImage]))
autorelease] bytes]; /* N.B. returned pixel buffer would be read-only */
这只是猜测它是如何工作的,实际上,但是基于在其他环境中的图像处理的一些经验。要从内存使用的角度来判断我的建议是否有意义并且是好的,请运行Instruments。
Apple文档说(相关,可能适用于您):
您应该避免创建大小超过1024 x 1024的UIImage对象。除了这样的图像会占用大量内存之外,在OpenGL ES中将图像用作纹理或将图像绘制到视图或图层时,可能会遇到问题。如果您正在执行基于代码的操作,则此大小限制不适用,例如通过将大小超过1024 x 1024像素的图像绘制到位图支持的图形上下文来调整大小。实际上,您可能需要以这种方式调整图像大小(或将其分成几个较小的图像),以便将其绘制到您的一个视图中。 [http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIImage_Class/Reference/Reference.html]
和
注意:在iPhone OS 3.0之前,UIView实例的最大高度和宽度可能为1024 x 1024.在iPhone OS 3.0及更高版本中,视图不再受限于此最大大小,但仍受内存量的限制他们消耗。因此,保持视图尺寸尽可能小是符合您的最佳利益的。无论运行哪个版本的iPhone OS,如果需要创建大小超过1024 x 1024的视图,都应考虑使用CATiledLayer对象。 [http://developer.apple.com/iPhone/library/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html]
另外值得注意的是: -
(a)官方指导
http://developer.apple.com/iphone/library/qa/qa2007/qa1509.html
(b)来自http://cameras.about.com/od/cameraphonespdas/fr/apple-iphone.htm
“上传到您计算机的图片尺寸为1600x1200,但如果您直接从iPhone发送照片,则尺寸将缩小为640x480。”
(c)使用JPEG图像压缩对大图像进行编码需要大量RAM,具体取决于大小,可能比应用程序可用的量大。
(d)可以使用备用压缩算法(如果需要)将其malloc重新连接以使用临时内存映射文件。但请考虑数据隐私/安全问题。
(e)来自iPhone SDK: After a certain number of characters entered, the animation just won't load
“我认为它可能是一个图层大小的问题,因为iPhone的纹理大小限制为1024 x 1024(之后你需要使用CATiledLayer来支持你的UIView),但是我能够布置比1024像素仍然有这个功能。“
有时1024像素的限制可能看起来有点软,但我总是建议您进行防御性编程并保持在1024像素限制内。如果可以的话。
编辑1
在代码中添加了额外的换行符。
编辑2
糟糕!代码获取数据的只读副本(CFMutableDataRef和CFDataRef之间存在差异)。由于可用RAM的限制,您必须通过自己平滑缩放来制作它的低分辨率副本,或者将其复制到可修改的缓冲区中,如果图像很大,您可能需要在频段中编写它到临时文件,释放不可修改的数据块并从文件加载数据。当然,如果将数据放在这样的临时文件中是可以接受的,那么只能这样做。痛苦。
编辑3
这可能是一个更好的想法,也许可以尝试使用目标位图上下文,该上下文使用CFData块作为内存映射CFData。那样有用吗?如果您对通过临时文件传输的数据感到满意,请再次执行此操作。
编辑4
哦不,看来内存映射的读写CFData不可用。也许试试mmap BSD API。
编辑5
为代码添加了“const char *”和“pixel read-only”注释。