RSS/Atom feed Twitter
Site is read-only, email is disabled

Adapted and unadapted sRGB luminance values

This discussion is connected to the gimp-developer-list.gnome.org mailing list which is provided by the GIMP developers and not related to gimpusers.com.

This is a read-only list on gimpusers.com so this discussion thread is read-only, too.

10 of 10 messages available
Toggle history

Please log in to manage your subscriptions.

Adapted and unadapted sRGB luminance values Elle Stone 21 Sep 13:30
  Adapted and unadapted sRGB luminance values Michael Henning 21 Sep 22:48
   Adapted and unadapted sRGB luminance values Elle Stone 22 Sep 00:21
    Adapted and unadapted sRGB luminance values Michael Henning 22 Sep 02:05
     Adapted and unadapted sRGB luminance values Elle Stone 22 Sep 15:37
      Adapted and unadapted sRGB luminance values Michael Henning 22 Sep 18:38
       Adapted and unadapted sRGB luminance values Elle Stone 22 Sep 20:30
        Adapted and unadapted sRGB luminance values Elle Stone 23 Sep 21:46
         Adapted and unadapted sRGB luminance values Michael Henning 29 Sep 16:12
          Adapted and unadapted sRGB luminance values Elle Stone 01 Oct 12:25
Elle Stone
2013-09-21 13:30:35 UTC (over 10 years ago)

Adapted and unadapted sRGB luminance values

I was curious as to why the Babl/Gegl/Gimp code uses the unadapted sRGB luminance values rather than the adapted values.

Quoting Lindbloom (http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html):

Since the ICC specification and Adobe Photoshop both use a reference white of D50, the working space primaries that are specified relative to some other reference white must first be adapted to D50 before they may be used in a D50 environment, or be meaningfully compared with one another.

