## Working Color Spaces

Practical and theoretical implementation discussion.
phresnel
Posts: 6
Joined: Sat Jan 07, 2012 9:03 pm

### Working Color Spaces

Hello folks,

I am currently trying to clean up my confusion about color spaces. We are all used to linear and additive RGB colors, and many of us are aware of the gamma correction you need to account for the non-linearity of commoditity display devices.

I searched a lot on the internet to find out which color spaces are suitable as working spaces. I mean by that each color space such that

A + B = C

with

a_n + b_n = c_n,

each a_n, b_n, c_n being real numbers, i.e. where adding colors is a linear operation, and so that adding positive colors results in a color with higher luminance.

Adding XYZ colors and Spectral colors (of same topology) satisfy that. But which other color spaces exist that do that? Which RGB color space do that? Is sRGB a linear and additive?

Ideally, the result of this thread would be a table in the following form:

Code: Select all

color space           | additive | linear
----------------------+----------+---------
Spectral (same topo.) | yes      | yes
XYZ                   | yes      | yes
HSV                   | no       | no
sRGB                  | ??       | ??

And if we do the usual stuff of adding RGB triplets, and finally putting this into some SDL or DirectX surface for display, which was that RGB space specifically? Enligthenment would be very welcome. The knowledge gained will become part of my Color Processing Library "gaudy", which you find on github.

Burce Lindbloom has a lot of information, but he didn't really enlighten me w.r.t. what exactly this little, tiny, raw RGB is we used so much.

I also realise that PBRT has switched from RGB to XYZ. But which exact RGB space did it use in V1?

friedlinguini
Posts: 89
Joined: Thu Apr 11, 2013 5:15 pm

### Re: Working Color Spaces

phresnel wrote:Adding XYZ colors and Spectral colors (of same topology) satisfy that. But which other color spaces exist that do that? Which RGB color space do that? Is sRGB a linear and additive?
sRGB is not linear. It is very close to linear RGB with a 2.2 gamma correction.
phresnel wrote:I also realise that PBRT has switched from RGB to XYZ. But which exact RGB space did it use in V1?
Wait, what? PBRT has always used a sampled spectrum to represent colors internally. By default, the spectrum had three components intended to represent RGB values, though they also exposed a 30-component spectrum in V2. I don't think they specifically named the RGB color space, but they did provide conversions to and from XYZ that should uniquely define it (inasmuch as such a thing makes sense for tristimulus color). V1 did say that it was used by high-definition television, so maybe there is some industry-standard name out there.

phresnel
Posts: 6
Joined: Sat Jan 07, 2012 9:03 pm

### Re: Working Color Spaces

friedlinguini wrote:
phresnel wrote:Adding XYZ colors and Spectral colors (of same topology) satisfy that. But which other color spaces exist that do that? Which RGB color space do that? Is sRGB a linear and additive?
sRGB is not linear. It is very close to linear RGB with a 2.2 gamma correction.
Okay, cool. Now, what would be needed is a conversion of the linear, "PBRT-style" RGB to sRGB or anything. I see on the Lindbloom homepage conversions from any RGB-color-space to XYZ and back, but not of the raw, linear RGB we are used to
phresnel wrote:I also realise that PBRT has switched from RGB to XYZ. But which exact RGB space did it use in V1?
Wait, what? PBRT has always used a sampled spectrum to represent colors internally. By default, the spectrum had three components intended to represent RGB values, though they also exposed a 30-component spectrum in V2. I don't think they specifically named the RGB color space, but they did provide conversions to and from XYZ that should uniquely define it (inasmuch as such a thing makes sense for tristimulus color). V1 did say that it was used by high-definition television, so maybe there is some industry-standard name out there.
Sorry, let me clarify.

They use XYZ to add up their sampled spectra per pixel, i.e. when R is their radiance sampled on a primary ray upon a pixel, they convert R to XYZ to build an average R/n for that pixel.

I.e., in the PBRT image pipeline, ...

