IPhone - CGBitmapContextCreateImage Leak, anyone else with this problem?
Does anyone else have this problem? I change images quite often with NSTimer. After using the tools, it doesn't detect any memory leaks, but my alloc object just keeps growing. It points directly to the CGBitmapContextCreateImage.
Does anyone know of a solution? or even possible ideas?
-(UIImage *) resizedImage:(UIImage *)inImage : (CGRect)thumbRect : (double)interpolationQuality
{
CGImageRef imageRef = [inImage CGImage];
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef);
if (alphaInfo == kCGImageAlphaNone)
alphaInfo = kCGImageAlphaNoneSkipLast;
// Build a bitmap context that the size of the thumbRect
CGContextRef bitmap = CGBitmapContextCreate(
NULL,
thumbRect.size.width,
thumbRect.size.height,
CGImageGetBitsPerComponent(imageRef),
4 * thumbRect.size.width,
CGImageGetColorSpace(imageRef),
alphaInfo
);
// Draw into the context, this scales the image
CGContextSetInterpolationQuality(bitmap, interpolationQuality);
CGContextDrawImage(bitmap, thumbRect, imageRef);
// Get an image from the context and a UIImage
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage* result = [UIImage imageWithCGImage:ref];
CGContextRelease(bitmap); // ok if NULL
CGImageRelease(ref);
return [result autorelease];
}
Should you be releasing imageRef?
CGImageRelease(imageRef);
Just a sanity check: are you freeing the returned UIImage? Normally I would expect a function that allocates a new object (in this case UIImage) to create in the name?
You might want
return [result autorelease]
?
Why not use a simpler one UIGraphicsBeginImageContext
?
@implementation UIImage(ResizeExtension)
- (UIImage *)resizedImageWithSize:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)interpolationQuality;
@end
@implementation UIImage(ResizeExtension)
- (UIImage *)resizedImageWithSize:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)interpolationQuality
{
UIGraphicsBeginImageContext(newSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetInterpolationQuality(context, interpolationQuality);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
@end
Moreover, this returns the image saved by the current autocomplete pool; if you create many of these images in a loop, manually select and delete NSAutoreleasePool
.
Ok, the problem is that we are defining the return from CGBitmapContextCreateImage to be CGImageRef, it should be CGImage. The reason your allocations (im assuming malloc) keep increasing is because the CGImage itself is never freed. Try the below code. Also, there is no need to automatically evaluate the result as it is never "Alloc'd".
Once the changes are made to the reassigned installations, this time you hopefully won't see a constant increase in bytes in real time.
I typed this on PC so it might get a syntax error if you put it in Xcode; however this should do the trick.
// Get an image from the context and a UIImage
CGImage cgImage = CGBitmapContextCreateImage(bitmap);
UIImage* result = [UIImage imageWithCGImage:cgImage];
CGContextRelease(bitmap); // ok if NULL
CGImageRelease(cgImage);
return result;
If you are using garbage collection use CFMakeCollectable (posterFrame). If you are using traditional memory management it is very simple:
return (CGImageRef)[(id)posterFrame autorelease];
You pass a CFTypeRef (in this case, CGImageRef) to an Objective-C object pointer, send the -autorelease message, and then feed the result back to CGImageRef. This pattern works for almost any type that is compatible with CFRetain () and CFRelease ().