views:

181

answers:

2

If I'm writing drawing code in Core Graphics on Mac OS X or iPhone OS, I can set the active fill color to red by calling:

CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0); // RGB(1,0,0)

If I want 50% gray, I could call:

CGContextSetRGBFillColor(context, 0.5, 0.5, 0.5, 1.0); // RGB(0.5,0.5,0.5)

But for shades of gray it's tempting to make a shorter line and call:

CGContextSetGrayFillColor(context, 0.5, 1.0);

However, this function is NOT simply calling the RGB method with the intensity value copied three times; instead it is changing the context's color space from DeviceRGB to DeviceGray. The next call to an RGB method will switch it back.

I'm curious to know:

  • What's the penalty for switching color spaces?
  • Is there a penalty for drawing when your context's color space doesn't match your device's native color space? (i.e., drawing in DeviceGray versus DeviceRGB)

I'm asking out of technical curiosity, not a desire to prematurely optimize, so please keep your admonitions to a minimum, please.

A: 

I have been using both extensively in a similar manner and have noticed no penalty in terms of performance.

Nick Toumpelis
I imagine any difference in performance is below the threshold of "noticing".
benzado
Yes. However, the proper way is to run benchmarks if you think that there might be a performance penalty. From experience, I can tell you that only methods/properties that directly draw on the screen (or affect drawing) may have a penalty e.g. adjustsFontSizeToFitWidth. This may not always be apparent.
Nick Toumpelis
+2  A: 

Conceptually, there's a penalty, but in practice it's so miniscule as to be irrelevant; converting (e.g.) a shade of gray to an RGB triplet (plus alpha) is trivial arithmetic even with a custom colour space.

Colour spaces do have a penalty when you're drawing images, however, as it's more than a matter of a single conversion operation. Every pixel must be converted, and while there are optimizations that can be done here (e.g. CLUTs, Colour Look-Up Tables, are useful if the source image uses indexed colours) they don't tend to be useful in situations where you also find Quartz code.

You say you expect CGContextSetGrayFillColor() to change the colour space of the graphics context, but that isn't actually the case. Doing so would necessitate converting the contents of that graphics context to match the context's new colour space. Since it's far cheaper and simpler to convert the colour instead of the context's buffers (e.g. by making CGContextSetGrayFillColor() an under-the-covers wrapper around CGContextSetRGBFillColor()), such an expense is going to be avoided in any sensible implementation.

Jonathan Grynspan
The documentation [clearly states](http://developer.apple.com/iphone/library/documentation/GraphicsImaging/Reference/CGContext/Reference/reference.html#//apple_ref/c/func/CGContextSetRGBFillColor) that the `CGContextSet*Color()` functions change the context's color space. But I don't think that is the same as changing the color space of the buffer you are drawing into, though.
benzado
Jonathan Grynspan
(Or around `CGContextSetStrokeColor()` as appropriate. Ran out of room.)
Jonathan Grynspan