【问题标题】:Calculate colour temperature in K以 K 计算色温
【发布时间】:2012-12-08 04:39:45
【问题描述】:

我已经编写了一个用于处理颜色的库,并且一直在尝试计算 Tc(k)。从我读到的在CIE 1931XYZ 色彩空间中工作是可行的方法,可以使用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)

【问题讨论】:

  • 您可以尝试其中一种approximations for color temperature。对于另一种方式,您正在寻找Planckian locus
  • 黑体的颜色实际上是光谱,而不是纯光谱颜色。例如,颜色可以是白色,即使峰值颜色可能是绿色。任何公式都必须涉及通过分析眼睛的视杆和视锥细胞的反应来确定等效的 CIE 颜色。

标签: php c colors gimp


【解决方案1】:

根据 Wikipedia 文章,我将 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

工作正常!

【讨论】:

    【解决方案2】:

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

    [CCT1] 使用 CIE 1960 统一色彩空间执行计算 坐标 u 和 v。坐标 u 和 v 由 x 和 y 使用 公式: u = 4x/(12y-2x+3) 和 v = 6y/(12y-2x+3) 相关色温定义为黑体的温度 最接近测试源的 u,v 坐标。两种不同的方法提供 结果:一个是基于定义的迭代方法,另一个是 常用的罗伯逊方法涉及基于 30 表的插值 预先计算的 u、v 和反斜率参数。 迭代 如果我们和vS 是测试源的值,uT 和 vT 是黑体值 在温度 T 下,相关色温是 T 的值,其中:

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

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

    不知道对你有没有帮助。

    【讨论】:

      【解决方案3】:

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

      还找到了一个paper,似乎很好地涵盖了该主题。

      转换为 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%。 (在我的代码中找到了bug,现在几乎完美了)

      • 颜色从 k -> rgb 略微偏离
      • k -> rgb -> k 不起作用。您不会恢复到相同的值。

      代码

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

      【讨论】:

      • 嗨朋友,链接坏了,你能更新这个答案吗?
      【解决方案4】:

      找到Temperature to RGB solution written in JavaScript并将其转换为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));
      

      【讨论】:

      • 您在 gist 上引用了一个脚本,它自己引用了另一个源。您可以简单地引用它,因为它非常彻底tannerhelland.com/4435/convert-temperature-rgb-algorithm-code
      • @dogmatic69 不完全是,GIST 提供了现成的 JavaScript 解决方案,但是是的,源链接值得一提 - 谢谢
      【解决方案5】:

      维基百科指出色温是通过考虑 u-v 色度而不是 x-y 来计算的,因此您必须执行转换。也就是说,我建议使用@sixlettervariables 建议的近似值(也在维基百科中解释过)。

      真正的问题是,您要查找的色温是多少?我看到了对 RGB 颜色的引用 (#FF0000),如果没有说明颜色空间,这些颜色就毫无意义。假设您在 sRGB 中(所以我可以再次point you at Wikipedia),您必须先获取线性 RGB 坐标,然后再进行 XYZ。

      【讨论】:

        【解决方案6】:

        我意识到这是一个老问题,但我也在努力寻找答案。我终于遇到了这个nifty calculator,它还发布了如下公式:

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

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

        希望这对仍在寻找的其他人有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-07-24
          • 2010-11-04
          • 1970-01-01
          • 1970-01-01
          • 2015-08-13
          • 1970-01-01
          • 1970-01-01
          • 2021-09-28
          相关资源
          最近更新 更多