【问题标题】:RGB to XYZ and LAB colours conversionRGB 到 XYZ 和 LAB 颜色转换
【发布时间】:2013-03-14 11:53:21
【问题描述】:

我在将颜色从 RGB 转换为 LAB 空间时遇到问题 使用here 中的公式应该是直截了当的,只是我得到了错误的值

  • RGB = 56,79,132

  • X = 8.592

  • Y = 8.099
  • Z = 22.940

和 CIE-L*ab 一样

  • 长* 34.188
  • a* 8.072
  • b* -32.478

这是我的代码;但我看不出哪里出错了。这可能是由于我之前的fella 这样的浮点数。谢谢。

// user colour
var Red   = 56;
var Green = 79;
var Blue  = 132;

// user colour converted to XYZ space
XYZ = RGBtoXYZ(Red,Green,Blue)
var colX = XYZ[0];
var colY = XYZ[1];
var colZ = XYZ[2];

// alert(XYZ)

LAB = XYZtoLAB(colX, colY, colZ)

alert(LAB)

function RGBtoXYZ(R, G, B)
{
    var_R = parseFloat( R / 255 )        //R from 0 to 255
    var_G = parseFloat( G / 255 )        //G from 0 to 255
    var_B = parseFloat( B / 255 )        //B from 0 to 255

    if ( var_R > 0.04045 ) var_R = ( ( var_R + 0.055 ) / 1.055 ) ^ 2.4
    else                   var_R = var_R / 12.92
    if ( var_G > 0.04045 ) var_G = ( ( var_G + 0.055 ) / 1.055 ) ^ 2.4
    else                   var_G = var_G / 12.92
    if ( var_B > 0.04045 ) var_B = ( ( var_B + 0.055 ) / 1.055 ) ^ 2.4
    else                   var_B = var_B / 12.92

    var_R = var_R * 100
    var_G = var_G * 100
    var_B = var_B * 100

    //Observer. = 2°, Illuminant = D65
    X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805
    Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
    Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505
    return [X, Y, Z]
}


function XYZtoLAB(x, y, z)
{
    var ref_X =  95.047;
    var ref_Y = 100.000;
    var ref_Z = 108.883;

    var_X = x / ref_X          //ref_X =  95.047   Observer= 2°, Illuminant= D65
    var_Y = y / ref_Y          //ref_Y = 100.000
    var_Z = z / ref_Z          //ref_Z = 108.883

    if ( var_X > 0.008856 ) var_X = var_X ^ ( 1/3 )
    else                    var_X = ( 7.787 * var_X ) + ( 16 / 116 )
    if ( var_Y > 0.008856 ) var_Y = var_Y ^ ( 1/3 )
    else                    var_Y = ( 7.787 * var_Y ) + ( 16 / 116 )
    if ( var_Z > 0.008856 ) var_Z = var_Z ^ ( 1/3 )
    else                    var_Z = ( 7.787 * var_Z ) + ( 16 / 116 )

    CIE_L = ( 116 * var_Y ) - 16
    CIE_a = 500 * ( var_X - var_Y )
    CIE_b = 200 * ( var_Y - var_Z )

return [CIE_L, CIE_a, CIE_b]
}