Code: Select all

<input> --> Radiance --> Pixel --> <output>
I talk about the part named "pixel".

friedlinguini
Posts: 89
Joined: Thu Apr 11, 2013 5:15 pm

### Re: Working Color Spaces

phresnel wrote:They use XYZ to add up their sampled spectra per pixel, i.e. when R is their radiance sampled on a primary ray upon a pixel, they convert R to XYZ to build an average R/n for that pixel.
The nice thing about XYZ is that it has a built-in luminance measurement. In PBRT 1 they used the luminance information to feed a tone mapper. I think in version 2 they decided that tone mapping was outside the scope of the book, since tone mapping isn't physically based, and they had EXR available as an output format. Hence, no need to convert color spaces.

phresnel
Posts: 6
Joined: Sat Jan 07, 2012 9:03 pm

### Re: Working Color Spaces

friedlinguini wrote:
phresnel wrote:They use XYZ to add up their sampled spectra per pixel, i.e. when R is their radiance sampled on a primary ray upon a pixel, they convert R to XYZ to build an average R/n for that pixel.
The nice thing about XYZ is that it has a built-in luminance measurement. In PBRT 1 they used the luminance information to feed a tone mapper. I think in version 2 they decided that tone mapping was outside the scope of the book, since tone mapping isn't physically based, and they had EXR available as an output format. Hence, no need to convert color spaces.
That's interesting to hear. Lux developers say the same in another thread I started, related to my current studies (http://www.luxrender.net/forum/viewtopi ... 25&t=10632):
Jeanphi wrote:
Lord Crc wrote: Yes above points should be correct. I'm rusty, jeanphi might correct me here, but there are two reasons I can think of off the top of my head why XYZ is nice to use instead of RGB. One is that the color matching functions are strictly non-negative (unlike RGB), and that you have Y, without further computations. This can be handy in different situations.
Yes, XYZ is an absolute colorspace (it doesn't depend on the rendering device) while RGB depends on the red, green, blue colors of the rendering device.
And yes, LuxRender uses Bradford matrices for color adaption when tuning light groups color.

Regarding sRGB conversion, sRGB also defines the gamma because monitor have non linear response curves, so if you have data in sRGB you must first convert to linear RGB (it doesn't change the colorspace but removes the gamma correction), then convert the linear color.

ypoissant
Posts: 97
Joined: Wed Nov 30, 2011 12:44 pm

### Re: Working Color Spaces

About three years ago, I experimented with all the different color spaces found on Lindbloom site plus several other color spaces I found elsewhere in publications and some of my own color spaces plus XYZ. I also used a 60 wavelength spectral rendering for reference. The scene was a Cornell box with a Gretag Macbeth chart in it. I had the spectra for all the Macbeth colors. For the color space experiments, I first converted the spectra to XYZ and then to the selected color space using different conversion method from a single sample in the middle of the filter center frequency to a whole filter envelope and rendered and did all the illumination calculations in these color spaces. Then converted the result to Lab for comparison. The comparison involved computing the pixel by pixel Lab distance from the reference spectral render.

In the 3 bands color spaces group, the winner was a color space I designed by dividing the visible bandwidth into 3 equal bands. The second best came from averaging the raw RGB filter spectra from a few digital cameras. These guys seem to know what they are doing. XYZ was relatively near the head. I have tabulated those Lab differences in a spreadsheet and I will try to find it for posting here. The winner overall was a 4 band color space RYGB if I remember right. Most of the other color spaces from Lindbloom site were too far off to consider.

However, in conclusion, I decided to internally use sRGB without the gamma correction which I call sRGB-g. The main reason is because all color samples available around are from sRGB devices or if unknown can be assumed to be in sRGB color space. Photos used for textures are usually in sRGB color space as well as any color selected from a color widget. So all input colors are de-gamma'd before using them for illumination calculations. Any non standard color space input colors must be converted to some common color space for calculations so it might just as well be sRGB-g. Since the output device is also assumed to be sRGB, then there are no need for color space conversion apart from adding the gamma correction. If a different output color space is needed, then sRGB-g is converted to XYZ and then to the other color space.

ypoissant
Posts: 97
Joined: Wed Nov 30, 2011 12:44 pm

### Re: Working Color Spaces

Here are the results in order of lowest to largest mean differences. I added dashes between columns in case the tabs would not format right on the forum. IOGU stands for infrared, orange, green, ultraviolet.

Color space - Method - Mean - Variance
RYGB - Sampled - 4,54965 - 4,7876
Wide RYGB - Smoothstep - 5,09692 - 11,4742
Wide RYGB - Sampled - 5,35925 - 6,07094
Equispace RGB - Splitted - 5,65845 - 10,5985
Camera RGB - Smoothstep - 5,75021 - 14,3903
Equispace RGB - Smoothstep - 6,35782 - 15,679
RYGB - Smoothstep - 6,7153 - 15,1159
XYZ - - 6,78778 - 29,1256
IOGU - Sampled - 8,09293 - 47,4824
IOGU - Smoothstep - 8,15884 - 48,5573
Rec 709 RGB - Splitted - 8,61403 - 35,7853
Wide RYGB - Gauss filtered - 8,75611 - 33,7381
Camera RGB - Sampled - 8,95558 - 30,6004
IOGU - Splitted - 8,96891 - 48,2302
Camera RGB - Splitted - 9,68708 - 18,92
IOGU - Gauss filtered - 10,498 - 67,4984
RYGB - Gauss filtered - 11,0605 - 46,2333
Camera RGB - Gauss filtered - 11,2147 - 57,9348
IOGU - Interpolated - 11,413 - 73,2648
Camera RGB - Interpolated - 12,2147 - 53,4798
Equispace RGB - Interpolated - 12,6107 - 80,2037
Wide RYGB - Splitted - 12,8257 - 38,3618
Wide RYGB - Interpolated - 14,6149 - 55,329
AC1C2 - Smoothstep - 14,7236 - 27,9729
AC1C2 - Sampled - 14,8421 - 23,8749
Equispace RGB - Gauss filtered - 14,8433 - 101,367
AC1C2 - Splitted - 16,1007 - 36,5681
Rec 709 RGB - Interpolated - 16,4862 - 115,397
AC1C2 - Gauss filtered - 17,1196 - 47,5004
RYGB - Interpolated - 17,3484 - 61,2076
RYGB - Splitted - 17,4102 - 44,5379
AC1C2 - Interpolated - 18,551 - 66,9343
Rec 709 RGB - Gauss filtered - 19,9693 - 123,341
Equispace RGB - Sampled - 23,4838 - 80,1973
Rec 709 RGB - Smoothstep - 23,4838 - 80,1973
Rec 709 RGB - Sampled - 69,6558 - 906,98

McAce
Posts: 7
Joined: Fri Feb 22, 2013 6:28 am

### Re: Working Color Spaces

Hi ypoissant.
ypoissant wrote:For the color space experiments, I first converted the spectra to XYZ and then to the selected color space using different conversion method from a single sample in the middle of the filter center frequency to a whole filter envelope and rendered and did all the illumination calculations in these color spaces.
Could you please elaborate on the filtering part? (I guess the second column of your table refers to that.) Which part of the conversion requires that and what is sampled exactly?

I've been thinking of each color space I know in terms of "a small set of functions (of wavelength) to which I store the coefficients needed to create a color spectrum as a linear combination of those functions". So I've always wondered why we don't just use your "dividing the visible bandwidth into 3 equal bands"-method for rendering. It is the 3-dimensional analog to high-dimensional spectral rendering.

Also, don't you lose a dimension when converting to XYZ first and then to a 4-dimensional space? Why not convert from the spectrum to the 4D space directly?

Thanks!

ypoissant
Posts: 97
Joined: Wed Nov 30, 2011 12:44 pm

### Re: Working Color Spaces

McAce wrote:Could you please elaborate on the filtering part? (I guess the second column of your table refers to that.) Which part of the conversion requires that and what is sampled exactly?

Also, don't you lose a dimension when converting to XYZ first and then to a 4-dimensional space? Why not convert from the spectrum to the 4D space directly?
Each of those color spaces were defined from their center wavelength.
Color space, Nb bands, Center wavelength[4]
{ "Digital Camera", 3, { 0.0f, 470.0f, 550.0f, 630.0f } },
{ "ITU Rec 709", 3, { 0.0f, 435.0f, 548.0f, 700.0f } },
{ "Equispaced RGB", 3, { 0.0f, 450.0f, 550.0f, 650.0f } },
{ "AC1C2", 4, { 456.0f, 490.0f, 557.0f, 631.0f } },
{ "RYGB", 4, { 460.0f, 515.0f, 570.0f, 625.0f } },
{ "Wide RYGB", 4, { 455.0f, 515.0f, 575.0f, 635.0f } },
{ "IOGU", 4, { 435.0f, 510.0f, 585.0f, 660.0f } },
{ "Prime colors", 3, { 0.0f, 450.0f, 530.0f, 600.0f } },
{ "Prime colors 2", 3, { 0.0f, 450.0f, 540.0f, 605.0f } },
{ "Color Scanner", 3, { 0.0f, 473.0f, 532.0f, 635.0f } },
{ "Sharp Colors", 3, { 0.0f, 450.0f, 540.0f, 620.0f } } };

Looking at the code, I have to modify my spectra to color space conversion description. For those "experimental" color space for which there were no published color space matrices I did not convert the spectra to XYZ. Instead, I directly converted the spectra to 3 or 4 bands representation and used those 3 or 4 band representations for illumination calculations. While doing the conversion, I also computed the from-XYZ and to-XYZ color space transformation matrices.

The spectra were converted using those methods:

Sampled : One single sample was taken at the provided central wavelengths.

Gaussian_Filtered : Spectrum samples were weighted according to a Gaussian filter centered at the provided wavelength and with a width that attempted to get an as flat as possible response when all the filters were added together.

Interpolated : A pyramid filter where the central wavelength is weighted 1 and the neighbors central wavelengths are weighted 0 with linear interpolation between central and neighbors.

Splitted : A box filter that includes all wavelengths between the mean wavelengths between central wavelengths.

SmoothStep_Filtered : A filter between a box and a Gaussian filter. I programmed this method after observing typical digital camera filters that were flatter and larger than Gaussian but not boxed. I adjusted the width of the smoothstep to visually match the typical form of digital camera filters.

I will try to find graphics of those filters and post them.
I've been thinking of each color space I know in terms of "a small set of functions (of wavelength) to which I store the coefficients needed to create a color spectrum as a linear combination of those functions". So I've always wondered why we don't just use your "dividing the visible bandwidth into 3 equal bands"-method for rendering. It is the 3-dimensional analog to high-dimensional spectral rendering.
The conversion from a reduced number of bands to Spectrum is not defined. There are an infinite number of conversions possible. The linear combination of capturing filters weighted by those coefficients will get you a Spectrum if you know the form of the capture filters used but the probability that this Spectrum looks like the original one is nearly nil. Even less if you don't know the form of the capture filter and yet even less if the coefficients were the result of some color transformation.

The reduction of dimensionality necessarily involve loss of information as several wavelengths are weighted together into one coefficient and we lose each individual wavelength weights.

ypoissant
Posts: 97
Joined: Wed Nov 30, 2011 12:44 pm

### Re: Working Color Spaces

Here are the filters and the methods in graphic form:
All Gaussian filters
Color Sapces Gaussian.jpg (96.98 KiB) Viewed 7786 times
Stectrum to bands filtering methods
Spectrum to Bands.jpg (76.18 KiB) Viewed 7786 times