Zrobiłem trochę kopania w niektórych aplikacjach open source i znalazłem coś w UFRaw. Nie do końca zrozumiałem, co się dzieje.
Znaleźliśmy również paper, który wydaje się dość dobrze omawiać temat.
przeliczona na php i to, co mam tak daleko:
$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);
}
Moja wyjściowa:
Całkiem blisko, ale jeszcze nie w 100%. (Znaleziono bug w moim kodu i jest teraz prawie idealny)
- Kolory są nieco się dzieje z k -> RGB
- To nie działa w ten k -> RGB -> K. Nie powrócisz do tej samej wartości.
Kod
UFRaw line 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;
}
Możesz wypróbować jedną z tych [przybliżonych wartości temperatury kolorów] (http://en.wikipedia.org/wiki/Color_temperature#Approximation). Po drugie szukacie [locus Planckian] (http://en.wikipedia.org/wiki/Planckian_locus#Approximation). – user7116
Kolor czarnego ciała jest w rzeczywistości spektrum, a nie czystym spektralnym kolorem. Na przykład kolor może być biały, nawet jeśli pik koloru może być zielony. Jakakolwiek formuła musiałaby obejmować ustalenie równoważnego koloru CIE poprzez analizę odpowiedzi prętów i stożków oka. – UncleO