Artifacts in small textures on the iPhone
For the next version of Arctic Shuffle, we’re using Open GL to speed things up. One problem we’re run into along the way is strange artifacts in textures smaller than 64 pixels by 64 pixels. After a lot of head scratching, an obscure forum post saved the day. It turns out there’s a bug in Apple’s GLSprite sample code (where our texture loading code came from).
Here’s the important bit from our texture loading code:
if(image = [UIImage imageWithContentsOfFile:aPath].CGImage) {
width = CGImageGetWidth(image);
height = CGImageGetHeight(image);
data = (GLubyte *) malloc(width * height * 4);
context = CGBitmapContextCreate(data, width, height, 8, width * 4, CGImageGetColorSpace(image), kCGImageAlphaPremultipliedLast);
CGContextDrawImage(context, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), image);
CGContextRelease(context);
glGenTextures(1, &name);
free(data);
}
I have literally no idea how malloc works, but from what I gather it doesn’t clean out the memory that it allocates. For some reason, the memory allocated for textures smaller than 64 pixels by 64 pixels has a bunch of garbage in it, which shows up as artifacts in the texture. Switching from malloc to calloc, which explicitly sets all the bits in the allocated memory to zero got rid of the problem.
Here’s the working code:
if(image = [UIImage imageWithContentsOfFile:aPath].CGImage) {
width = CGImageGetWidth(image);
height = CGImageGetHeight(image);
data = (GLubyte *) calloc(width * height, 4);
context = CGBitmapContextCreate(data, width, height, 8, width * 4, CGImageGetColorSpace(image), kCGImageAlphaPremultipliedLast);
CGContextDrawImage(context, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), image);
CGContextRelease(context);
glGenTextures(1, &name);
free(data);
}
Happy texturing!
May 14th, 2009 at 6:45 pm
it’s true, malloc() does not clear memory it allocates, which makes me wonder how textures of any size work reliably with that code, if the image contains transparency. curious!