如何将从解析的PSD中得到的颜色对象转换为可用的RGBA。

huangapple go评论61阅读模式
英文:

How to convert color object from parsed PSD into usable RGBA

问题

我正在解析一个PSD,获取正常的RGBA值,最近我遇到了这些奇怪的浮点颜色值:

{
  "red": 1.0343483686447144,
  "green": 0.9487225413322449,
  "blue": -0.12634865939617157,
  "alpha": 100,
  "rgba": "rgba(1.0343483686447144, 0.9487225413322449, -0.12634865939617157, 1)"
}

这是我的解析函数:

function getRGBColor(color, opacity = 100) {
   if ("Clr " in color) {
      color = color["Clr "];
   }

   var type = color.class.id;
   var red = color["Rd  "];
   var green = color["Grn "];
   var blue = color["Bl  "];

   if ("blueFloat" in color) {
      red = color.redFloat;
      green = color.greenFloat;
      blue = color.blueFloat;
   }

   var rgba = {
      red: red, 
      green: green,
      blue: blue,
      alpha: opacity,
      rgba: `rgba(${red}, ${green}, ${blue}, ${opacity/100})`
   }

   return rgba;
}

它应该是黄色的。

这个对象来自于strokeColorContent

var vectorMask = node.get("vectorMask")?.export();
var vectorStroke = node.get("vectorStroke")?.data;
var vectorStrokeContent = node.get("vectorStrokeContent")?.data;
var fillColor = getRGBColor(vectorStrokeContent);

相关问题:
https://stackoverflow.com/q/75761808/441016

更新:
我已经更新了CSS以使用建议的lab()颜色空间,似乎有效:

lab(94 -12 103)

我还没有确认alpha值,但这似乎有效:

lab(94 -12 103 / 1)

在大多数浏览器中似乎支持lab()(目前不支持Firefox,但在Firefox 113中支持)。

要获取rgba()值,需要从lab到rgba的公式。

英文:

I'm parsing a PSD getting normal RGBA values and recently I encountered this strange float color values:

{
  "red": 1.0343483686447144,
  "green": 0.9487225413322449,
  "blue": -0.12634865939617157,
  "alpha": 100,
  "rgba": "rgba(1.0343483686447144, 0.9487225413322449, -0.12634865939617157, 1)"
}

Here is my parsing function:

function getRGBColor(color, opacity = 100) {
   if ("Clr " in color) {
      color = color["Clr "];
   }

   var type = color.class.id;
   var red = color["Rd  "];
   var green = color["Grn "];
   var blue = color["Bl  "];

   if ("blueFloat" in color) {
      red = color.redFloat;
      green = color.greenFloat;
      blue = color.blueFloat;
   }

   var rgba = {
      red: red, 
      green: green,
      blue: blue,
      alpha: opacity,
      rgba: `rgba(${red}, ${green}, ${blue}, ${opacity/100})`
   }

   return rgba;
}

It's supposed to be yellow.

The object is coming from strokeColorContent.

     var vectorMask = node.get("vectorMask")?.export();
     var vectorStroke = node.get("vectorStroke")?.data;
     var vectorStrokeContent = node.get("vectorStrokeContent")?.data;
     var fillColor = getRGBColor(vectorStrokeContent);

如何将从解析的PSD中得到的颜色对象转换为可用的RGBA。

Related question:
https://stackoverflow.com/q/75761808/441016

Update:
I've updated the CSS to use the lab() color space as suggested and it seems to work:

lab(94 -12 103)

I haven't confirmed the alpha value yet but this seems to work:

lab(94 -12 103 / 1)  

It seems that, in most browsers, lab() is being supported (not currently in Firefox but in Firefox 113).

To get the rgba() value there needs to be a formula from lab to rgba.

答案1

得分: 1

显然,psd.js 的颜色输出对象将LAB值与RGB值混淆

不幸的是,你只能将LAB转换为更通用的RGB近似值。

你不能精确地将LAB转换为RGB(没有目标颜色空间的定义)

LAB颜色系统的整个理念是提供一种表示人眼可辨别的所有颜色的系统,作为所有种类颜色转换的参考颜色空间。

解决方法:通用RGB近似:

假设你的psd使用了更通用的RGB颜色配置文件,例如类似于sRGB,你可以使用antimatter15的rgb-lab库

let psdCols = {
  "red": 1.0343483686447144,
  "green": 0.9487225413322449,
  "blue": -0.12634865939617157,
  "alpha": 100,
}

let labRGBAVals = [[psdCols.green, psdCols.blue, psdCols.red].map(val => +(val * 100).toFixed(0)), psdCols.alpha / 100].flat();

console.log('LAB values: ', labRGBAVals.join(' '));

let rgba = lab2rgb(labRGBAVals).map(val => +(val).toFixed(0));

labToRgb.style.backgroundColor = `rgba( ${rgba.join(', ')} )`
console.log('RGB values: ', rgba)

/**
 * 基于
 * https://github.com/antimatter15/rgb-lab/blob/master/color.js
 */
function lab2rgb(lab) {
  let y = (lab[0] + 16) / 116,
    x = lab[1] / 500 + y,
    z = y - lab[2] / 200,
    r, g, b;

  x = 0.95047 * ((x * x * x > 0.008856) ? x * x * x : (x - 16 / 116) / 7.787);
  y = 1.00000 * ((y * y * y > 0.008856) ? y * y * y : (y - 16 / 116) / 7.787);
  z = 1.08883 * ((z * z * z > 0.008856) ? z * z * z : (z - 16 / 116) / 7.787);

  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;

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

  return [Math.max(0, Math.min(1, r)) * 255,
    Math.max(0, Math.min(1, g)) * 255,
    Math.max(0, Math.min(1, b)) * 255]
}
.color {
  width: 200px;
  height: 200px;
  border: 1px solid #ccc;
}

#rgb {
  background: rgb(255, 242, 0)
}
<h3>rgba(255, 242, 0, 1)</h3>
<div class="color" id="rgb"></div>
<h3>LAB*a (95, -13, 103, 1) to RGB</h3>
<div class="color" id="labToRgb"></div>

理想情况下,你可以解析“输出意图”(目标)颜色配置文件

例如,一个 .icc 文件,然后将LAB颜色转换为满足所需目标颜色空间的颜色。

英文:

So apparently, the psd.js color output object confuses RGB with LAB values.

Unfortunately, you can only convert LAB to to a more generic RGB approximation.

You can't precisely convert LAB to RGB (without a target color space definition)

The whole idea behind the LAB color system is to provide a system that represents all colors distinguishable by the human eye as a reference color space for all kind of color conversions.

Workaround: generic RGB approximation:

Provided, your psd used a more generic RGB color profile e.g similar to sRGB, you can use antimatter15's rgb-lab library

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-js -->

let psdCols = {
&quot;red&quot;: 1.0343483686447144,
&quot;green&quot;: 0.9487225413322449,
&quot;blue&quot;: -0.12634865939617157,
&quot;alpha&quot;: 100,
}
let labRGBAVals =  [[psdCols.green,  psdCols.blue, psdCols.red].map(val=&gt;+(val*100).toFixed(0)) ,psdCols.alpha / 100].flat();
console.log(&#39;LAB values: &#39;, labRGBAVals.join(&#39; &#39;));
let rgba = lab2rgb(labRGBAVals).map(val=&gt;+(val).toFixed(0) );
labToRgb.style.backgroundColor = `rgba( ${rgba.join(&#39;, &#39;)} )`
console.log(&#39;RGB values: &#39;, rgba)
/**
* based on 
* https://github.com/antimatter15/rgb-lab/blob/master/color.js
*/
function lab2rgb(lab){
let y = (lab[0] + 16) / 116,
x = lab[1] / 500 + y,
z = y - lab[2] / 200,
r, g, b;
x = 0.95047 * ((x * x * x &gt; 0.008856) ? x * x * x : (x - 16/116) / 7.787);
y = 1.00000 * ((y * y * y &gt; 0.008856) ? y * y * y : (y - 16/116) / 7.787);
z = 1.08883 * ((z * z * z &gt; 0.008856) ? z * z * z : (z - 16/116) / 7.787);
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;
r = (r &gt; 0.0031308) ? (1.055 * Math.pow(r, 1/2.4) - 0.055) : 12.92 * r;
g = (g &gt; 0.0031308) ? (1.055 * Math.pow(g, 1/2.4) - 0.055) : 12.92 * g;
b = (b &gt; 0.0031308) ? (1.055 * Math.pow(b, 1/2.4) - 0.055) : 12.92 * b;
return [Math.max(0, Math.min(1, r)) * 255, 
Math.max(0, Math.min(1, g)) * 255, 
Math.max(0, Math.min(1, b)) * 255]
}

<!-- language: lang-css -->

.color {
width: 200px;
height: 200px;
border: 1px solid #ccc;
}
#rgb {
background: rgb(255, 242, 0)
}

<!-- language: lang-html -->

&lt;h3&gt;rgba(255, 242, 0, 1)&lt;/h3&gt;
&lt;div class=&quot;color&quot; id=&quot;rgb&quot;&gt;&lt;/div&gt;
&lt;h3&gt;LAB*a (95, -13, 103, 1) to RGB&lt;/h3&gt;
&lt;div class=&quot;color&quot; id=&quot;labToRgb&quot;&gt;&lt;/div&gt;

<!-- end snippet -->

Ideally, you could parse a "output-intent" (target) color profile

E.g an .icc file and then convert LAB colors to meet the desired target color space.

huangapple
  • 本文由 发表于 2023年3月31日 04:50:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75892884.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定