How to Release a Cgimageref in iOS

How do I release a CGImageRef in iOS

Your memory issue results from the copied data, as others have stated. But here's another idea: Use Core Graphics's optimized pixel interpolation to calculate the average.

  1. Create a 1x1 bitmap context.
  2. Set the interpolation quality to medium (see later).
  3. Draw your image scaled down to exactly this one pixel.
  4. Read the RGB value from the context's buffer.
  5. (Release the context, of course.)

This might result in better performance because Core Graphics is highly optimized and might even use the GPU for the downscaling.

Testing showed that medium quality seems to interpolate pixels by taking the average of color values. That's what we want here.

Worth a try, at least.

Edit: OK, this idea seemed too interesting not to try. So here's an example project showing the difference. Below measurements were taken with the contained 512x512 test image, but you can change the image if you want.

It takes about 12.2 ms to calculate the average by iterating over all pixels in the image data. The draw-to-one-pixel approach takes 3 ms, so it's roughly 4 times faster. It seems to produce the same results when using kCGInterpolationQualityMedium.

I assume that the huge performance gain is a result from Quartz noticing that it does not have to decompress the JPEG fully but that it can use the lower frequency parts of the DCT only. That's an interesting optimization strategy when composing JPEG compressed pixels with a scale below 0.5. But I'm only guessing here.

Interestingly, when using your method, 70% of the time is spent in CGDataProviderCopyData and only 30% in the pixel data traversal. This hints to a lot of time spent in JPEG decompression.

Pixel Iterating Screenshot Draw-To-One-Pixel Screenshot

Note: Here's a late follow up on the example image above.

Releasing CGImage (CGImageRef)

Core Foundation objects (which all Core Graphics objects are) do support autorelease.

The steps you describe should work just fine and not leak or over-release the object.

I use CFRelease instead of specific-class release functions like CGImageRelease, but purely as a matter of style. I just have to beware of NULL: CGImageRelease checks for NULL, whereas CFRelease will crash when passed NULL. Using CGImageRelease and its siblings means you don't have to worry about this.

I'm assuming you meant removeObject:forKey:, not removeObject (which doesn't exist and wouldn't have somewhere to specify an object anyway).

How to release CGImageRef if required to return it?

The Cocoa memory management naming policy states, that you own an object that is created from methods whose name begin with alloc, copy or new.

This rules are also respected by the Clang Static Analyzer.

Note that there are slightly different conventions for Core Foundation. Details can be found in Apple's Advanced Memory Management Programming Guide.

I modified your above method to conform to that naming conventions. I also removed the asterisk when passing in anImage, as CGImageRef is already a pointer. (Or was this on purpose?).

Note that you own the returned CGImage and have to CGImageRelease it later.

-(CGImageRef)newResizedImageWithImage:(CGImageRef)anImage width:(CGFloat)width height:(CGFloat)height
{
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(anImage);
if (alphaInfo == kCGImageAlphaNone)
{
alphaInfo = kCGImageAlphaNoneSkipLast;
}
CGContextRef bitmap = CGBitmapContextCreate(NULL, width, height, CGImageGetBitsPerComponent(anImage), 4 * width, CGImageGetColorSpace(anImage), alphaInfo);
CGContextDrawImage(bitmap, CGRectMake(0, 0, width, height), anImage);
CGImageRef image = CGBitmapContextCreateImage(bitmap);
CGContextRelease(bitmap);
return image;
}

When is it appropriate to release CGImageRef?

UIImageView retains the image property (if it needs it) or it copies it - whatever. Once you have set that property, you can then immediately release the CGImageRef.

How do I release a CGDataProvider in Swift on iOS?

You don't have to release it. The documentation is still targeted towards Objective-C. The compiler error message is correct.

From Using Swift with Cocoa and Objective-C:

Core Foundation objects returned from annotated APIs are automatically memory managed in Swift—you do not need to invoke the CFRetain, CFRelease, or CFAutorelease functions yourself.

Need to release a CGImage contained in a CALayer's contents property

The contents property on CALayer is a retaining property, meaning that it's setter implementation more or less does this:

- (void)setContents:(id)contents
{
if (contents == _contents) return; // Same as existing value
[_contents release];
_contents = [contents retain];
}

So, when you set nil as the new contents, the old contents is released.



Related Topics



Leave a reply



Submit