tinycolor javascript converter rgb hsv hsb

javascript - tinycolor - hsl css



Javascript convierte el color HSB/HSV a RGB con precisiĆ³n (5)

Necesito convertir HSB a RGB con precisión, pero no estoy seguro de cómo evitar el problema de convertir decimales en números enteros sin redondear. Esta es la función actual que tengo de una biblioteca de 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) };

Como puede ver, la inexactitud en esta función proviene del Math.round


Aquí está el algoritmo en unityscript, tendrás que reescribir las funciones float, mathf.floor y la salida es un vector3 de 3 flotantes.

EDITAR Esta fue la primera respuesta en esta página y me pareció que valía la pena proporcionar esta ayuda cuando no había otras respuestas, con la pequeña reserva de que tienes que convertirla a una versión casi idéntica en 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); }


Dada la creciente popularidad de npm , creo que vale la pena mencionar un package contiene todas estas funciones a través de una API simple:

npm instala colorsys

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

Para el navegador: <script src="http://netbeast.github.io/colorsys/browser.js"></script>

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


Del enlace de Parthik Gosar en este comentario con una ligera modificación que le permite ingresar cada valor de manera independiente o todo a la vez como un objeto

/* 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 = h.s, v = h.v, h = h.h; } 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) }; }

Este código espera 0 <= h, s, v <= 1 , si está usando grados o radianes, recuerde dividirlos.

Los 0 <= r, g, b <= 255 devueltos se redondean al entero más cercano. Si no desea este comportamiento, elimine Math.round s del objeto devuelto.

Y el reverso (con menos división)

/* accepts parameters * r Object = {r:x, g:y, b:z} * OR * r, g, b */ function RGBtoHSV(r, g, b) { if (arguments.length === 1) { g = r.g, b = r.b, r = r.r; } 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 }; }

Este código generará 0 <= h, s, v <= 1 , pero esta vez toma cualquier 0 <= r, g, b <= 255 (no necesita ser un número entero)

Por completitud,

function HSVtoHSL(h, s, v) { if (arguments.length === 1) { s = h.s, v = h.v, h = h.h; } 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 = h.s, l = h.l, h = h.h; } 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 }; }

Todos estos valores deben estar en el rango de 0 a 1 . Para HSL<->RGB vaya a través de HSV .


Hay un error en la función HSVtoHSL Paul S: cuando la entrada v es 0 obtenemos un problema de división por cero y la salida s se convierte en NaN. Aquí hay una solución:

function HSVtoHSL(h, s, v) { if (arguments.length === 1) { s = h.s, v = h.v, h = h.h; } 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; }; }

PD: Hubiera agregado esto como un comentario en la publicación de Paul S., pero soy nuevo y el sistema me dijo que no tengo suficiente representante.


Una vez escribí esta función:

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

Espera 0 <= H <= 360, 0 <= S <= 1 y 0 <= V <= 1 y devuelve un objeto que contiene R, G y B (valores enteros entre 0 y 255). Usé esta imagen para crear el código.