最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Converting CSS Lch to RGB - Stack Overflow

programmeradmin6浏览0评论

I wanted to convert a CSS Lch color string like:

--my-color: lch(20% 8.5 220.0);

To an RGB hex code. I tried using tools like chroma's Lch parser, but all of them seem to use absolute values for the first ordinate (the 20% in my case).

Is there some standard way to convert that 20% into the lightness values used by most Lch conversion tools?

I wanted to convert a CSS Lch color string like:

--my-color: lch(20% 8.5 220.0);

To an RGB hex code. I tried using tools like chroma's Lch parser, but all of them seem to use absolute values for the first ordinate (the 20% in my case).

Is there some standard way to convert that 20% into the lightness values used by most Lch conversion tools?

Share Improve this question edited Sep 17, 2020 at 8:20 mkrieger1 23.5k7 gold badges64 silver badges82 bronze badges asked Sep 17, 2020 at 0:58 user2662833user2662833 1,0731 gold badge12 silver badges21 bronze badges 2
  • first w3/TR/css-color-4/#lch-to-lab then w3/TR/css-color-4/#lab-to-rgb – Kaiido Commented Sep 17, 2020 at 1:26
  • You can just scale, if you have different ranges. BTW, it is not a good question writing "used by most ...". We have no idea on which tools you consider (and your field). You should always specify range and colour space (in question, but remember to write it also in the code, or next time it will take huge amount of time to find out errors and your definition). – Giao Catenazzi Commented Sep 17, 2020 at 7:19
Add a ment  | 

4 Answers 4

Reset to default 4

A JS-native CanvasRenderingContext2D instance can read any CSS-formatted color (as a string) and write it in a RGBA buffer (0 to 255) for you :

const myCssColor  = "lch(20% 8.5 220.0)";

function cssColor_to_rgba255Color(string) {
    const canvas = document.createElement("canvas");
    canvas.width = canvas.height = 1;
    const ctx = canvas.getContext("2d", {willReadFrequently: true});
    ctx.fillStyle = string;
    ctx.fillRect(0, 0, 1, 1);
    return ctx.getImageData(0, 0, 1, 1).data;
}

const rgba = cssColor_to_rgba255Color(myCssColor);

console.log( rgba[0], rgba[1], rgba[2], rgba[3] );
// 33 51 56 255

This function may have poor performance but can be greatly optimized by always recycling (using clearRect) the same "ctx" object.

The w3c is working on a draft and there is example code in javascript attached (it's a bit too long to post here and you'll need higher math to do that (at least sin and the power of 2.4).

I can give you this function that I wrote for myself from LCH to HEX, or RGB if you want. I wrote it in PHP, so it's easy to adapt to any other language

function lch2hex($l, $c, $h) {
  $a=round($c*cos(deg2rad($h)));
  $b=round($c*sin(deg2rad($h)));
  unset($c,$h);
  
  // Reference white values for D65 Light Europe Observer
  // $xw = 0.95047;
  // $yw = 1.00000;
  // $zw = 1.08883;
  
  // Reference white values for CIE 1964 10° Standard Observer
  $xw = 0.948110;
  $yw = 1.00000;
  $zw = 1.07304;
  
  // Compute intermediate values
  $fy = ($l + 16) / 116;
  $fx = $fy + ($a / 500);
  $fz = $fy - ($b / 200);
  
  // Compute XYZ values
  $x = round($xw * (($fx ** 3 > 0.008856) ? $fx ** 3 : (($fx - 16 / 116) / 7.787)),5);
  $y = round($yw * (($fy ** 3 > 0.008856) ? $fy ** 3 : (($fy - 16 / 116) / 7.787)),5);
  $z = round($zw * (($fz ** 3 > 0.008856) ? $fz ** 3 : (($fz - 16 / 116) / 7.787)),5);
  unset($l,$a,$b,$xw,$yw,$zw,$fy,$fx,$fz);
  
  $r = $x * 3.2406 - $y * 1.5372 - $z * 0.4986;
  $g = -$x * 0.9689 + $y * 1.8758 + $z * 0.0415;
  $b = $x * 0.0557 - $y * 0.2040 + $z * 1.0570;
  unset($x,$y,$z);

  $r = $r > 0.0031308 ? 1.055 * pow($r, 1 / 2.4) - 0.055 : 12.92 * $r;
  $g = $g > 0.0031308 ? 1.055 * pow($g, 1 / 2.4) - 0.055 : 12.92 * $g;
  $b = $b > 0.0031308 ? 1.055 * pow($b, 1 / 2.4) - 0.055 : 12.92 * $b;

  $r = round(max(min($r, 1), 0) * 255);
  $g = round(max(min($g, 1), 0) * 255);
  $b = round(max(min($b, 1), 0) * 255);
  
  return '#' . sprintf('%02X%02X%02X', $r, $g, $b);
  }

You can now use OffscreenCanvas to create the canvas context:

function cssColor_to_rgba255Color(string) {
  const ctx = new OffscreenCanvas(1, 1).getContext('2d')
  ctx.fillStyle = string;
  ctx.fillRect(0, 0, 1, 1);
  return ctx.getImageData(0, 0, 1, 1).data;
}

const input = document.querySelector('input')
const span = document.querySelector('span')

input.addEventListener('input', updateOutput)
updateOutput()

function updateOutput() {
  span.textContent = cssColor_to_rgba255Color(input.value).join(' ')
}
<input value="lch(20% 8.5 220.0)" />
<br/>
<br/>
RGBA: <span></span>

发布评论

评论列表(0)

  1. 暂无评论