23

色を操作するためのライブラリを作成し、計算しようとして立ち往生しましたTc(k)。私が読んだことから、CIE 1931 XYZ色空間で作業することが道であり、 を使用して取得できますxyY

これまでのところ、私は正しいものを理解するところまですべて正しいものを手に入れましxy

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

数字はグラフにかなり合っていますが、あなたがどのように行き来するかを詳しく説明するものは何も見つかりませxyTc(K)

ここに画像の説明を入力

例: #FF0000 の場合、次のようになります。

x: 0.64007449945677
y: 0.32997051063169

このトピックに関する多くの論文と、文字通りすべてのウィキペディアの記事を読みました。私がSOで遭遇したすべての質問は、計算のための実際の式を持っているものではなく、単に色に関するwiki記事にリンクしていますTc(k)

4

6 に答える 6

3

ウィキペディアの記事に基づいて、Color Temperature計算用の近似式を次のように Excelに入力しました。

=(-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

正常に動作します!

于 2014-04-12T12:55:48.220 に答える
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 '<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);
}

参照

私の出力:

出力

かなり近いですが、まだ 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;
}
于 2012-12-20T23:54:03.347 に答える
1

Found the Temperature to RGB solution written in JavaScript and converted it into 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));
于 2019-11-18T13:58:19.360 に答える
1

私があなたを正しく理解している場合は、いくつかの方法(簡単に:( )が説明されているこのPDFを参照してください。このPDFから

[CCT1] 計算は、CIE 1960 均一色空間座標 u および v を使用して実行されます。座標 u および v は、次の式を使用して x および y から導出されます: u = 4x/(12y-2x+3) および v = 6y/(12y- 2x+3) 相関色温度は、テスト ソースの u、v 座標に最も近い黒体の温度として定義されます。2 つの別々の方法で結果が得られます。1 つは定義に基づく反復法で、もう 1 つは事前に計算された 30 個の u、v、および逆勾配パラメーターのテーブルに基づく補間を含む一般的に使用される Robertson の方法です。反復 uS と vS がテスト ソースの値であり、uT と vT が温度 T での黒体値である場合、相関色温度は T の値です。

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

最小化されます。この関数の最小値を得るための温度 T の調整は、スプレッドシート (Quattro Pro 8 および Excel 97) を使用して行われました。両方のスプレッドシートで同じ値が得られました。

実際に役立つかどうかはわかりません。

于 2012-12-20T16:23:48.407 に答える
0

ウィキペディアによると、色温度はxyではなくUVの色度を考慮して計算されるため、変換を実行する必要があります。そうは言っても、@ sixlettervariablesによって提案されているように、近似値(Wikipediaでも説明されています)を使用することをお勧めします。

本当の問題は、何の色温度を見つけようとしているのかということです。RGB色への参照(#FF0000)が表示されます。これは、色空間を指定しないと意味がありません。sRGBを使用しているとすると(ウィキペディアをもう一度参照できます)、XYZに進む前に、まず線形RGB座標を取得する必要があります。

于 2012-12-29T06:07:05.100 に答える