【问题讨论】:

    标签: javascript rgb


    【解决方案1】:

    我很确定 ^ 在 javascript 中是按位异或,而不是幂运算符。我认为Math.pow 是您正在寻找的。

    【讨论】:

      【解决方案2】:
      /**
       * Converts RGB color to CIE 1931 XYZ color space.
       * https://www.image-engineering.de/library/technotes/958-how-to-convert-between-srgb-and-ciexyz
       * @param  {string} hex
       * @return {number[]}
       */
      export function rgbToXyz(hex) {
          const [r, g, b] = hexToRgb(hex).map(_ => _ / 255).map(sRGBtoLinearRGB)
          const X =  0.4124 * r + 0.3576 * g + 0.1805 * b
          const Y =  0.2126 * r + 0.7152 * g + 0.0722 * b
          const Z =  0.0193 * r + 0.1192 * g + 0.9505 * b
          // For some reason, X, Y and Z are multiplied by 100.
          return [X, Y, Z].map(_ => _ * 100)
      }
      
      /**
       * Undoes gamma-correction from an RGB-encoded color.
       * https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation
       * https://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color
       * @param  {number}
       * @return {number}
       */
      function sRGBtoLinearRGB(color) {
          // Send this function a decimal sRGB gamma encoded color value
          // between 0.0 and 1.0, and it returns a linearized value.
          if (color <= 0.04045) {
              return color / 12.92
          } else {
              return Math.pow((color + 0.055) / 1.055, 2.4)
          }
      }
      
      /**
       * Converts hex color to RGB.
       * https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
       * @param  {string} hex
       * @return {number[]} [rgb]
       */
      function hexToRgb(hex) {
          const match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
          if (match) {
              match.shift()
              return match.map(_ => parseInt(_, 16))
          }
      }
      
      /**
       * Converts CIE 1931 XYZ colors to CIE L*a*b*.
       * The conversion formula comes from <http://www.easyrgb.com/en/math.php>.
       * https://github.com/cangoektas/xyz-to-lab/blob/master/src/index.js
       * @param   {number[]} color The CIE 1931 XYZ color to convert which refers to
       *                           the D65/2° standard illuminant.
       * @returns {number[]}       The color in the CIE L*a*b* color space.
       */
      // X, Y, Z of a "D65" light source.
      // "D65" is a standard 6500K Daylight light source.
      // https://en.wikipedia.org/wiki/Illuminant_D65
      const D65 = [95.047, 100, 108.883]
      export function xyzToLab([x, y, z]) {
        [x, y, z] = [x, y, z].map((v, i) => {
          v = v / D65[i]
          return v > 0.008856 ? Math.pow(v, 1 / 3) : v * 7.787 + 16 / 116
        })
        const l = 116 * y - 16
        const a = 500 * (x - y)
        const b = 200 * (y - z)
        return [l, a, b]
      }
      
      /**
       * Converts Lab color space to Luminance-Chroma-Hue color space.
       * http://www.brucelindbloom.com/index.html?Eqn_Lab_to_LCH.html
       * @param  {number[]}
       * @return {number[]}
       */
      export function labToLch([l, a, b]) {
          const c = Math.sqrt(a * a + b * b)
          const h = abToHue(a, b)
          return [l, c, h]
      }
      
      /**
       * Converts a and b of Lab color space to Hue of LCH color space.
       * https://stackoverflow.com/questions/53733379/conversion-of-cielab-to-cielchab-not-yielding-correct-result
       * @param  {number} a
       * @param  {number} b
       * @return {number}
       */
      function abToHue(a, b) {
          if (a >= 0 && b === 0) {
              return 0
          }
          if (a < 0 && b === 0) {
              return 180
          }
          if (a === 0 && b > 0) {
              return 90
          }
          if (a === 0 && b < 0) {
              return 270
          }
          let xBias
          if (a > 0 && b > 0) {
              xBias = 0
          } else if (a < 0) {
              xBias = 180
          } else if (a > 0 && b < 0) {
              xBias = 360
          }
          return radiansToDegrees(Math.atan(b / a)) + xBias
      }
      
      function radiansToDegrees(radians) {
          return radians * (180 / Math.PI)
      }
      
      function degreesToRadians(degrees) {
          return degrees * Math.PI / 180
      }
      
      

      【讨论】:

      • "// 出于某种原因,X、Y 和 Z 乘以 100。" - 是的,可能那个 XYZ 的错误位置应该是 0 到 1。实验室的亮度从 0 到 100,这可能就是他们这样做的原因。
      【解决方案3】:

      function xyzc(c){return ((c/255)&gt;0.04045)?Math.pow((((c/255)+0.055)/1.055),2.4)*100:(c/255)/12.92*100;}

      此行会将 rgb 通道转换为 XYZ

      【讨论】:

      • 不,不会,这也是 sRGB,不是 RGB(12.92 数字)。这只是使用 sRGB 曲线将 R'G'B' 转换为线性 RGB。 XYZ 需要特殊矩阵,具体取决于线性光(线性 RGB)现在是什么原色。
      猜你喜欢
      • 2020-03-17
      • 2020-03-16
      • 2018-11-07
      • 2011-06-03
      • 2023-04-11
      • 2018-08-13
      • 2011-01-22
      • 1970-01-01
      相关资源
      最近更新 更多