在iPhone/iPad上创建CGBitmapContextCreate

在iPhone/iPad上创建CGBitmapContextCreate,iphone,memory,ipad,cgcontext,Iphone,Memory,Ipad,Cgcontext,我有一个方法,需要逐像素解析一堆大的PNG图像(每个PNG为600x600像素)。它在模拟器上似乎工作得很好,但在设备(iPad)上,我在一些内存复制功能中获得了EXC_BAD_访问。它的大小似乎是罪魁祸首,因为如果我在较小的图像上尝试它,一切似乎都正常。下面是与记忆相关的方法 + (CGRect) getAlphaBoundsForUImage: (UIImage*) image { CGImageRef imageRef = [image CGImage]; NSUInt

我有一个方法,需要逐像素解析一堆大的PNG图像(每个PNG为600x600像素)。它在模拟器上似乎工作得很好,但在设备(iPad)上,我在一些内存复制功能中获得了EXC_BAD_访问。它的大小似乎是罪魁祸首,因为如果我在较小的图像上尝试它,一切似乎都正常。下面是与记忆相关的方法

+ (CGRect) getAlphaBoundsForUImage: (UIImage*) image 
{    
    CGImageRef imageRef = [image CGImage];

NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

unsigned char *rawData = malloc(height * width * 4);
memset(rawData,0,height * width * 4);

NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGColorSpaceRelease(colorSpace);

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);

/* non-memory related stuff */

free(rawData);

当我在一堆图像上运行它时,它运行了12次,然后退出,而在模拟器上运行没有问题。你们有什么想法吗?

我用CGImageCreate()在我的iPad(当然是iPhoneOS 3.2)上遇到了类似的崩溃。看到你的困难给了我一个暗示。我通过将我的bytesPerRow与下一个最大的2次方对齐,解决了这个问题

size_t bytesPerRowPower2=(size_t)round(pow(2.0,trunc(log((double)bytesPerRow)/log(2.0))+1.0))


让我们知道,如果提供2行对齐功能也能解决您的问题。您需要分配调整大小的*rawData,并将bytesPerRowPower2传递给CGBitmapContextCreate()。。。高度似乎不需要对齐。

可能是CGImageGetBytesPerRow(两个的幂听起来太大了)。

我在一个应用程序中使用了两个对齐行大小的幂,该应用程序直接定义行大小,因为我是通过编程创建图像的。但我也建议您在尝试我的建议之前先尝试一下CGImageGetBytesPerRow。

运行12次,然后崩溃听起来像是内存不足的问题。可能是CGContext在内部创建了一些大型的自动释放结构。由于您在循环中执行此操作,因此它们不会被释放,因此您会耗尽内存并死亡

我不知道核心基金会如何处理临时对象。我认为CF对象没有autorelease的等价物,核心图形上下文几乎肯定是处理CF对象而不是NSObject

为了减少代码中的内存波动,我建议在开始处理之前重构代码,创建一个屏幕外的CGContext,并重复使用它来处理每个图像。然后在完成后释放它。这在任何情况下都会更快(因为您不会在循环的每次传递上分配巨大的数据结构)


我敢打赌,这将消除您的崩溃问题,我敢打赌,这也会使您的代码更快、更快。与其他操作相比,内存分配速度非常慢,您需要使用一些相当大的数据结构来处理600x600像素的RGBA图像。

在设备上运行应用程序时,尝试运行instruments allocation,这可能是内存相关的问题。如果您处于循环中,请在该循环中创建一个自动释放池。

转到产品->编辑方案->启用僵尸对象。在启用僵尸对象之前打勾。现在构建并运行它。它可以为您提供更好、切中要害的EXC\u BAD\u ACCES错误描述。

可能会替换

CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

因为颜色空间ref可能还是需要的?只是一个随机猜测。。。 甚至可能把它放在背景发布的后面

// cleanup
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);

我通过创建一个正方形上下文(宽度=高度)解决了这个问题。我有一个512x256纹理,每次我将数据发送到OpenGL时它都会崩溃。现在我分配了一个512x512缓冲区,但仍然渲染512x256。希望这有帮助

// cleanup
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);