I wanted to easily blend a UIImage on top of another background image, so wrote a category method for UIImage, adapted from http://stackoverflow.com/questions/1309757/blend-two-uiimages :
- (UIImage *) blendedImageOn:(UIImage *) backgroundImage {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
UIGraphicsBeginImageContext(backgroundImage.size);
CGRect rect = CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height);
[backgroundImage drawInRect:rect];
[self drawInRect:rect];
UIImage* blendedImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
UIGraphicsEndImageContext();
[pool release];
return [blendedImage autorelease];
}
Unfortunately my app that uses the above method to load around 20 images and blend them with background and gloss images (so probably around 40 calls), is being jettisoned on the device.
An Instruments session revealed that calls to malloc stemming from the calls to drawInRect: are responsible for the bulk of the memory usage. I tried replacing the drawInRect: messages with equivalent function calls to the function CGContextDrawImage but it didn't help. The AutoReleasePool was added after I found the memory usage problem; it also didn't make a difference.
I'm thinking this is probably because I'm not using graphics contexts appropriately. Would calling the above method in a loop be a bad idea because of the number of contexts I create? Or did I simply miss something?
- Edit 1: thanks for the comments. The method is invoked in a controller method that sets up 20 views, so in a loop I have the following call:
UIImage *blendedImage = [newImage blendedImageOn:backgroundImage];
I added the autorelease pool to make sure the images are released before the main autorelease pool will release them, so theoretically all of the new UIImages objects should be released when the loop has finished. The profiling results don't show any difference whether the autorelease pool is in there or not.
- Edit 2: And yes, I've tried adding an autorelease pool before the call to blendedImageOn: as well, to no effect.
- Edit 3: fixed embarrassing bug of UIImage being released because of the autorelease pool. The intention of the autorelease pool is to release any objects other than the result UIImage, in case the excessive memory is due to temporary objects added to the main autorelease pool which are not freed immediately.
The question I was trying to ask (very badly, I admit!) is: why does calling this method 20 times result in a lot of memory usage?