Modern-day color spaces
Modern-day color spaces
- Subject: Modern-day color spaces
- From: Kyle Sluder <email@hidden>
- Date: Tue, 18 Dec 2012 22:59:53 -0800
I'm trying to piece together the truth about color spaces on OS X 10.7
and 10.8. There's so much documentation of varying age that I'm not sure
what's correct anymore.
My current understanding is this:
Since 10.4, Quartz does not support the concept of a device color space
_at all_. That is to say, you cannot create a bitmap context and assign
a color space such that drawing RGB(128,0,0) is guaranteed to feed
RGB(128,0,0) to the graphics hardware.
If you continue to ask for a Device color space, Quartz will instead
give you a "Generic" color space. The generic color space is described
in QA 1396 and an email to the quartz-dev mailing list [1] as an
ICC-based color profile that represents the "gold standard" to which
Apple monitors strived in 2005, the definition of which lives at
'/System/Library/ColorSync/Profiles/Generic <Color Space Model>.icc'.
When 10.6 came around, the definition of the Generic RGB color space
(and thus the profile at …/Generic RGB.icc) was updated with a gamma of
2.2 instead of 1.8.
That thread recommends using CGLayerRefs for offscreen drawing, since
you don't have to specify its color space. But we know that CGLayerRefs
are almost entirely useless. [2] I assume creating a CGLayerRef from a
graphics context just uses whatever color space the graphics context
uses, so it would not have been wise to create a CGLayerRef hang onto it
forever, given that the color space of the device context can change.
So the best approach for caching offscreen drawing using Quartz nowadays
is to draw into a CGBitmapContext with a Generic color space, and then
draw that bitmap into your destination context when needed, at which
point Quartz will perform color conversion into the window's color
space. This means that unlike a CGLayerRef, you can create the bitmap
once and stamp it into whatever context you want, and you should get the
same appearance in all places.
There's one unresolved inconsistency: the docs for CGImageCreateWithMask
say:
"""If the mask is an image, it must be in the DeviceGray color space,
must not have an alpha component, and may not itself be masked by an
image mask or a masking color."""
I guess this just some documentation that hasn't been updated since
device color spaces were deprecated.
Enter Cocoa.
The AppKit release notes for 10.4 say the following: [3]
"""Calibrated NSColors (those created with colorWithCalibratedRed:..,
colorWithCalibratedHue:.., or colorWithCalibratedWhite:...) now use
Quartz generic color spaces, rather than the "display" (aka "device")
color spaces. For debugging purposes this behavior can be disabled with
the NSUseGenericColorSpaceForCalibrated default. This is a debugging
default and will be removed in a future update.
In applications, the proper way to get the device color space behavior
is to create colors with colorWithDeviceRed:...,
colorWithDeviceWhite:..., etc.
In many cases, as appropriate, the underlying color for NSColors
representing colors used in the user interface (for instance, methods
such as -[NSColor alternateSelectedControlColor]) has been changed to
device color space."""
I'm trying to rectify this with my understanding of the situation as it
pertains to Quartz.
I suppose the implication of the first paragraph was that in 10.3 and
earlier +colorWithCalibrated{Blah} actually invoked ColorSync to
calculate the calibrated colors for the specific output device. Since
10.4, the named color space NSCalibrated<Model>ColorSpace maps to
kCGColorSpaceGeneric<Model>.
The second paragraph still baffles me. So +colorWithDevice{Blah}:… is
somehow able to give me a color in device color space, despite Quartz
not supporting that concept? Or does it just pick a specific device at
the time of the cal and use that device's ICC-based color space? Or does
AppKit drawing do something like reinterpret the color values of an
NSDevice<Model>ColorSpace as values in the color space of the current
NSGraphicsContext?
Finally, the AppKit release notes for 10.7 [3] say this:
"""NSColor now has two class methods to enable creating colors with sRGB
or its gray counterpart color spaces. These create colors with
colorSpaceName = NSCustomColorSpace and the appropriate color space
(+[NSColorSpace sRGBColorSpace] or +[NSColorSpace
genericGamma22GrayColorSpace]).
These days the sRGB color space is a better match to the default Mac
display environment than the calibrated color space. For this reason in
general we recommend using sRGB color space for your images and in your
colors—this can lead to better fidelity and performance."""
The implication here is that Apple's recent display hardware is
targeting the sRGB gamut. How does this relate to, say, choosing color
constants for UI?
--Kyle Sluder
[1] http://lists.apple.com/archives/quartz-dev/2005/May/msg00110.html
[2]
http://blog.metaobject.com/2012/11/cglayer-performance-and-quality.html
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden