ICC's D50 vs sRGB D65 problems


I read this article “The Luminance of an sRGB Color”


However, there is something I don’t get.

XYZ is an absolute color space. Correct right?

sRGB is also an absolute color space, because it is specified according to specific physical hardware. Again correct, right?

An absolute color space does not depend on a whitepoint, correct?

So if sRGB is an absolute color space, and XYZ is an absolute color space, there should be exaclty one way to transform sRGB to XYZ. One particular 3x3 matrix.

However, ICC profiles operate in D50, and the red/green/blue chromaticities of sRGB in an ICC profile are given as different xyY coordinates than they are in other contexts!

What’s happening here? This is the part that I don’t get. XYZ (and xyY of course) are absolute spaces, and so is sRGB, so I would exact there to be one single well defined value for the red/green/blue chromaticities of sRGB.

How come ICC has different ones? Why does D50 matter?

For XYZ, D50 should not matter: it’s an absolute color space.
For sRGB, D50 does not matter, its whitepoint is D65.

So how can the fact that ICC uses D50 influence sRGB or its chromaticity coordinates at all?

What am I missing? All info appreciated!

My main issue, by the way, is that the RGB/XYZ Matrices from http://www.brucelindbloom.com/ are not working for me when computing from ICC.
ICC gives me a red, green, blue and white point. But plugging these in the brucelindbloom formula gives a different matrix, and the reason is exactly that those red/green/blue chromaticities seem to be given in a different way. What’s going on here? How can there be different coordinates for red/green/blue chromaticities in xyY if xyY is an absolute color space? How should I correctly interpret the red/green/blue chromaticity values in an ICC profile and get colors from it in an absolute color space (which by definition does not depend on a whitepoint)?

So the formula on brucelindbloom, as far as I know, tells how to create a matrix to convert unambiguously from the one absolute sRGB color space to the one absolute XYZ color space, with the chromaticities of sRGB space given unambiguously in the one xyY color space.

So is ICC using a different xyY color space with its D50 whitepoint, since its giving those absolute sRGB chromaticities with different numerical coordinates? How can that be possible, there is only one absolute xyY/XYZ color space.

Thank you

@color Welcome to the forum! I won’t be the best person to clarify this for you; I will let someone else more fluent than I. If you would like a response from @Elle herself, please send her an email. It should be “ellestone (at) ninedegreesbelow (dot) com”.

1 Like

XYZ is an absolute colour space, yes.

sRGB is defined with a D65 white point (WP), but not with a particular chromatic adaptation transform (CAT), so it isn’t absolute, and there is no one “true” sRGB. A common CAT is “Bradford”, but others are available, giving slightly different results.

Primaries are measured with respect to a particular WP. So sRGB xy primaries for D65 are different numbers to the xy primaries for D65. ICC profiles are defined with D50 WP not D65, which accounts for most of the difference you can probably see in the numbers.

In addition, neither D65 nor D50 illuminants have consistent numbers. Lindbloom WP numbers (from ASTM) are slightly different to sRGB standard numbers, and slightly different to ICC numbers. In addition, numbers in ICC profiles are rounded to 16 binary places in the fractional part, about 4 decimal places. The sRGB standard quotes numbers to only 4 decimal places.

In practice, when the maths is correctly done, results from Lindbloom, Elle Stone, my own attempts, etc seem to agree within 4 decimal places.

I think those factors account for all the differences. As always, corrections or additions are welcome.


I still don’t fully understand this one.

There are two different understandings of whitepoint I have:

  1. The value in the absolute color space you get when setting R, G and B of a particular RGB color model to their maximum values. So the whitest that RGB color model is able to make.

  2. Something related to colored light (like morning sun vs evening sun) shining on paper. This one is not relevant for monitors that emit light though I guess.

When measuring R/G/B values of a light emitting monitor in absolute XYZ space, how do you involve a whitepoint in there, and how does ICC involve D50 in there?

If you define sRGB as having certain coordinates in XYZ space (a certain exact 3D coordinate of red, green, blue, black and white), how can there also be different ones with different 3D coordinates, and when do you use those?

I’m not speaking about slightly numerically different sRGB color spaces by the way, that’s understandable. I’m talking about completely different chromaticity values, such as xy 0.6485,0.3308 instead of 0.6400,0.3300 for red that give a totally different sRGB to XYZ matrix

Thank you

It is relevant, because the “whitest white” that a monitor can emit is a coloured light, it has a chromaticity (expresed as x and y, or X and Y and Z). This might be D65 or D50 or something else. The sRGB standard assumes D65.

(In addition, we should also consider the white point of the ambient lighting in the room that contains the monitor. The sRGB standard assumes D50.)

Ignoring ambient room lighting, suppose we have two monitors. One has a WP of D50 which is reddish. The other has a WP of D65 which is bluer. If we use the bluer monitor then its primaries will be different to those of the reddish monitor. They should be different, because the user of a monitor adapts to the “pure white”, and sees that as white. If the reddish monitor had the primaries of the bluer monitor, colours would look wrong.

1 Like

Ok, I think I get then that R/G/B do depend on the whitepoint in that case.

One more thing then though: If you want to specify the D65 sRGB in an ICC profile:

Can you just give its classic D65 coordinates, where red is 0.6400,0.3300, green is 0.3000,0.6000, blue is 0.1500,0.0600 (in xyY), and its D65 whitepoint in the ICC profile?

Or does the ICC profile somehow still require you to enter different values for the red/green/blue coordinates anyway, even if you give the D65 whitepoint, because ICC uses D50?

I have no experience of building ICC profiles. As I understand it, if we want a D65 ICC profile, we should set the measurementType structure (tag “meas”), which contain the primaries and standard illuminant WP we desire. (Note the WP has to be one of D50, D65, D93 (!) or a few others. We don’t have flexibility to specify the x,y of the WP.)

1 Like

Prior disclaimer: the below is based on my limited experience programming this stuff…

I haven’t actually read the ICC specification, but a lot of folk say it “specifies” D50 as the white point to be used in its profiles. My experience is that ICC profiles don’t have to actually use D50; indeed, if you use dcraw to develop your raw file to sRGB, the resulting TIFF will contain a D65-anchored sRGB profile. A profile of a particular whitepoint can be converted to another whitepoint with one of the chromatic adaptation transforms (CATs) @snibgo referred to. I think ICC said, “Use D50” to keep things simple. LittleCMS, the library I use to apply profiles, seems to handle the CAT just fine.

I recently started a thread on developing an overview chart describing how profile-based color management generally works. You might find it helpful:

1 Like

That’s not my experience. (Perhaps a different version of dcraw? I use v9.27, slightly hacked by me, but I’ve heard version numbers are not always incremented.) I get:

Red: 0.64843207589456,0.330852728980697
Green: 0.32115496490425,0.597872320134279
Blue: 0.155883679164759,0.0660447944681277
WP: 0.345689445525292,0.358517931734951

As this uses ICC, only the first four digits or so are significant. This WP corresponds to illuminant D50 with 2° field of view, more or less.

(Incidentally, the field of view is another potential source of difference. This is usually 2 degrees, but can be 10 degrees, which gives different numbers.)

I had to check, so I ran dcraw against one of my files like this:

dcraw -T -4 DSG_3111.NEF

Which defaults to spitting out the TIFF as sRGB, with sRGB (2.4, IIRC) gamma. Here’s the [ICC_PROFILE] output from:

exiftool -G DSG_3111.tiff

[ICC_Profile]   Profile CMM Type                : 
[ICC_Profile]   Profile Version                 : 2.1.0
[ICC_Profile]   Profile Class                   : Display Device Profile
[ICC_Profile]   Color Space Data                : RGB
[ICC_Profile]   Profile Connection Space        : XYZ
[ICC_Profile]   Profile Date Time               : 0000:00:00 00:00:00
[ICC_Profile]   Profile File Signature          : acsp
[ICC_Profile]   Primary Platform                : Unknown ()
[ICC_Profile]   CMM Flags                       : Not Embedded, Independent
[ICC_Profile]   Device Manufacturer             : none
[ICC_Profile]   Device Model                    : 
[ICC_Profile]   Device Attributes               : Reflective, Glossy, Positive, Color
[ICC_Profile]   Rendering Intent                : Perceptual
[ICC_Profile]   Connection Space Illuminant     : 0.9642 1 0.82491
[ICC_Profile]   Profile Creator                 : 
[ICC_Profile]   Profile ID                      : 0
[ICC_Profile]   Profile Copyright               : auto-generated by dcraw
[ICC_Profile]   Profile Description             : sRGB
[ICC_Profile]   Media White Point               : 0.95045 1 1.08905
[ICC_Profile]   Media Black Point               : 0 0 0
[ICC_Profile]   Red Tone Reproduction Curve     : (Binary data 14 bytes, use -b option to extract)
[ICC_Profile]   Green Tone Reproduction Curve   : (Binary data 14 bytes, use -b option to extract)
[ICC_Profile]   Blue Tone Reproduction Curve    : (Binary data 14 bytes, use -b option to extract)
[ICC_Profile]   Red Matrix Column               : 0.43608 0.2225 0.01393
[ICC_Profile]   Green Matrix Column             : 0.38509 0.71689 0.09709
[ICC_Profile]   Blue Matrix Column              : 0.14305 0.06061 0.71402

The Media White Point, 0.95045 1.0, 1.08905, is what @Elle uses in her profile generation code as the D65 media white point:

Hmm, I’m scratching my head. Possibly dcraw is confused about what type of profile it is creating?

Exiftool says this about the ICC profile that dcraw embeds in my tiff:

[ICC_Profile]   Profile Class                   : Display Device Profile
[ICC_Profile]   Color Space Data                : RGB
[ICC_Profile]   Profile Connection Space        : XYZ
[ICC_Profile]   Connection Space Illuminant     : 0.9642 1 0.82491
[ICC_Profile]   Profile Description             : sRGB
[ICC_Profile]   Media White Point               : 0.95045 1 1.08905

ICC (http://color.org/specification/ICC1v43_2010-12.pdf) says:

So this is a display profile, so the media white point should be the same as the Profile Connection Space Illuminant. But it isn’t. I don’t know why.

Perhaps LCMS ignores the Media White Point. Certainly, when I use ImageMagick to use LCMS to give the chromaticities, I get the numbers in my previous post, D50.

@Elle has an article that talks about that, too, relevant to the white point:


I think the embedded profile is correctly classed, because the destination of the output image is nominally a display. The input profile was used internally by dcraw, as the camera profile created from the adobe_coeff lookup. The image was transformed from camera space to sRGB using the

adobe_coeff profile -> XYZ -> sRGB,

just like any regular transform.

There may be a bug in the way I’m getting my numbers. I’ll work on that. But it’s snowing outside, and well past my bedtime. G’night all.

I haven’t read @Elle’s articles in a while so I don’t remember where the relevant info is. Try reading https://ninedegreesbelow.com/photography/xyz-rgb.html. There is also a place where she includes ODS and XLS files that show her calculations but I forgot where.

PS https://ninedegreesbelow.com/photography/srgb-color-space-to-profile.html might be helpful but I still can’t find the spreadsheets…

PPS I changed the category and added a tag.

Yes and No. It’s absolute in a chromaticity sense, but is often used as a relative space in terms of luminance (i.e. XYZ measurements may be scaled to some reference having Y = 100). In some contexts it may be a percentage of reflectance or transmittance. In other context it may be a percentage of a devices white luminance.

Yes and No. If a display is adjusted to conform to the sRGB specification, then yes, it will have a D65 white point. But an sRGB ICC profile is not the sRGB colorspace, it is a profile representing sRGB response in the ICC prescribed manner. And this means that its native model of how the profile behaves is as if its white has been chromatically adapted to the ICC profile connection space (PCS) D50 white point.

Now if you use a suitably constructed ICCV2 profile in absolute colorimetric intent mode, you should get the native display sRGB colorspace response D65 values. But if you try this with an ICCV4 sRGB profile with most CMMs, you will get a D50 white point, because the V4 spec. disabled absolute colorimetric intent for display profiles.

(ArgyllCMS is an exception, since it will reverse the ICCV4 display profile ‘chad’ tag in absolute colorimetric mode, restoring absolute colorimetric intent behavior for these profiles.)


Hmm, sorry, for now I’ll have to say: I don’t fully understand ICC profiles.

However, I’ll make a couple of observations:

  1. An ICC profile contains instructions for converting between a colorspace and the connection space which is either XYZ or LAB, in principle in either direction. So it may have two different whitepoints: one for the colorspace, the other for the connection space. In ICC v2 and v4, the connection space WP is always D50, so the tag is technically redundant. (But ICCmax allows other connection space WPs.) However, the colorspace WP doesn’t need to be D50.

  2. dcraw embeds an sRGB profile with these primaries:

      <XYZNumber X="0.43608093" Y="0.22250366" Z="0.01393127"/>
      <XYZNumber X="0.38508606" Y="0.71688843" Z="0.09709167"/>
      <XYZNumber X="0.14305115" Y="0.06060791" Z="0.71401978"/>

Using the formulae…

x = X / (X+Y+Z)
y = Y / (X+Y+Z)

… we can easily calculate the chromaticies (x,y) of the primaries to 6 decimal places…

red = (0.648432, 0.330853)
green = (0.321155, 0.597872)
blue = (0.155884, 0.066045)

These are the sRGB standard primaries, chromatically adapted from D65 to D50. But if the primaries are D50, how come the media white point is D65? I don’t know.

I fear that to understand ICC profiles, I need to play with LCMS. I don’t currently have time.

Neither XYZ nor sRGB for a D65 monitor need D50, nor do you need D50 to describe how to convert sRGB D65 to XYZ.

What is the reason why ICC involves D50 in here anyway, and why does ICC’s design not allow you to give chromaticities in the whitepoint you want (you can give a whitepoint with the wtpt tag, so why does it not treat the rXYZ, gXYZ and bXYZ compared to that one?), or better, just the 3x3 matrix values to convert between the RGB and XYZ values?

To repeat very clearly:

If neither your RGB model nor XYZ use D50, why is the design of ICC forcing you to involve D50 and Bradford adaptions anyway while this is not necessary?

Maybe I am missing some extra layer, what required this extra complexity?

And asked from a different angle:

AFAIK the only thing you need the rXYZ, gXYZ, bXYZ chromaticities for, is for converting the RGB to XYZ. Yet converting RGB to XYZ is simpler when not involving an additional whitepoint. So why is it involved at all? Don’t you know everything once you know how to convert to XYZ, and simplest would be best (less numerical precesion errors, less confusion and wrongly made profiles, …)?

Because the intention of ICC profiles is to provide conversions from one device space to another, and 99.9% of the time, people want white on one device to be white on the other.

The way this is done is to either measure the devices with a D50 illuminant (print, transparency), or chromatically transform the device white to D50 (the Profile Connection Space white). This naturally gives you an overall transform (Device -> PCS -> Device) that is Relative Colorimetric intent.


XYZ on its own is not sufficient to describe the appearance of a colour. You also need to know the conditions under which it is viewed (surrounding colour, illumination etc.).

In a typical colour management workflow, you have to deal with many different white points and viewing conditions. Rather than having specific conversions between each pair of devices in a system (which results in a LOT of possible transforms), ICC colour management uses a common Profile Connection Space (PCS) as the target for ICC profiles. That way, each ICC profile converts from a device colourspace to the PCS (or the other way around). You can build colour transforms by plugging profiles together using the PCS as a common intermediate space. The ICC PCS just happens to be D50 based.

Conversion between device white points and the PCS whitepoint is handled in the profiles. There is some extra complexity in putting the profile together to account for viewing conditions, but using the profiles is simplified.

The full explanation of the reasons for a D50 whitepoint in Display profiles is on the ICC website here:
Why is the media point of a display profile always D50?

Quote from the book by Charles Poynton (2012, page 272):
“Tristimulus values are computed from a continuous spectral power distribution (SPD) by integrating the SPD under the colour matching functions.”

This is also detailed on Bruce Lindbloom’s math-page “Computing XYZ From Spectral Data”.

One SPD is D50, another is D65, so both will give different XYZ values according to this.