A set of RGB values does not really describe a color. It only tells your graphics adapter how much percentage of red, green and blue light you want in that color, but a color like 50% pure red is not the same color on all monitors for two reasons:
50% is not the same relative brightness on all monitors because of slightly different gamma curves (it's not the same absolute brightness either because of different backlight brightness, but that's actually irrelevant - only relative values are important)
Even 100% red isn't the same red tone as monitors have different "shades" of red, depending on their backlight color and their color filters.
So the same combination of RGB may look different on different monitors. Being a nice orange on your monitor, it could look like a very bright red on some and like a dark yellow on other monitors. It's the same RGB values everywhere but not the same color.
To make RGB describe a "color", it needs also a color space, that defines a space of colors where the RGB values are like coordinates into that space and thus describe an exact color.
(The original uploader was Cpesacreta at English Wikipedia - Transferred from en.wikipedia to Commons by aboalbiss.)
If you use colorWithDeviceRed:green:blue:alpha:
, RGB values are not transformed, they are reported exactly like this to your graphics adapter. Thus the color will really have these RGB values, but the results that the user sees on screen will vary from screen to screen.
If you use colorWithSRGBRed:green:blue:alpha:
, the RGB values are interpreted as RGB values of the sRGB color space. The system knows that space and thus it knows what color is described here. If the system also knows the color space of your monitor (e.g. because it has been calibrated at the factory or by the users using a calibration tool), then it can transform the RGB values from the sRGB color space to the native color space of your monitor. This transformation will change the absolute RGB values on their way to your monitor. You may have used #758299
and the monitor will actually display #7483A1
but that's because the color #7483A1
looks exactly like the sRGB color #758299
on this display, so the user sees the expected correct color (even though it may not have the same RGB values - but users don't see RGB values, they see colors).
sRGB is a very popular color space, it's the most compatible one, most graphic apps and system know about it and you can expect that every modern display is able to correctly display pretty much all existing sRGB color. But it's also a very limited color space. sRGB is only a subset of all the colors that most devices can display as of today and it also doesn't offer 16.7 million different colors (even though there are that many possible RGB combinations). That's why there exists wider color spaces, like the one from Adobe that you find in all Adobe graphic apps. Apple offers a color space named the "calibrated color space" - sometimes also called the "generic color space". You use it with colorWithCalibratedRed:green:blue:alpha:
and from what I can find in the documentation, this is basically the HSB color space, that is wider than sRGB (internally it stores colors in a different format but there is a fixed, device neutral formula to convert RBG to HSB and HSB back to to RGB).
So if color correctness is important to you (the user shall see the same color you are seeing on your screen, regardless what RGB values are required to achieve that), you should always specify colors in combination with a color space. Whether you use sRGB or Generic/Calibrated doesn't matter, just use the same one throughout your entire app.
If you use a tool that reports colors in sRGB then the hex values only match that space. Note that all web standards use sRGB colors implicitly. So when you use hex colors in HTML or CSS files, those are always interpreted as sRGB values. Also when you receive colors from an external source and this source does not tell you what colorspace they belong to, it's always safest to assume sRGB.
If you read colors from your screen using the color picker of the Digital Color Meter app (that always comes with MacOS), be sure to choose Display in Generic RGB or Display in sRGB but don't use Display native values if you plan to use these values in apps or on web sites. Native values is only what your system really uses to display that color but this combination only looks that way on your system.
Of course, none of this can work if your display is not correctly calibrated. Modern displays have an embedded calibration profile computers can download and mobile devices have their calibration stored on the device as well. If you have an older monitor or if you think the profile is not accurate (or not accurate anymore because of display aging!), you need to get display calibration hardware and use a tool like DisplayCAL to generated a better profile (free, OpenSource, all major platforms, supports a wide range of USB hardware)
A common question is, what does actually happen, if I interpret RGB values according to the wrong color space? Well, it won't look totally wrong. If you display an image of a smaller color space as if it was from a bigger one, then the image will look very "vibrant" (all colors have a lot saturation, contrasts will be enhanced, crispness will be enhanced), if its the other way round, the image will look rather "mute" (colors will have a lot less saturation, contrast we be decreased, crispness will be decreased). See this example: The image has normal color space and is displayed with the correct color space on the right, on the left it is displayed in a wide color space, treating the image RGB values as if they would belong to that wide color space, which they in fact are not, hence the exaggerated vibrancy:
colorWithCalibratedRed
andcolorWithDeviceRed
, but what ofcolorWithSRGBRed
? – Vowel