Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the result of CGImageGetColorSpace(image) have to be released?

I'm scaling a CGImageRef. I found various code examples on the web that begin like so:

CGColorSpaceRef colorspace = CGImageGetColorSpace(image); // "Get" color space

CGContextRef context = CGBitmapContextCreate(NULL, width, height,
    CGImageGetBitsPerComponent(image),
    CGImageGetBytesPerRow(image),
    colorspace,
    CGImageGetAlphaInfo(image));

CGColorSpaceRelease(colorspace); // Really?

As you can see above, the colorspace is released. However, when I do that my code works most of the time, but crashes once in a while, because sometimes that colorspace instance is already gone. The API docs say:

You are responsible for retaining and releasing the color space as necessary.

Does that mean I must release it? I assumed the convention was that only results of calls with "Create" in the name return objects that have to be released explicitly. Does this mean the examples on the web are simply wrong when releasing that CGColorSpaceRef?

like image 688
Mark Avatar asked Mar 11 '11 06:03

Mark


5 Answers

As the API docs say, you are responsible for retaining and releasing the color space as necessary. I.e. if you need, retain it. If you do not retain, don't release. Read more about it here

like image 143
Qiau Avatar answered Nov 05 '22 14:11

Qiau


Note that it seems possible to get a crash from releasing the colorspace object. I did some digging, but was unable to ascertain the root cause of the crash.

We have an app that was reading fields from the colorspace of each bitmap it dealt with and would call [UIImage imageName] followed by CGImageGetColorSpace followed by CGColorSpaceRelease. And in a certain scenerio, it would do this multiple times in a row for the same image. Non-deterministically, this would sometimes crash with the following error during the CGColorSpaceRelease:

Assertion failed: (!state->is_singleton), function color_space_state_dealloc, file ColorSpaces/CGColorSpace.c, line 127.

This was on iOS5 on both the ipad and the sim.

I know, this is the worst kind of bug report, but hey, if you run into the same issue and start pulling your hair out (we did), then perhaps this can serve as confirmation that you aren't the only person to ever hit this behavior.

This bug: "random crash while running WebGL conformance tests" seems like it might be the same issue. Or this one.

Our workaround was to stop reading the colorspace data. Still not quite sure what was going wrong. Sorry, wish I could give more info

--- Dave

p.s., http://xkcd.com/979/, and sorry for the "here be dragons" post. :)

like image 24
Dave Dopson Avatar answered Nov 05 '22 15:11

Dave Dopson


The same problem used to happen to me. I found out, that in my case the problem was the releasing the following ColorSpace:

CGColorSpaceRef colorSpace = CGImageGetColorSpace(pic.CGImage);

After i changed that line to:

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

everything worked as before, except of the error :)

like image 3
A lucky man Avatar answered Nov 05 '22 14:11

A lucky man


The rule for managing CoreFoundation objects lifetimes and other objects like them e.g., CoreGraphic objects is that if you have obtained the object using a function that has Create or Copy in its name then you need to use the appropriate release method when you have finished with the object.

Since the code in the original question shows that the CoreGraphics object was obtained using a method with Get in its name and not Create or Copy then you should NOT release the object after using it. If you do release you should expect to get crashes.

like image 3
SheffieldKevin Avatar answered Nov 05 '22 16:11

SheffieldKevin


Yes, you have to.

The returned CGColorSpaceRef from CGImageGetColorSpace is not retained, as its "Get" in the name implies. And it's your call will you then call CGColorSpaceRetain(colorSpace) or not.

However, I strongly urge you to do that (and later release, of course) if you intend to do anything useful with that color space (say create a gradient or something). If you do not, you will invite yourself to a nightmare of random crashes in various CG functions.

If you need some CG object to be passed to some other functions, always make sure it's retained. Always.

like image 1
Aleksandar Vacić Avatar answered Nov 05 '22 16:11

Aleksandar Vacić