What is the meaning of conversion from RGB to luma?
The following formula is used:
luma = 0.2126*R + 0.7152*G + 0.0722*B
It is not clear what luma here is supposed to mean.
I can see two explanations for this formula:
-
This is the same formula which is used in conversion from Rec. 709 RGB to YCbCr to find Y (luma) component. However it seems that it is assumed that
Rgbpixel is in sRGB color space (although docs don't say anything about color spaces) and not in Rec. 709. -
Coefficients are the same as in matrix to convert from linear sRGB to XYZ. If R, G and B values were in linear sRGB then the above formula would give the luminance value.
The above two cases do not apply and I don't see any other explanations for this .
What else would you propose to use if no color space information is given? Just averaging all values?
What I'm more concerned with is what do we use if we have color space information. One of the usages of luma in this library is converting images to grayscale. However, I believe, the correct way to convert images to grayscale is to keep perceived brightness of each pixel in the resulting image to be the same as in the original. image::imageops::grayscale currently uses luma for this operation and thus in addition to converting image to grayscale it may also change brightness of some pixels (usually making them darker). To avoid this one need to use luminance instead of luma.
I made some experiments to compare current implementation of image::imageops::grayscale with converting images to grayscale using luminance.
- Purple flowers: colored | gray-luma | gray-luminance.
- Magenta dress: colored | gray-luma | gray-luminance.
The best way to see the difference is to open these images in separate tabs and instantly switch between them.
- By switching between gray-luma and gray-luminance versions one can see that they are very different, luma version is much darker.
- When switching from color to gray-luma version it is clear that luma version is darker than the original.
- However this is not the case when you switch from colored to gray-luminance version.
@kryptan I added this to image_buffer. Here, Rgb<f32> is defined to be in linear color space (scaled to 1.0) and Rgb<uX> in gamma compressed color space. Converting between this two formats automatically performs the gamma compression/expansion. This would also fix #599 if implemented.
Do you think that this approach is sensible (given I document it properly in the crate)?
What else would you propose to use if no color space information is given?
The absence of color space information simply means to assume the default, which is gamma encoded sRGB, because that's what practically all monitors and cameras are supposed to be calibrated for.
@nwin Yes, I think using linear values when using floating point numbers is the right approach. This is e.g. how it is generally done on GPU - if texture is 8-bit sRGB then it is converted to linear on read, all rendering is done using linear values, and the final result is then converted back to 8-bit sRGB (or whatever format is necessary for the target monitor).
This would definitely need good documentation, many people would be confused why 0.5 isn't get converted to 128.
This is e.g. how it is generally done on GPU
The GPU actually has specific color formats for sRGB. So when you load up some u8 data you specifically have to tell the driver that it is sRGB. I think it may be better to have a type parameter to differentiate between color spaces (with the only two options for now being linear and sRGB), provide methods to convert between those two spaces, and implement most operations only on the linear version. When you open an image it should open it as sRGB, and when you save an image you have to save it as sRGB.
It's actually consistent with option 1, the Y component in BT709: https://www.itu.int/rec/R-REC-BT.709-1-199311-S/en
Derivation of luminance signal E′ = 0.2126 RE′ + 0.7152 GE′ + 0.0722 BE′
Where prime refers to non-linear signals. This is the 'inaccurate' luminance transform, an accurate transform in linear color space is an optional part of Rec.2020 (calling it YcCbcCrc "constant luminance") but all previous BT recommendations that I'm aware of actually specify their transform with regards to non-linear inputs. Rec.2100 again doesn't specify such a scheme.
You'll also find that the BT709 primaries are the same as sRGB.