views:

618

answers:

2

Has anyone else come across this problem? ObjectAlloc climbs as a result of the CGBitmapContextCreateImage. Does Apple's software not fully releasing the objectalloc?

I am resizing images 12 times a second with a NSTimer. During resizing of the image I am also adding a photoshop like Gaussian blur effect by including interpolationQuality.

After using Instruments it does not show any memory leaks but my objectalloc just continues to climb. It points directly to CGBitmapContextCreateImage.
CGBitmapContextCreateImage > create_ bitmap_ data_provide > malloc

Anyone know of a solution? or Even possible ideas?

The Call within the NSTimer

NSString * fileLocation = [[NSBundle mainBundle] pathForResource:imgMain ofType:@"jpg"];
NSData * imageData = [NSData dataWithContentsOfFile:fileLocation];
UIImage * blurMe = [UIImage imageWithData:imageData];

CGRect rect = CGRectMake(0, 0, round(blurMe.size.width /dblBlurLevel), round(blurMe.size.width /dblBlurLevel)); 
UIImage * imageShrink = [self resizedImage: blurMe : rect : 3.0];   

CGRect rect2 = CGRectMake(0, 0, blurMe.size.width , blurMe.size.width ); 
UIImage * imageReize = [self resizedImage: imageShrink : rect2 : 3.0];

imgView.image = imageReize;

The Resize Function

-(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's 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];
}
A: 

That code overreleases result.

That said, it's likely that the issue is that the UIImage is not getting deallocated, and the UIImage is holding onto the CGImage, and the CGImage is holding onto the memory that was allocated under CGBitmapContextCreate.

Use instruments to see if UIImages are not getting deallocated, and if so try to debug why.

Ken
To make sure that I don't overrelease the result can I just replace.... return [result autorelease] with return result; ....if that is the case then that doesn't fix it either. My original code had it this way, someone gave the advice of adding the autorelease. This CGBitmapContextCreateImage > create_bitmap_data_provide > malloc, is driving me crazy.
bbullis21
The overrelease is not the problem, it's something else that's wrong.It's the rest of my comment that's relevant. Check if you're leaking UIImages.
Ken
bbullis21
A: 

I compiled and ran your code as you have it and I don't see any leaks nor does my object alloc keep climbing. I run the code a couple of times a second and don't see any object growth in Instruments. I am only running on the simulator. I also tried a kCGInterpolationNone instead of 3.0 in case that is the problem, and still no leak.

Not sure why I don't get them and you do. You might want to just do this in the method:

-(UIImage *) resizedImage:(UIImage *)inImage : (CGRect)thumbRect : (double)interpolationQuality
{
    CGImageRef                  imageRef = [inImage CGImage];
    CGImageAlphaInfo    alphaInfo = CGImageGetAlphaInfo(imageRef);

    return inImage;
...

In order to make this method be meaningless and then watch to see if the object alloc continues to grow. If so, then the problem is elsewhere.

mahboudz
I gave this a try and still same result. The ObjectAlloc build up still is pointing to CGBitmapContextCreateImage call. Thanks though. Third day in a row I have been pulling my hair out over this.
bbullis21
Try this: instead of providing NULL to CGBitmapCreateContext, pass it bmapPtr = malloc(height*4*thumbRect.size.width); Don't forget to free(bmapPtr) at the end of the method.
mahboudz
is bmapPtr an int? I am not sure what to declare it as?
bbullis21
I declared it as a void * bmapPtr like the class reference file said. It just caused the image to freeze and crashed.
bbullis21
No, you never release something that you got with a get method.[Memory rules for CoreFoundation][1].[1]: http://developer.apple.com/mac/library/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html#//apple_ref/doc/uid/20001148-CJBEJBHH
Ken
Those docs are saying that if you want to keep it around, you'd have to retain it. It would have been better not to say anything here; it's the usual rule.
Ken