Skip to content

Conversation

@9prady9
Copy link
Member

@9prady9 9prady9 commented Nov 17, 2016

Fixes #122

@9prady9 9prady9 added the fix label Nov 17, 2016
@9prady9 9prady9 added this to the 1.0.0 milestone Nov 17, 2016
@9prady9 9prady9 changed the title Colormap fixes WIP: Colormap fixes Nov 17, 2016
@9prady9 9prady9 mentioned this pull request Nov 17, 2016
@kryptan
Copy link

kryptan commented Nov 17, 2016

To compute sRGB color for a particular wavelength I would use the folllowing method:

  1. Calculate coordinates in the CIE XYZ colorspace for this wavelength. The method for computing XYZ values from a spectral radiance is described in Wikipedia. In our case spectral radiance is simply a Dirac delta function centered at the wavelength in question and all these integrals become equal to the color matching functions at this wavelength.
  2. Convert to linear sRGB.
  3. At least one of the R, G or B will be negative because this color will be outside of sRGB. The best thing to do here is probably to replace negative values with zero.

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.

@kryptan
Copy link

kryptan commented Nov 17, 2016

Google directed me to this weird website for the table values of color matching functions for the standard observer.

That's what I got:

spectrum

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}]]

@9prady9
Copy link
Member Author

9prady9 commented Nov 17, 2016

The one i have been referring to is this, which computes the rgb values for 380nm-780nm range. You can see the range of colors using that code at this page interactively.

@kryptan
Copy link

kryptan commented Nov 17, 2016

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.

@9prady9 9prady9 force-pushed the colormap_fixes branch 2 times, most recently from 0473b5c to b225137 Compare November 19, 2016 16:02
@9prady9
Copy link
Member Author

9prady9 commented Nov 19, 2016

@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.

spectrum

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;

@9prady9 9prady9 changed the title WIP: Colormap fixes Colormap fixes Nov 20, 2016
@9prady9
Copy link
Member Author

9prady9 commented Dec 5, 2016

@arrayfire/core-devel I think this is ready for merge, pls review.

@shehzan10
Copy link
Member

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.

@9prady9
Copy link
Member Author

9prady9 commented Dec 5, 2016

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.

@shehzan10
Copy link
Member

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.

@9prady9
Copy link
Member Author

9prady9 commented Dec 5, 2016

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.

@shehzan10 shehzan10 merged commit 2e8da87 into arrayfire:devel Dec 6, 2016
@9prady9 9prady9 deleted the colormap_fixes branch December 7, 2016 02:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants