JavaScript准确地将HSB / HSV颜色转换为RGB

我需要准确地将HSB转换为RGB,但我不知道如何解决小数转换为整数而不四舍五入的问题。 这是我从colorpicker库中获得的当前函数:

HSBToRGB = function (hsb) { var rgb = { }; var h = Math.round(hsb.h); var s = Math.round(hsb.s * 255 / 100); var v = Math.round(hsb.b * 255 / 100); if (s == 0) { rgb.r = rgb.g = rgb.b = v; } else { var t1 = v; var t2 = (255 - s) * v / 255; var t3 = (t1 - t2) * (h % 60) / 60; if (h == 360) h = 0; if (h < 60) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3 } else if (h < 120) { rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3 } else if (h < 180) { rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3 } else if (h < 240) { rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3 } else if (h < 300) { rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3 } else if (h < 360) { rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3 } else { rgb.r = 0; rgb.g = 0; rgb.b = 0 } } return { r: Math.round(rgb.r), g: Math.round(rgb.g), b: Math.round(rgb.b) }; 

正如你所看到的,这个函数的不准确性来自Math.round

从Parthik Gosar在这个评论中的链接稍作修改,让你单独或全部input每个值作为一个对象

 /* accepts parameters * h Object = {h:x, s:y, v:z} * OR * h, s, v */ function HSVtoRGB(h, s, v) { var r, g, b, i, f, p, q, t; if (arguments.length === 1) { s = hs, v = hv, h = hh; } i = Math.floor(h * 6); f = h * 6 - i; p = v * (1 - s); q = v * (1 - f * s); t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v, g = t, b = p; break; case 1: r = q, g = v, b = p; break; case 2: r = p, g = v, b = t; break; case 3: r = p, g = q, b = v; break; case 4: r = t, g = p, b = v; break; case 5: r = v, g = p, b = q; break; } return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) }; } 

这个代码期望0 <= h, s, v <= 1 ,如果你使用度或弧度,记得把它们分开。

返回的0 <= r, g, b <= 255被四舍五入到最接近的整数 。 如果您不想要这种行为,请从返回的对象中移除Math.round


而相反(用较less的分工)

 /* accepts parameters * r Object = {r:x, g:y, b:z} * OR * r, g, b */ function RGBtoHSV(r, g, b) { if (arguments.length === 1) { g = rg, b = rb, r = rr; } var max = Math.max(r, g, b), min = Math.min(r, g, b), d = max - min, h, s = (max === 0 ? 0 : d / max), v = max / 255; switch (max) { case min: h = 0; break; case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break; case g: h = (b - r) + d * 2; h /= 6 * d; break; case b: h = (r - g) + d * 4; h /= 6 * d; break; } return { h: h, s: s, v: v }; } 

这段代码将输出0 <= h, s, v <= 1 ,但这次取0 <= r, g, b <= 255 (不一定是整数)


为了完整性,

 function HSVtoHSL(h, s, v) { if (arguments.length === 1) { s = hs, v = hv, h = hh; } var _h = h, _s = s * v, _l = (2 - s) * v; _s /= (_l <= 1) ? _l : 2 - _l; _l /= 2; return { h: _h, s: _s, l: _l }; } function HSLtoHSV(h, s, l) { if (arguments.length === 1) { s = hs, l = hl, h = hh; } var _h = h, _s, _v; l *= 2; s *= (l <= 1) ? l : 2 - l; _v = (l + s) / 2; _s = (2 * s) / (l + s); return { h: _h, s: _s, v: _v }; } 

所有这些值应该在01的范围内。 HSL<->RGB通过HSV

考虑到npm的日益普及,我认为值得一提的是一个包含所有这些function的包通过一个简单的API:

npm安装colorsys

 var colorsys = require('colorsys') colorsys.rgb_to_hsv({ r: 255, g: 255, b: 255 }) // { h: 0 , s: 0 , v: 100 } 

对于浏览器: <script src="colorsys/browser.js"></script>

 colorsys.rgb_to_hex(h, s, v) // #hexcolor 

我曾经写过这个函数:

 function mix(a, b, v) { return (1-v)*a + v*b; } function HSVtoRGB(H, S, V) { var V2 = V * (1 - S); var r = ((H>=0 && H<=60) || (H>=300 && H<=360)) ? V : ((H>=120 && H<=240) ? V2 : ((H>=60 && H<=120) ? mix(V,V2,(H-60)/60) : ((H>=240 && H<=300) ? mix(V2,V,(H-240)/60) : 0))); var g = (H>=60 && H<=180) ? V : ((H>=240 && H<=360) ? V2 : ((H>=0 && H<=60) ? mix(V2,V,H/60) : ((H>=180 && H<=240) ? mix(V,V2,(H-180)/60) : 0))); var b = (H>=0 && H<=120) ? V2 : ((H>=180 && H<=300) ? V : ((H>=120 && H<=180) ? mix(V2,V,(H-120)/60) : ((H>=300 && H<=360) ? mix(V,V2,(H-300)/60) : 0))); return { r : Math.round(r * 255), g : Math.round(g * 255), b : Math.round(b * 255) }; } 

它期望0 <= H <= 360,0 <= S <= 1且0 <= V <= 1,并返回包含R,G和B(0到255之间的整数值)的对象。 我用这个图像来创build代码。

Paul S的HSVtoHSL函数存在一个错误:当vinput为0时,我们得到一个被零除的问题,并且s输出变成NaN。 这是一个修复:

 function HSVtoHSL(h, s, v) { if (arguments.length === 1) { s = hs, v = hv, h = hh; } var _h = h, _s = s * v, _l = (2 - s) * v; _s /= (_l <= 1) ? (_l === 0 ? 1 : _l) : 2 - _l; _l /= 2; return { h: _h, s: _s, l: _l; }; } 

PS我会添加这个评论保罗·S的职位,但我是新的,系统告诉我,我没有足够的代表。

这里是unityscript中的algorithm,你将不得不重写float,mathf.floor函数,输出是一个vector3的3个浮点数。

编辑这是这个页面上的第一个答案,当没有任何其他答案的时候,提供这么多的帮助似乎是值得的,你必须把它转换成JS中几乎相同的版本。

 function HSVToRGB(h : float, s : float, v : float) { h=h%1; s=s%1; v=v%1; var r : float; var g : float; var b : float; var i : float; var f : float; var p : float; var q : float; var t : float; i = Mathf.Floor(h * 6); f = h * 6 - i; p = v * (1 - s); q = v * (1 - f * s); t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; } return Color(r,g,b); }