CGBitmapContextCreate on iPhone / iPad

I have a method that needs to be parsed through a bunch of large PNG images pixel by pixel (PNG - 600x600 pixels each). It seems to work fine on Simulator, but on the device (iPad) I get EXC_BAD_ACCESS in some copy function of the internal memory. Size seems to be the culprit, because if I try it on smaller images, everything seems to work. Here is a description of the meat associated with memory.

+ (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); 

When I run this on a bunch of images, it runs 12 times and then twitches, and on the simulator this is not a problem. Do you have any ideas?

+6
memory iphone ipad cgcontext
source share
8 answers

Running 12 times, and then the crash sounds like a lack of memory problem. It is possible that within CGContext creates several large auto-implemented structures. Since you do this in a loop, they are not freed, so you run out of memory and die.

I'm not sure how the Core Foundation deals with temporary objects. I don’t think CF objects have the autorelease equivalent, and the Core Graphics context almost certainly deals with CF objects, not NSObjects.

To reduce the memory junk in the code, I suggest reorganizing it to create an off-screen CGContext once before you start processing, and reusing it to process each image. Then release it when done. It will be faster anyway (since you do not allocate huge data structures on each pass through the loop.)

I will try this to fix your crash problem, and I'm sure it also makes your code much faster. Memory allocation is very slow compared to other operations, and you do some pretty large data structures for processing RGBA images with a resolution of 600x600 pixels.

+3
source share

Go to product β†’ Change schemes β†’ Enable zombie objects. Place a check mark in front of Enable Zombie objects. Now create and run it. This may give you a better and describe point for the EXC_BAD_ACCES error.

+3
source share

I was getting a similar crash on my iPad (iPhoneOS 3.2, of course) using CGImageCreate (). Seeing your difficulty, I gave me a hint. I solved the problem by combining my bytesPerRow with the next highest power of 2.

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

Let us know if your problem allows two-line alignment. You will need to select * rawData with the given size and pass bytesPerRowPower2 to CGBitmapContextCreate () ... The height does not need to be aligned.

0
source share

Perhaps CGImageGetBytesPerRow (the power of two sounds is excessive).

0
source share

I used the power of two aligned lines in an application that directly determined the size of the line as I was creating images programmatically. But I also recommend toastie to try CGImageGetBytesPerRow before trying my suggestion.

0
source share

Try to start the selection of tools when starting the application on the device, it is cold, "memory problem." If you are in a loop, create an automatic release pool inside this loop.

0
source share

Maybe replace

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

from

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

since ref color space might still be needed? Just a random guess ... And maybe even put this to release the context?

 // cleanup CGContextRelease(context); CGColorSpaceRelease(colorSpace); 
0
source share

I solved the problem by creating a square context (width = height). I had a 512x256 texture and it crashed every time I sent data to OpenGL. Now I allocate a 512x512 buffer, but STILL renders 512x256. Hope this helps.

0
source share

All Articles