Php 用K计算色温
我已经编写了一个用于处理颜色的库,并且一直在尝试计算Php 用K计算色温,php,c,colors,gimp,Php,C,Colors,Gimp,我已经编写了一个用于处理颜色的库,并且一直在尝试计算Tc(k)。从我所读到的内容来看,在XYZ颜色空间中工作是一条可行之路,可以使用xyY获得它 到目前为止,我已经把所有的事情都搞定了,从以下方面找出了正确的x和y: X Y x = ____________ y = ____________ ( X + Y + Z) ( X + Y + Z) 这些数字与图表非常接近,但找不到任何详细信息,说明如何从x和y到Tc(K) 对
Tc(k)
。从我所读到的内容来看,在XYZ
颜色空间中工作是一条可行之路,可以使用xyY
获得它
到目前为止,我已经把所有的事情都搞定了,从以下方面找出了正确的x
和y
:
X Y
x = ____________ y = ____________
( X + Y + Z) ( X + Y + Z)
这些数字与图表非常接近,但找不到任何详细信息,说明如何从x
和y
到Tc(K)
对于#FF0000,我得到以下信息
x: 0.64007449945677
y: 0.32997051063169
我已经读了很多关于这个话题的论文,几乎所有的维基百科文章都读过了。我遇到的所有问题都只是链接到一篇关于颜色的wiki文章,没有看到一篇有实际计算公式的文章。
Tc(k)
如果我理解正确,请参见这里,其中描述了许多方法(简要:()。从本PDF:
[CCT1]使用CIE 1960均匀颜色空间进行计算
坐标u和v。坐标u和v使用
公式:
u=4x/(12y-2x+3)和v=6y/(12y-2x+3)
相关色温定义为黑体的温度
最接近测试源的u、v坐标。提供两种不同的方法
结果:一种是基于定义的迭代法,另一种是
常用的Robertson方法,包括基于表30的插值
预先计算的u、v和反向坡度参数。
迭代
如果我们和vS
是测试源的值,以及uT和vT
是黑体值吗
在温度T下,相关色温为T值,其中:
调整温度T以获得该功能的最小值
使用电子表格(Quattro Pro 8和Excel 97)完成。两个电子表格都给出了
相同的值
不知道它是否真的对你有帮助。我在一些开源应用程序中做了一些挖掘,在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 '<h3>K -> RGB</h3>';
foreach ($temp as $k) {
$rgb = ColourConverter::temperature2rgb($k);
echo sprintf('<div style="background-color:rgb(%s); text-align: center; width: 100px; height: 25px; clear: both;">%s</div>', implode(', ', $rgb), $k);
}
echo '<h3>RGB -> K</h3>';
foreach ($hex as $v) {
$rgb = array_values(ColourConverter::hex2rgb($v));
$k = round(ColourConverter::rgb2temperature($rgb[0], $rgb[1], $rgb[2]));
echo sprintf('<div style="background-color:rgb(%s); text-align: center; width: 100px; height: 25px; clear: both;">%s</div>', implode(', ', $rgb), $k);
}
$temp=array(95007000550037503000027001500);
$hex=array('9DBEFF','E4EEFF','FFE4BE','FFA04C','FF7A26','FF6A19','FF500B','FF3403','FF2300');
回声'K->RGB';
foreach($k){
$rgb=颜色转换器::温度2RGB($k);
echo sprintf(“%s”,内爆(“,”,$rgb),$k);
}
回声“RGB->K”;
外汇(十六进制为$v){
$rgb=数组_值(colorConverter::hex2rgb($v));
$k=圆形(颜色转换器::rgb2temperature($rgb[0],$rgb[1],$rgb[2]);
echo sprintf(“%s”,内爆(“,”,$rgb),$k);
}
我的输出:
非常接近,但还不是100%。(在我的代码中找到了a,现在几乎完美了)
- 颜色稍微偏离k->rgb
- 做k->rgb->k不起作用。你不能回到相同的值
void Temperature\u to\u RGB(双T,双RGB[3])
{
INTC;
双xD,yD,X,Y,Z,最大值;
//适用于CIE日光光源
如果(t0.1;*T=(Tmax+Tmin)/2){
温度至RGB(*T,测试RGB);
if(testRGB[2]/testRGB[0]>RGB[2]/RGB[0])
Tmax=*T;
其他的
Tmin=*T;
}
*绿色=(testRGB[1]/testRGB[0])/(RGB[1]/RGB[0]);
如果(*绿色<0.2)*绿色=0.2;
如果(*绿色>2.5)*绿色=2.5;
}
维基百科声明,色温是通过考虑u-v色度而不是x-y来计算的,因此您必须进行转换。也就是说,我建议使用@sixlettervariables建议的近似值(也在维基百科中解释)
真正的问题是,你想找出的色温是多少?。我看到了RGB颜色的参考(#FF0000),如果不说明颜色空间,这是毫无意义的。假设你在sRGB中(所以我可以再次),您必须首先获得线性RGB坐标,然后才能继续进行XYZ。根据维基百科文章,我在Excel中输入了
色温计算的近似公式,如下所示:
=(-449*((R1-0332)/(S1-01858))^3)+(3525*((R1-0332)/(S1-01858))^2)-(6823,3*((R1-0332)/(S1-01858))+(5520,33)
很好!我意识到这是一个老问题,但我也在努力寻找答案。我最终发现了这个问题,并发布了如下公式:
n=(x-0.3320)/(0.1858-y)
CCT=437*n^3+3601*n^2+6861*n+5517
希望这能帮助其他仍在寻找的人。找到并将其转换为PHP
<?php
function colorTemperatureToRGB($kelvin)
{
$temp = $kelvin / 100;
$red = null;
$green = null;
$blue = null;
if ($temp <= 66)
{
$red = 255;
$green = $temp;
$green = 99.4708025861 * log($green) - 161.1195681661;
if ($temp <= 19)
{
$blue = 0;
}
else
{
$blue = $temp - 10;
$blue = 138.5177312231 * log($blue) - 305.0447927307;
}
}
else
{
$red = $temp - 60;
$red = 329.698727446 * pow($red, -0.1332047592);
$green = $temp - 60;
$green = 288.1221695283 * pow($green, -0.0755148492);
$blue = 255;
}
return [
'r' => clamp($red, 0, 255),
'g' => clamp($green, 0, 255),
'b' => clamp($blue, 0, 255)
];
}
function clamp($x, $min, $max)
{
if ($x < $min)
return $min;
if ($x > $max)
return $max;
return $x;
}
var_dump(colorTemperatureToRGB(7000));
您可以尝试其中一种。另一种方法是寻找颜色。黑体的颜色实际上是光谱,而不是纯光谱颜色。例如,颜色可以是白色,即使峰值颜色可能是绿色。任何公式都必须涉及通过分析棒和传感器的响应来确定等效的CIE颜色眼锥。嗨,朋友,链接坏了,你能更新这个答案吗?你引用了gist上的一个脚本,它自己引用了另一个sorce。你可以简单地引用它,因为它非常thourough@dogmatic69不完全是这样,gist提供了JavaScript现成的解决方案,但是是的,源链接值得一提-谢谢
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;
}
R1 is color space x coordinate from 0 to 1
S1 is color space y coordinate from 0 to 1
<?php
function colorTemperatureToRGB($kelvin)
{
$temp = $kelvin / 100;
$red = null;
$green = null;
$blue = null;
if ($temp <= 66)
{
$red = 255;
$green = $temp;
$green = 99.4708025861 * log($green) - 161.1195681661;
if ($temp <= 19)
{
$blue = 0;
}
else
{
$blue = $temp - 10;
$blue = 138.5177312231 * log($blue) - 305.0447927307;
}
}
else
{
$red = $temp - 60;
$red = 329.698727446 * pow($red, -0.1332047592);
$green = $temp - 60;
$green = 288.1221695283 * pow($green, -0.0755148492);
$blue = 255;
}
return [
'r' => clamp($red, 0, 255),
'g' => clamp($green, 0, 255),
'b' => clamp($blue, 0, 255)
];
}
function clamp($x, $min, $max)
{
if ($x < $min)
return $min;
if ($x > $max)
return $max;
return $x;
}
var_dump(colorTemperatureToRGB(7000));