iPhone / iPad上的CGBitmapContextCreate

时间:2010-04-12 00:07:21

标签: iphone memory ipad cgcontext

我有一种方法需要逐像素地解析一堆大的PNG图像(PNG每个600x600像素)。它似乎在模拟器上运行良好,但在设备(iPad)上,我在某些内部存储器复制功能中获得了EXC_BAD_ACCESS。看起来大小是罪魁祸首,因为如果我在较小的图像上尝试它,一切似乎都有效。以下是与方法有关的内容。

+ (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次然后缩小,而在模拟器上它运行没有问题。你们有什么想法吗?

7 个答案:

答案 0 :(得分:3)

运行12次然后崩溃的声音就像是内存不足问题。可能是CGContext内部正在创建一些大的自动释放结构。因为你在循环中这样做,所以它们没有被释放,所以你的内存耗尽而死。

我不确定Core Foundation如何处理临时对象。我不认为CF对象具有相当于自动释放的功能,而Core Graphics上下文几乎肯定会处理CF对象而不是NSObjects。

为了减少代码中的内存流失,我建议在开始处理之前重构一次以创建一个屏幕外CGContext,并重复使用它来处理每个图像。完成后释放它。在任何情况下都会更快(因为你没有在每次循环中分配大量的数据结构。)

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

答案 1 :(得分:3)

转到产品 - >编辑方案 - >启用Zombie对象。在启用Zombie对象之前勾选一个刻度线。现在构建并运行它。它可以为您提供更好的EXC_BAD_ACCES错误的点描述。

答案 2 :(得分:0)

我使用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()...高度似乎不需要对齐。

答案 3 :(得分:0)

也许CGImageGetBytesPerRow(两个声音的声音过大)。

答案 4 :(得分:0)

我在直接定义行大小的应用中使用了两个对齐行大小的功能,因为我是以编程方式创建图像。但我也建议toastie尝试CGImageGetBytesPerRow,然后再尝试我的建议。

答案 5 :(得分:0)

也许替换

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

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

因为可能仍然需要某种颜色空间参考?随便猜一下...... 甚至可能把它放在上下文的发布之后?

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

答案 6 :(得分:0)

我通过制作正方形上下文(width = height)来解决问题。我的纹理是512x256,每次将数据发送到OpenGL时都会崩溃。现在我分配一个512x512缓冲区但仍然呈现512x256。希望这会有所帮助。