用K计算色温

我已经编写了一个用于处理颜色的库,并试图计算Tc(k) 。 根据我在CIE 1931 XYZ色彩空间中的工作xyY ,可以使用xyY获得。

到目前为止,我已经将所有内容都弄正确,以便从中找出正确的xy

  XY x = ____________ y = ____________ ( X + Y + Z) ( X + Y + Z) 

数字远远超出图表,但无法找到任何详细说明如何从xyTc(K)

在此处输入图像描述

例如:对于#FF0000,我得到以下内容。

 x: 0.64007449945677 y: 0.32997051063169 

我已经阅读了很多关于这个主题的论文,并且阅读了所有维基百科的文章。 我在SO上遇到的所有问题只是链接到关于颜色的维基文章,没有看到具有计算Tc(k)的实际公式的文章

如果我理解正确,请参阅此pdf ,其中描述了许多方法(简要说明:()。来自此PDF:

[CCT1]使用CIE 1960均匀颜色空间坐标u和v进行计算。坐标u和v使用以下公式从x和y导出:u = 4x /(12y-2x + 3)和v = 6y /(12y- 2x + 3)相关色温定义为最靠近测试源的u,v坐标的黑体温度。 两种不同的方法提供结果:一种是基于定义的迭代方法,另一种是常用的Robertson方法,涉及基于30个预先计算的u,v和反斜率参数的表格进行插值。 迭代如果uS和vS是测试源的值,并且uT和vT是温度T下的黑体值,则相关色温是T的值,其中:

 sqrt( (uS - uT)^2 + (vS - vT)^2 ) 

最小化。 使用电子表格(Quattro Pro 8和Excel 97)调整温度T以获得此function的最小值。 两个电子表格都给出了相同的值。

不知道它是否真的对你有帮助。

根据维基百科的文章,我输入了Excel中Color Temperature计算的近似公式

=(-449*((R1-0,332)/(S1-0,1858))^3)+(3525*((R1-0,332)/(S1-0,1858))^2)-(6823,3*((R1-0,332)/(S1-0,1858)))+(5520,33)

 R1 is color space x coordinate from 0 to 1 S1 is color space y coordinate from 0 to 1 

工作良好!

我在一些开源应用程序中做了一些挖掘,并在UFRaw中找到了一些东西。 我还没弄清楚到底发生了什么。

还找到了一篇似乎很好地涵盖这个主题的论文 。

转换为PHP,这是我到目前为止:

 $temp = array(9500, 7000, 5500, 3750, 3000, 2700, 2250, 1800, 1500); $hex = array('9DBEFF', 'E4EEFF', 'FFE4BE', 'FFA04C', 'FF7A26', 'FF6A19', 'FF500B', 'FF3403', 'FF2300'); echo '

K -> RGB

'; foreach ($temp as $k) { $rgb = ColourConverter::temperature2rgb($k); echo sprintf('
%s
', implode(', ', $rgb), $k); } echo '

RGB -> K

'; foreach ($hex as $v) { $rgb = array_values(ColourConverter::hex2rgb($v)); $k = round(ColourConverter::rgb2temperature($rgb[0], $rgb[1], $rgb[2])); echo sprintf('
%s
', implode(', ', $rgb), $k); }

参考

我的输出:

产量

非常接近但不是100%。 (在我的代码中发现了一个错误 ,它现在几乎是完美的)

  • 从k – > rgb稍微偏离颜色
  • 它不起作用k – > rgb – > k。 你没有回到相同的价值。

UFRaw线246-294

 void Temperature_to_RGB(double T, double RGB[3]) { int c; double xD, yD, X, Y, Z, max; // Fit for CIE Daylight illuminant if (T <= 4000) { xD = 0.27475e9 / (T * T * T) - 0.98598e6 / (T * T) + 1.17444e3 / T + 0.145986; } else if (T <= 7000) { xD = -4.6070e9 / (T * T * T) + 2.9678e6 / (T * T) + 0.09911e3 / T + 0.244063; } else { xD = -2.0064e9 / (T * T * T) + 1.9018e6 / (T * T) + 0.24748e3 / T + 0.237040; } yD = -3 * xD * xD + 2.87 * xD - 0.275; // Fit for Blackbody using CIE standard observer function at 2 degrees //xD = -1.8596e9/(T*T*T) + 1.37686e6/(T*T) + 0.360496e3/T + 0.232632; //yD = -2.6046*xD*xD + 2.6106*xD - 0.239156; // Fit for Blackbody using CIE standard observer function at 10 degrees //xD = -1.98883e9/(T*T*T) + 1.45155e6/(T*T) + 0.364774e3/T + 0.231136; //yD = -2.35563*xD*xD + 2.39688*xD - 0.196035; X = xD / yD; Y = 1; Z = (1 - xD - yD) / yD; max = 0; for (c = 0; c < 3; c++) { RGB[c] = X * XYZ_to_RGB[0][c] + Y * XYZ_to_RGB[1][c] + Z * XYZ_to_RGB[2][c]; if (RGB[c] > max) max = RGB[c]; } for (c = 0; c < 3; c++) RGB[c] = RGB[c] / max; } void RGB_to_Temperature(double RGB[3], double *T, double *Green) { double Tmax, Tmin, testRGB[3]; Tmin = 2000; Tmax = 23000; for (*T = (Tmax + Tmin) / 2; Tmax - Tmin > 0.1; *T = (Tmax + Tmin) / 2) { Temperature_to_RGB(*T, testRGB); if (testRGB[2] / testRGB[0] > RGB[2] / RGB[0]) Tmax = *T; else Tmin = *T; } *Green = (testRGB[1] / testRGB[0]) / (RGB[1] / RGB[0]); if (*Green < 0.2) *Green = 0.2; if (*Green > 2.5) *Green = 2.5; } 

维基百科指出,色温是通过考虑紫外色度而非xy来计算的,因此您必须执行平移。 也就是说,我建议使用@sixlettervariables建议的近似值(也在维基百科中解释)。

真正的问题是,你想找到什么色温? 我看到RGB颜色的参考(#FF0000),没有说明颜色空间,这是没有意义的。 假设你在sRGB(所以我可以再次指向维基百科 ),你必须首先获得线性RGB坐标才能进入XYZ。

我意识到这是一个古老的问题,但我也在努力寻找答案。 我终于遇到了这个漂亮的计算器 ,它也发布了如下公式:

n =(x-0.3320)/(0.1858-y)

CCT = 437 * n ^ 3 + 3601 * n ^ 2 + 6861 * n + 5517

希望这可以帮助任何仍在寻找的人。