Closed 9prady9 closed 7 years ago
To compute sRGB color for a particular wavelength I would use the folllowing method:
Once we've computed linear sRGB colors for each wavelength that we are interested in we need to normalize colors so that they will fit in 0-1 range (i.e. simply divide them by the maximum value).
Now we can apply the gamma to these colors get the proper sRGB.
Google directed me to this weird website for the table values of color matching functions for the standard observer.
That's what I got:
The range is 390 - 830 nm.
I used the following Mathematica code to produce the image above.
fs = Import[
FileNameJoin[{NotebookDirectory[], "./lin2012xyz2e_5_7sf.csv"}]];
fs = Transpose[fs];
mf = fs[[2 ;; 4]];
srgb = {{3.2406, -1.5372, -0.4986}, {-0.9689, 1.8758,
0.0415}, {0.0557, -0.2040, 1.0570}}.mf/2.7;
srgb = Map[Max[0, #] &, srgb, {2}];
srgbNL = Map[#^(1/2.2) &, srgb, {2}];
spectrum = Map[ListInterpolation, srgbNL];
n = 500;
Image[Table[{spectrum[[1]][1 + i*88/n], spectrum[[2]][1 + i*88/n],
spectrum[[3]][1 + i*88/n]}, {j, 1, 100}, {i, 0, n}]]
Yes, I've read those. The comment in the original FORTRAN program says:
The red, green and blue values (RGB) are assumed to vary linearly with wavelength.
But I don't think this is true. There are good mathematical models of human vision and one can precisely calculate sRGB color corresponding to any wavelength or to any combination of wavelengths without such assumptions.
@kryptan Thank you for the clarification. Took me some time to understand the Mathematica code stub you shared, but was finally able to create the following octave script to generate the visible spectrum colours in sRGB space. I think i got it correct this time, the colormap shows up as expected.
lin2012xyz2e_5_7sf = csvread("lin2012xyz2e_1_7sf.csv");
lambda = transpose(lin2012xyz2e_5_7sf(:,1));
lms = transpose(lin2012xyz2e_5_7sf(:,2:4));
XYZ_to_sRGB = [3.2404542, -1.5371385, -0.4985314;
-0.9692660, 1.8760108, 0.0415560;
0.0556434, -0.2040259, 1.0572252];
lrgb = XYZ_to_sRGB * lms;
crgb = lrgb / max(max(lrgb));
crgb = (crgb > 0.0) .* crgb;
bt = (abs(crgb) <= 0.0031308)*12.92.*abs(crgb);
at = (abs(crgb) > 0.0031308).*(1.055*(abs(crgb).^(1/2.4))-0.055);
srgb = bt+at;
wvl_2s = 390:1.72:830;
rInter = spline(lambda, srgb(1, :), wvl_2s);
gInter = spline(lambda, srgb(2, :), wvl_2s);
bInter = spline(lambda, srgb(3, :), wvl_2s);
rgb = [rInter; gInter; bInter];
rgb = (rgb > 0.0) .* rgb;
@arrayfire/core-devel I think this is ready for merge, pls review.
Looks good to me except for changing Colors->Rainbow. I'm not against rainbow. It's whether changing the enum makes a significant difference to cause problems to users.
The reason i changed it is to make sense of the colormap that enum value represents. Colors was too generic to describe anything at all.
The reason i changed it is to make sense of the colormap that enum value represents. Colors was too generic to describe anything at all.
I understand the reasoning and agree with it. That's why I'm not against the name itself.
As far as ArrayFire-Forge inter-operation, we should not see any issues as the enum value itself didn't change. Since forge 1.0 is not released, we can change this name without any repercussions.
Fixes #122