If I understand him correctly, Poynton (http://www.poynton.com/PDFs/ColorFAQ.pdf) was talking about the conversion appropriate for sending signals to a monitor with a D65 white point. Y709 = 0.2125 R + 0.7154 G + 0.0721B

Lindbloom unadapted and adapted sRGB "Y" values: unadpapted sRGB R, G, B luminance (Y): 0.212656 0.715158 0.072186 adapted sRGB R, G, B luminance (Y): 0.222491 0.716888 0.060621

The sRGB profile created in gegl/operations/external/lcms-from-profile.c has values very close to the Lindbloom adapted values: 0.222488 0.716904 0.060608.

All the code in Babl/Gegl/Gimp that I could locate uses values very close to the Lindbloom *un*adapted Y values: ./babl/babl/base/rgb-constants.h: #define RGB_LUMINANCE_RED (0.212671) ./babl/babl/base/rgb-constants.h: #define RGB_LUMINANCE_GREEN (0.715160) ./babl/babl/base/rgb-constants.h: #define RGB_LUMINANCE_BLUE (0.072169) ./gegl/operations/common/snn-mean.c:#define RGB_LUMINANCE_RED (0.212671) ./gegl/operations/common/snn-mean.c:#define RGB_LUMINANCE_GREEN (0.715160) ./gegl/operations/common/snn-mean.c:#define RGB_LUMINANCE_BLUE (0.072169) ./gegl/operations/workshop/snn-percentile.c:#define RGB_LUMINANCE_RED (0.212671)
./gegl/operations/workshop/snn-percentile.c:#define RGB_LUMINANCE_GREEN (0.715160)
./gegl/operations/workshop/snn-percentile.c:#define RGB_LUMINANCE_BLUE (0.072169)
./gegl/opencl/colors.cl.h:" #define RGB_LUMINANCE_RED (0.212671f) ./gegl/opencl/colors.cl.h:" #define RGB_LUMINANCE_GREEN (0.715160f) ./gegl/opencl/colors.cl.h:" #define RGB_LUMINANCE_BLUE (0.072169f) ./gimp/libgimpcolor/gimprgb.h:#define GIMP_RGB_LUMINANCE_RED (0.2126) ./gimp/libgimpcolor/gimprgb.h:#define GIMP_RGB_LUMINANCE_GREEN (0.7152) ./gimp/libgimpcolor/gimprgb.h:#define GIMP_RGB_LUMINANCE_BLUE (0.0722) ./babl/extensions/ycbcr.c: luminance = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
./babl/extensions/ycbcr.c: luminance = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
./gegl/operations/common/svg-saturate.c uses red:0.213 green:0.715 blue:0.072

Elle

http://ninedegreesbelow.com

Just because it's a standard, doesn't mean it's right.
Michael Henning
2013-09-21 22:48:24 UTC (over 10 years ago)

Adapted and unadapted sRGB luminance values

Both babl's RGB format and Y format are currently defined with a white point of D65. Because of this, I believe the code's current luminance values are correct.

Out of curiosity, how did you determine the Y values from the code in gegl/operations/external/lcms-from-profile.c ? If you're somehow dumping the icc profile and analyzing it, then it would make sense that those are relative to D50 because icc mandates D50.

In other words, I think that the whitepoints are all currently correct, because the constants in code are for converting between two color spaces with D65, and the icc profile is relative to D50.

(As a side note, I believe some of the grayscale conversions are currently very broken for other reasons. They operate in a gamma space, but use constants that are meant for linear color spaces. I meant to fix this before, but I forgot to at some point.)

On Sat, Sep 21, 2013 at 9:30 AM, Elle Stone wrote:

I was curious as to why the Babl/Gegl/Gimp code uses the unadapted sRGB luminance values rather than the adapted values.

Quoting Lindbloom (http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html):

Since the ICC specification and Adobe Photoshop both use a reference white of D50, the working space primaries that are specified relative to some other reference white must first be adapted to D50 before they may be used in a D50 environment, or be meaningfully compared with one another.

If I understand him correctly, Poynton (http://www.poynton.com/PDFs/ColorFAQ.pdf) was talking about the conversion appropriate for sending signals to a monitor with a D65 white point. Y709 = 0.2125 R + 0.7154 G + 0.0721B

Lindbloom unadapted and adapted sRGB "Y" values: unadpapted sRGB R, G, B luminance (Y): 0.212656 0.715158 0.072186 adapted sRGB R, G, B luminance (Y): 0.222491 0.716888 0.060621

The sRGB profile created in gegl/operations/external/lcms-from-profile.c has values very close to the Lindbloom adapted values: 0.222488 0.716904 0.060608.

All the code in Babl/Gegl/Gimp that I could locate uses values very close to the Lindbloom *un*adapted Y values: ./babl/babl/base/rgb-constants.h: #define RGB_LUMINANCE_RED (0.212671) ./babl/babl/base/rgb-constants.h: #define RGB_LUMINANCE_GREEN (0.715160) ./babl/babl/base/rgb-constants.h: #define RGB_LUMINANCE_BLUE (0.072169) ./gegl/operations/common/snn-mean.c:#define RGB_LUMINANCE_RED (0.212671) ./gegl/operations/common/snn-mean.c:#define RGB_LUMINANCE_GREEN (0.715160) ./gegl/operations/common/snn-mean.c:#define RGB_LUMINANCE_BLUE (0.072169) ./gegl/operations/workshop/snn-percentile.c:#define RGB_LUMINANCE_RED (0.212671)
./gegl/operations/workshop/snn-percentile.c:#define RGB_LUMINANCE_GREEN (0.715160)
./gegl/operations/workshop/snn-percentile.c:#define RGB_LUMINANCE_BLUE (0.072169)
./gegl/opencl/colors.cl.h:" #define RGB_LUMINANCE_RED (0.212671f) ./gegl/opencl/colors.cl.h:" #define RGB_LUMINANCE_GREEN (0.715160f) ./gegl/opencl/colors.cl.h:" #define RGB_LUMINANCE_BLUE (0.072169f) ./gimp/libgimpcolor/gimprgb.h:#define GIMP_RGB_LUMINANCE_RED (0.2126) ./gimp/libgimpcolor/gimprgb.h:#define GIMP_RGB_LUMINANCE_GREEN (0.7152) ./gimp/libgimpcolor/gimprgb.h:#define GIMP_RGB_LUMINANCE_BLUE (0.0722) ./babl/extensions/ycbcr.c: luminance = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
./babl/extensions/ycbcr.c: luminance = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
./gegl/operations/common/svg-saturate.c uses red:0.213 green:0.715 blue:0.072

Elle

-- http://ninedegreesbelow.com

Just because it's a standard, doesn't mean it's right. _______________________________________________ gimp-developer-list mailing list
List address: gimp-developer-list@gnome.org List membership: https://mail.gnome.org/mailman/listinfo/gimp-developer-list

Elle Stone
2013-09-22 00:21:09 UTC (over 10 years ago)

Adapted and unadapted sRGB luminance values

On 9/21/13, Michael Henning wrote:

Both babl's RGB format and Y format are currently defined with a white point of D65. Because of this, I believe the code's current luminance values are correct.

The whitepoint of an ICC profile might have a D65 white point without a chad tag, if it's a V2 profile. Or it might have a D50 white point with a chad (chromatic adaptation) tag if it's a V4 profile. Either way, the XYZ values are the adapted values, NOT the unadapted values. In other words "D65" as the white point for the V2 profiles doesn't mean "use the unadapted primaries", which means the unadapted "Y" values are wrong. So are the unadapted X and Z values.

Out of curiosity, how did you determine the Y values from the code in gegl/operations/external/lcms-from-profile.c ?

I put in a couple additional lines of code in the gegl file telling lcms to save the profile to disk. Then I recompiled gegl, retrieved the profile, and used iccToXml to examine the primaries. It's a bog standard sRGB V4 lcms-generated profile. If you would like to look at it, it's attached to this email.

> If you're somehow

dumping the icc profile and analyzing it, then it would make sense that those are relative to D50 because icc mandates D50.

That's kinda the point. If a person opens an sRGB image file with Gimp, that image's profile has the adapted primaries, not the unadapted primaries.

In other words, I think that the whitepoints are all currently correct, because the constants in code are for converting between two color spaces with D65, and the icc profile is relative to D50.

But that means the code is assuming a very odd color space, not the same sRGB as is used by the vast majority of all the sRGB images ever created. This includes all images to which Gimp assigns the built-in sRGB profile created by lcms. V2 or V4, lcms1 or lcms2, the sRGB primaries are the adapted primaries, which means the adapted R,G, and B "Y" values.

So how can it be right that the babl/gegl/gimp code uses unadapted primaries for image processing, while operating on images that are created using the adapted primaries? If you assign an sRGB profile with unadapted primaries to an sRGB image that was created with a proper sRGB image, that image will have a false blue color cast. And if you use the unadapted Y values for Luminance desaturating in a linear gamma color space, the resulting image will be slightly wrong.

(As a side note, I believe some of the grayscale conversions are currently very broken for other reasons. They operate in a gamma space, but use constants that are meant for linear color spaces.

It's true that Luminance conversions to black and white in a nonlinear color space makes much more wrong results than merely using the unadapted Y values. But the Y values for the Luminance desaturate code, for example, are still wrong. They should be the adapted values.

Elle

Michael Henning
2013-09-22 02:05:37 UTC (over 10 years ago)

Adapted and unadapted sRGB luminance values

Those conversion factors are attempting to get a D65 Y from D65 RGB.

So, we currently do a conversion like this, using unadapted values: D65 Y = 0.212656 * D65 Red + 0.715158 * D65 Green + 0.072186 * D65 Blue

And you want us to do this, using the adapted values: Y = 0.222491 * D65 Red + 0.716888 * D65 Green + 0.060621 * D65 Blue

Isn't the second (adapted) transform going to give us a D50 Y instead of a D65 Y?

On Sat, Sep 21, 2013 at 8:21 PM, Elle Stone wrote:

On 9/21/13, Michael Henning wrote:

Both babl's RGB format and Y format are currently defined with a white point of D65. Because of this, I believe the code's current luminance values are correct.

The whitepoint of an ICC profile might have a D65 white point without a chad tag, if it's a V2 profile. Or it might have a D50 white point with a chad (chromatic adaptation) tag if it's a V4 profile. Either way, the XYZ values are the adapted values, NOT the unadapted values. In other words "D65" as the white point for the V2 profiles doesn't mean "use the unadapted primaries", which means the unadapted "Y" values are wrong. So are the unadapted X and Z values.

Out of curiosity, how did you determine the Y values from the code in gegl/operations/external/lcms-from-profile.c ?

I put in a couple additional lines of code in the gegl file telling lcms to save the profile to disk. Then I recompiled gegl, retrieved the profile, and used iccToXml to examine the primaries. It's a bog standard sRGB V4 lcms-generated profile. If you would like to look at it, it's attached to this email.

> If you're somehow

dumping the icc profile and analyzing it, then it would make sense that those are relative to D50 because icc mandates D50.

That's kinda the point. If a person opens an sRGB image file with Gimp, that image's profile has the adapted primaries, not the unadapted primaries.

In other words, I think that the whitepoints are all currently correct, because the constants in code are for converting between two color spaces with D65, and the icc profile is relative to D50.

But that means the code is assuming a very odd color space, not the same sRGB as is used by the vast majority of all the sRGB images ever created. This includes all images to which Gimp assigns the built-in sRGB profile created by lcms. V2 or V4, lcms1 or lcms2, the sRGB primaries are the adapted primaries, which means the adapted R,G, and B "Y" values.

So how can it be right that the babl/gegl/gimp code uses unadapted primaries for image processing, while operating on images that are created using the adapted primaries? If you assign an sRGB profile with unadapted primaries to an sRGB image that was created with a proper sRGB image, that image will have a false blue color cast. And if you use the unadapted Y values for Luminance desaturating in a linear gamma color space, the resulting image will be slightly wrong.

(As a side note, I believe some of the grayscale conversions are currently very broken for other reasons. They operate in a gamma space, but use constants that are meant for linear color spaces.

It's true that Luminance conversions to black and white in a nonlinear color space makes much more wrong results than merely using the unadapted Y values. But the Y values for the Luminance desaturate code, for example, are still wrong. They should be the adapted values.

Elle

Elle Stone
2013-09-22 15:37:01 UTC (over 10 years ago)

Adapted and unadapted sRGB luminance values

On 9/21/13, Michael Henning wrote:

Both babl's RGB format and Y format are currently defined with a white point of D65. Because of this, I believe the code's current luminance values are correct.

In other words, I think that the whitepoints are all currently correct, because the constants in code are for converting between two color spaces with D65, and the icc profile is relative to D50.

When converting between linear gamma sRGB and regular sRGB, the only thing that ought to happen is that the image red, blue, and green values are modified by the babl/babl/base/util.h functions "gamma_2_2_to_linear" and "gamma_2_2_to_linear" (which aren't "gamma" transforms, but rather sRGB companding functions). So is there some other place in the babl/gegl/gimp code where there is an actual hard-coded matrix transform between two D65 color spaces? If so, which two D65 color spaces?

On 9/21/13, Michael Henning wrote:

Those conversion factors are attempting to get a D65 Y from D65 RGB.

So, we currently do a conversion like this, using unadapted values: D65 Y = 0.212656 * D65 Red + 0.715158 * D65 Green + 0.072186 * D65 Blue

And you want us to do this, using the adapted values: Y = 0.222491 * D65 Red + 0.716888 * D65 Green + 0.060621 * D65 Blue

Well, what I really want babl/gegl/gimp to do is stop using sRGB as the "one space to rule them all" and instead, if there has to be a single internal color space, make it the D50 Identity color space, in which case equations for calculating the luminance of an image would simplify to Y=Green and you also wouldn't have to deal with RGB values less than 0 and greater than 1 resulting like they do when you convert more saturated images from larger color spaces to sRGB. It would make coding up proper soft proofing a lot easier, too.

However, that wasn't what you were asking about. So, to answer the question:

D50 has two uses in an ICC profile: the profile illuminant and also the profile white point for profiles with D50 white points.

D65 has only one use, that being as a profile white point, as the ICC hasn't approved other illuminants besides D50. So a D65 whitepoint ICC profile like sRGB still has a D50 illuminant. That's why you need the Bradford-adapted XYZ primaries, hence the Bradford-adapted "Y".

So there really is no unadapted "D65" red, green, and blue, not in the actual sRGB images that Gimp creates and not in any sRGB images that Gimp opens that were created by digital cameras or by properly color managed image editors.

Assuming I understand Poynton correctly, the babl/gegl/gimp code uses Y values that are appropriate for sending RGB values to a CRT that's been ***calibrated to match sRGB***, in a *non*-color-managed context. The Poynton values don't have any place in a color-managed application when sending the appropriate RGB values to the monitor (lcms takes care of that), or when doing ICC profile transforms (lcms does that), or when calculating image Luminance values from image RGB values. For calculating Luminance you need the adapted Y values.

As an aside, you can't assume that any of today's LCD monitors are calibrated to match sRGB or even to have a D65 white point - the native white point of LCD monitors seems to be around 5800K and not everyone is willing to trade the largest possible color gamut and the smoothest possible gray scale for the sake of calibrating an LCD monitor to have a more or less imperfectly achieved D65 white point, just to match the white point of an sRGB-calibrated CRT manufactured in the 1990s. Different times, different technology.

Isn't the second (adapted) transform going to give us a D50 Y instead of a D65 Y?

Yes, it will, and that's precisely what you want if you want to correctly calculate an sRGB image's Luminance values from its RGB values.

Elle Stone
http://ninedegreesbelow.com

Just because it's a standard, doesn't mean it's right.
Michael Henning
2013-09-22 18:38:34 UTC (over 10 years ago)

Adapted and unadapted sRGB luminance values

I hope you don't mind; I reordered parts of your email when responding to it.

Isn't the second (adapted) transform going to give us a D50 Y instead of a D65 Y?

Yes, it will, and that's precisely what you want if you want to correctly calculate an sRGB image's Luminance values from its RGB values.

The main usage for this transform (D65 RGB -> D65 Y, with the unadapted values) is to convert color images to grayscale. It seems to me that having a D65 grayscale image is correct, especially because when converting back to RGB D65 we simply copy the Y value into each of the components.

I haven't really looked at the other cases of the values you pointed out yet, but none of those are widely used code paths. They should probably be examined individually.

D50 has two uses in an ICC profile: the profile illuminant and also the profile white point for profiles with D50 white points.

I don't think we should be accounting for the illuminant when converting to grayscale.

As an aside, you can't assume that any of today's LCD monitors are calibrated to match sRGB or even to have a D65 white point

Every monitor is different. D65 with the sRGB primaries is the same as ITU‐R BT.709‐5 (HDTV), which I think is a reasonable approximation for certain calculations. Nobody is claiming that our conversions are exact for an profileless, uncalibrated monitor.

So is there some
other place in the babl/gegl/gimp code where there is an actual hard-coded matrix transform between two D65 color spaces? If so, which two D65 color spaces?

The YCbCr transform in babl might be wrong (assumes D65, in a case where we don't want D65), but you already pointed that out, and I wasn't really talking about that conversion.

Well, what I really want babl/gegl/gimp to do is stop using sRGB as the "one space to rule them all" and instead, if there has to be a single internal color space, make it the D50 Identity color space ...

I think the main reason for choosing an sRGB-like space is because of convenience. Many images are in sRGB, and it's nice to be able to store them in 8-bits/channel without severe quality loss. People using other color spaces are more likely to use high bitdepths, where the profile choice is less critical for image quality.

Elle Stone
2013-09-22 20:30:02 UTC (over 10 years ago)

Adapted and unadapted sRGB luminance values

On 9/22/13, Michael Henning wrote:

Isn't the second (adapted) transform going to give us a D50 Y instead of a D65 Y?

Yes, it will, and that's precisely what you want if you want to correctly calculate an sRGB image's Luminance values from its RGB values.

The main usage for this transform (D65 RGB -> D65 Y, with the unadapted values) is to convert color images to grayscale. It seems to me that having a D65 grayscale image is correct, especially because when converting back to RGB D65 we simply copy the Y value into each of the components.

All sRGB images are encoded using D50-adapted primaries. To convert to black and white using Luminance you need to use the "Y" values from the actual sRGB profile that's actually used in actual sRGB images. You shouldn't use the unadapted D65 Y values that are in the babl/gegl/gimp code.

I can send you a test image and some profiles if you'd like to demonstrate for yourself that the D50-adapted Y values are the right Y values to use for converting an sRGB image to black and white.

As an aside, you can't assume that any of today's LCD monitors are calibrated to match sRGB or even to have a D65 white point

Nobody is claiming that our conversions are exact for an profileless, uncalibrated monitor.

I wasn't talking about a profileless, uncalibrated monitor. Profiling and calibrating a monitor are completely independent actions. Personally, I profile my monitor, but I don't calibrate it other than setting how bright it is, because profiling an LCD monitor in its uncalibrated, "native" state gives a larger color gamut and smoother grayscale.

Every monitor is different. D65 with the sRGB primaries is the same as ITU‐R BT.709‐5 (HDTV), which I think is a reasonable approximation for certain calculations. Nobody is claiming that our conversions are exact for an profileless, uncalibrated monitor.

I'm actually claiming that as far as converting an sRGB image to a technically correct, luminance-based black and white image goes, your unadapted D65 Y values are not the right values regardless of whether a person is using a calibrated and/or profiled monitor or not. They are the wrong values if it's a CRT or an LCD or a TV set from the 1950s or a super hi-def state-of-the-art TV from today. The technology used to *display* the resulting image has nothing at all to do with the right values for converting that image to black and white in a ICC profile-based, color-managed workflow. The proper Y values for converting an sRGB image to black and white using Luminance are the D50-adapted Y values from the D50-adapted sRGB profile that's actually embedded in the sRGB image.

Elle Stone
http://ninedegreesbelow.com

Just because it's a standard, doesn't mean it's right.
Elle Stone
2013-09-23 21:46:33 UTC (over 10 years ago)

Adapted and unadapted sRGB luminance values

A technically correct luminance-based conversion to black and white is done using this formula:

L = R*Yr + G*Yg + B*Yb

where R, G, and B are the image RGB values for any given pixel and Yr, Yg, and Yb are the Y values from the image's actual ICC profile. If the profile white point isn't D50, the Y values are always adapted Y values. The image must be in a linear gamma version of the color space.

So far I'm repeating what I've already said. Below are concrete examples showing that using the **un**adapted sRGB Y values results in the wrong Luminance values:

Consider an image with a color block of the sRGB "reddest possible red" 16-bit integer color: (65535, 0, 0).

Convert the sRGB image to a different ICC profile using relative colorimetric intent and the RGB values will change but the **meaning** of the RGB values will be the same. In other words, the new RGB values will point to the same XYZ coordinates as the previous sRGB RGB values pointed to. Here are some examples:

According to the argyllcms xicclu utility, sRGB values (65535, 0, 0) are the same as XYZ (0.435837, 0.222366, 0.013916).

Convert the sRGB image to WideGamut: Widegamut RGB values (38832, 6228, 766) are the same as XYZ (0.435838 0.222362 0.013910)

Convert the sRGB image to ProPhoto: ProPhoto RGB values (34671, 6442, 1105) are the same as XYZ (0.435843 0.222371 0.013910)

Convert the sRGB image to the Identity profile: Identity RGB values (29623 14573 1106) are the same as XYZ (0.435837 0.222370 0.013921)

Notice that for each profile's equivalent-to-sRGB-reddedst-red, the XYZ "Y" value is almost identical to the sRGB ADAPTED Y value. The color's coordinates in XYZ space don't change upon converting the image from one color space to another using relative colorimetric intent (unless there is gamut clipping, but then only the clipped values are affected; I didn't mention black point compensation because for working spaces with 0 black points, using or not using blackpoint compensation makes no difference, and if it does, there' a problem in the code).

The "Y" in a color's equivalent XYZ values **is** a color's Luminance. If your method of calculating Luminance gives something other than the color's "Y" value in XYZ space, your method of calculating Luminance is wrong.

Back to the formula for calculating Luminance:

sRGB-unadapted: 65535 * 0.21265600 + 0 * 0.71515800 + 0 * 0.07218600 = 13936.4

sRGB-adapted: 65535 * 0.22236633 + 0 * 0.71704102 + 0 * 0.06059265 = 14572.8

WideGamut: 38832 * 0.25871277 + 6228 * 0.72470093 + 766 * 0.01658630 = 14572.5

ProPhoto: 34671 * 0.28804016 + 6442 * 0.71195984 + 1105 * 0.00000000 = 14573.1

Identity: 29623 * 0.00000000 + 14573 * 1.00000000 + 1106 * 0.00000000 = 14573.0

In the above equations, the RGB values for the color of red specified by the reddest possible sRGB red were determined by eye droppering a red color block after doing the appropriate ICC profile conversions. As you can see, the "Luminance" value calculated by the UNadapted sRGB "Y" values is out of line with the other four calculated values. Notice that 14573/65535 is 0.22237, the ADAPTED red Y value for sRGB. If you did the same calculations for bluest sRGB blue and greenest sRGB green, you'd get the ADAPTED sRGB blue and green Y values.

The actual eye droppered grayscale values for my four color test image (reddest sRGB red, bluest sRGB blue, and greenest sRGB green against an 18% gray background), after converting to black and white using Luminance, are as follows (ICC profile conversions done at 32-bit floating point, which is how I did the conversions, are more accurate than working with 16-bit values as given above):

Profile WtPt Red block Green block Blue block 18% Gray
sRGB D65-unadapted 13936 46868 4731 12094 sRGB D65-adapted 14573 46991 3971 12094
WideGamut D50 14573 46991 3971 12094
ProPhoto D50 14573 46991 3971 12094
Identity D50 14573 46991 3971 12094

The 18% gray value is the same for all five conversions because the ONLY thing that determines the value of a neutral patch in an RGB image is the profile's TRC. And a technically correct Luminance conversion must always be done in a linear gamma color space.

For neutral R=G=B starting "color image" values like 18% gray, correct OR incorrect Y values gives the same black and white R=G=B value after the Luminance conversion (it's always the same RGB values as before the conversion). But the more saturated the color is, the more wrong the results are using the UNadapted Y values.

A technically correct Luminance conversion to black and white should give the same resulting black and white image ***regardless*** of the RGB working space the image happens to be in (this is not true of most methods of converting an image to black and white).

Your incorrect use of the unadapted "Y" values makes the Luminance conversion dependent on the image profile's white point. But Luminance is determined by the value of Y in the color's XYZ coordinates. And those coordinates are determined using the adapted Y values from the actual image ICC profile. Those values don't change just because you converted the image from one color space to another, as long as you use relative colorimetric intent to do the conversion.

The **un**adapted sRGB Luminance values for red, blue and green are different from the adapted values because the unadapted values use the wrong "Y" values. The Luminance values calculated using the unadapted "Y" values don't correspond to the equivalent "Y" value in XYZ space for the color before the conversion to black and white.

You can download the test image and the four ICC profiles from this web page: http://ninedegreesbelow.com/photography/luminance-black-white.html

Elle

Michael Henning
2013-09-29 16:12:37 UTC (over 10 years ago)

Adapted and unadapted sRGB luminance values

Sorry for the delay in replying; I wanted to take the time to properly look at everything you've said.

Yes, Elle, you're right. I take what I said back; we should be using the adapted values.

If anyone is still doubting this, you can try playing around with this demo program I created:
http://ix.io/8ho

It creates lcms profiles for the babl RGB and Y formats, and then uses lcms to convert from RGB to Y.

Here's the output: (R, G, B) -> Y
(1.000000, 0.000000, 0.000000) -> 0.222492 (0.000000, 1.000000, 0.000000) -> 0.716902 (0.000000, 0.000000, 1.000000) -> 0.060606 (0.500000, 0.500000, 0.500000) -> 0.500000

On Mon, Sep 23, 2013 at 5:46 PM, Elle Stone wrote:

A technically correct luminance-based conversion to black and white is done using this formula:

L = R*Yr + G*Yg + B*Yb

where R, G, and B are the image RGB values for any given pixel and Yr, Yg, and Yb are the Y values from the image's actual ICC profile. If the profile white point isn't D50, the Y values are always adapted Y values. The image must be in a linear gamma version of the color space.

So far I'm repeating what I've already said. Below are concrete examples showing that using the **un**adapted sRGB Y values results in the wrong Luminance values:

Consider an image with a color block of the sRGB "reddest possible red" 16-bit integer color: (65535, 0, 0).

Convert the sRGB image to a different ICC profile using relative colorimetric intent and the RGB values will change but the **meaning** of the RGB values will be the same. In other words, the new RGB values will point to the same XYZ coordinates as the previous sRGB RGB values pointed to. Here are some examples:

According to the argyllcms xicclu utility, sRGB values (65535, 0, 0) are the same as XYZ (0.435837, 0.222366, 0.013916).

Convert the sRGB image to WideGamut: Widegamut RGB values (38832, 6228, 766) are the same as XYZ (0.435838 0.222362 0.013910)

Convert the sRGB image to ProPhoto: ProPhoto RGB values (34671, 6442, 1105) are the same as XYZ (0.435843 0.222371 0.013910)

Convert the sRGB image to the Identity profile: Identity RGB values (29623 14573 1106) are the same as XYZ (0.435837 0.222370 0.013921)

Notice that for each profile's equivalent-to-sRGB-reddedst-red, the XYZ "Y" value is almost identical to the sRGB ADAPTED Y value. The color's coordinates in XYZ space don't change upon converting the image from one color space to another using relative colorimetric intent (unless there is gamut clipping, but then only the clipped values are affected; I didn't mention black point compensation because for working spaces with 0 black points, using or not using blackpoint compensation makes no difference, and if it does, there' a problem in the code).

The "Y" in a color's equivalent XYZ values **is** a color's Luminance. If your method of calculating Luminance gives something other than the color's "Y" value in XYZ space, your method of calculating Luminance is wrong.

Back to the formula for calculating Luminance:

sRGB-unadapted: 65535 * 0.21265600 + 0 * 0.71515800 + 0 * 0.07218600 = 13936.4

sRGB-adapted: 65535 * 0.22236633 + 0 * 0.71704102 + 0 * 0.06059265 = 14572.8

WideGamut: 38832 * 0.25871277 + 6228 * 0.72470093 + 766 * 0.01658630 = 14572.5

ProPhoto: 34671 * 0.28804016 + 6442 * 0.71195984 + 1105 * 0.00000000 = 14573.1

Identity: 29623 * 0.00000000 + 14573 * 1.00000000 + 1106 * 0.00000000 = 14573.0

In the above equations, the RGB values for the color of red specified by the reddest possible sRGB red were determined by eye droppering a red color block after doing the appropriate ICC profile conversions. As you can see, the "Luminance" value calculated by the UNadapted sRGB "Y" values is out of line with the other four calculated values. Notice that 14573/65535 is 0.22237, the ADAPTED red Y value for sRGB. If you did the same calculations for bluest sRGB blue and greenest sRGB green, you'd get the ADAPTED sRGB blue and green Y values.

The actual eye droppered grayscale values for my four color test image (reddest sRGB red, bluest sRGB blue, and greenest sRGB green against an 18% gray background), after converting to black and white using Luminance, are as follows (ICC profile conversions done at 32-bit floating point, which is how I did the conversions, are more accurate than working with 16-bit values as given above):

Profile WtPt Red block Green block Blue block 18% Gray
sRGB D65-unadapted 13936 46868 4731 12094 sRGB D65-adapted 14573 46991 3971 12094
WideGamut D50 14573 46991 3971 12094
ProPhoto D50 14573 46991 3971 12094
Identity D50 14573 46991 3971 12094

The 18% gray value is the same for all five conversions because the ONLY thing that determines the value of a neutral patch in an RGB image is the profile's TRC. And a technically correct Luminance conversion must always be done in a linear gamma color space.

For neutral R=G=B starting "color image" values like 18% gray, correct OR incorrect Y values gives the same black and white R=G=B value after the Luminance conversion (it's always the same RGB values as before the conversion). But the more saturated the color is, the more wrong the results are using the UNadapted Y values.

A technically correct Luminance conversion to black and white should give the same resulting black and white image ***regardless*** of the RGB working space the image happens to be in (this is not true of most methods of converting an image to black and white).

Your incorrect use of the unadapted "Y" values makes the Luminance conversion dependent on the image profile's white point. But Luminance is determined by the value of Y in the color's XYZ coordinates. And those coordinates are determined using the adapted Y values from the actual image ICC profile. Those values don't change just because you converted the image from one color space to another, as long as you use relative colorimetric intent to do the conversion.

The **un**adapted sRGB Luminance values for red, blue and green are different from the adapted values because the unadapted values use the wrong "Y" values. The Luminance values calculated using the unadapted "Y" values don't correspond to the equivalent "Y" value in XYZ space for the color before the conversion to black and white.

You can download the test image and the four ICC profiles from this web page: http://ninedegreesbelow.com/photography/luminance-black-white.html

Elle

Elle Stone
2013-10-01 12:25:43 UTC (over 10 years ago)

Adapted and unadapted sRGB luminance values

On 9/29/13, Michael Henning wrote:

Sorry for the delay in replying; I wanted to take the time to properly look at everything you've said.

If you managed to make your way through *everything* I said in my attempt to explain why the adapted values are the correct values for an ICC profile color managed image editor, you have fortitude!

we should be using the adapted values.

This question of D50 adapted vs D65 unadapted sRGB primaries brings up a puzzling question. D65 white is much bluer than D50 white. So what do sRGB images create with Gimp before Gimp was color managed look like when viewed in an ICC profile color managed image editor? Does anyone have an image created using one of the earliest versions of Gimp that I could look at, preferably an image that is supposed to have areas of light gray or white?

Elle

Elle Stone
http://ninedegreesbelow.com

Just because it's a standard, doesn't mean it's right.