iOS性能调整:获取大图像像素颜色的最快方法

Way*_*man 11 performance core-graphics uiimage ios

关于如何获得给定点的图像的像素颜色存在许多问题/答案.但是,对于大型图像(例如,甚至小到1000 x 1300),所有这些答案都非常慢(100-500ms).

大多数代码示例都绘制到图像上下文.当实际抽签时,所有这些都需要时间:

CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage)
Run Code Online (Sandbox Code Playgroud)

在Instruments中对此进行检查后发现,通过从源图像复制数据来完成绘制:

在此输入图像描述

我甚至尝试过不同的方法来获取数据,希望自己获得字节实际上会更有效率.

NSInteger pointX = trunc(point.x);
NSInteger pointY = trunc(point.y);
CGImageRef cgImage = CGImageCreateWithImageInRect(self.CGImage, 
                           CGRectMake(pointX * self.scale, 
                                      pointY * self.scale, 
                                      1.0f, 
                                      1.0f));

CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
CFDataRef data = CGDataProviderCopyData(provider);

CGImageRelease(cgImage);

UInt8* buffer = (UInt8*)CFDataGetBytePtr(data);

CGFloat red   = (float)buffer[0] / 255.0f;
CGFloat green = (float)buffer[1] / 255.0f;
CGFloat blue  = (float)buffer[2] / 255.0f;
CGFloat alpha = (float)buffer[3] / 255.0f;

CFRelease(data);

UIColor *pixelColor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];

return pixelColor;
Run Code Online (Sandbox Code Playgroud)

此方法花费时间在数据副本上:

CFDataRef data = CGDataProviderCopyData(provider);
Run Code Online (Sandbox Code Playgroud)

它似乎也是从磁盘读取数据,而不是CGImage我正在创建的实例:

在此输入图像描述

现在,这种方法在一些非正式测试中确实表现得更好,但它仍然没有我想要的那么快. 有谁知道更快的获取基础像素数据的方法???

Bra*_*son 6

如果您可以通过OpenGL ES将此图像绘制到屏幕上,则可以通过该版本中引入的纹理缓存,对iOS 5.0中的基础像素进行极快的随机访问.它们允许直接存储器访问存储在OpenGL ES纹理中的底层BGRA像素数据(图像将驻留在其中),并且您几乎可以立即从该纹理中挑选出任何像素.

我用它来回读偶数大(2048x2048)图像的原始像素数据,读取时间最差的时间在10-20毫秒之间,以拉下所有这些像素.同样,随机访问单个像素几乎没有时间,因为您只是从字节数组中的某个位置读取.

当然,这意味着您必须解析并将您的特定图像上传到OpenGL ES,这将涉及从磁盘读取相同内容以及与Core Graphics的交互(如果通过UIImage),如果您尝试从磁盘上的随机PNG读取像素数据,但听起来你需要渲染一次并从中多次采样.如果是这样,OpenGL ES和iOS 5.0上的纹理缓存将是回读此像素数据的绝对最快的方式,也可以显示屏幕上显示的内容.

我将这些进程封装在我的开源GPUImage框架中的GPUImagePicture(图像上传)和GPUImageRawData(快速原始数据访问)类中,如果你想看看它是如何工作的.


hot*_*aw2 1

CGImage 上下文可能几乎是空的,并且不包含实际的像素数据,直到您尝试读取第一个像素或绘制它,因此尝试加快从图像中获取像素的速度可能不会有任何帮助。还没有什么可得到的。

您是否正在尝试从 PNG 文件读取像素?您可以尝试直接跟踪文件并映射它并自行解码 PNG 格式。从存储中提取数据仍需要一段时间。