2010-04-12 78 views
6

我有一个方法,需要解析通过一堆大PNG图像逐像素(每个PNGs是600x600像素)。它似乎在模拟器上效果很好,但在设备(iPad)上,我在某些内部存储器复制功能中获得了EXC_BAD_ACCESS。看起来大小是罪魁祸首,因为如果我在较小的图像上尝试它,一切似乎都奏效。下面的方法是记忆相关的肉类。CGBitmapContextCreate在iPhone/iPad上

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

回答

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

0

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

0

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

3

运行12次,然后崩溃听起来像内存不足的问题。 CGContext可能在内部创建一些大的自动发布结构。既然你是在循环中这样做,他们不会被释放,所以你用尽了内存并死亡。

我不确定Core Foundation如何处理临时对象。我不认为CF对象具有autorelease等价物,而Core Graphics上下文几乎可以肯定地处理CF对象而不是NSObject。

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

我会下注以消除您的崩溃问题,我敢打赌它也会让您的代码更快,更快。与其他操作相比,内存分配速度非常缓慢,而且您正在使用一些相当大的数据结构来处理600x600像素的RGBA图像。

0

尝试在设备上运行应用程序时运行乐器分配时,它会变成与内存相关的问题。如果您处于循环中,则在该循环内创建一个自动释放池。

3

转到产品 - >编辑方案 - >启用僵尸对象。在启用僵尸对象之前放置一个勾号。现在建立并运行它。它可以更好地为您提供EXC_BAD_ACCES错误的点描述。

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); 
0

我通过创建一个正方形上下文(width = height)来解决问题。每次我将数据发送到OpenGL时,我的纹理都是512x256,并且会崩溃。现在我分配一个512x512缓冲区但静止渲染512x256。希望这可以帮助。

相关问题