/** * @module color-space/hwb */ 'use strict' var rgb = require('./rgb'); var hsv = require('./hsv'); var hsl = require('./hsl'); var hwb = module.exports = { name: 'hwb', min: [0,0,0], max: [360,100,100], channel: ['hue', 'whiteness', 'blackness'], alias: ['HWB'], // http://dev.w3.org/csswg/css-color/#hwb-to-rgb rgb: function(hwb) { var h = hwb[0] / 360, wh = hwb[1] / 100, bl = hwb[2] / 100, ratio = wh + bl, i, v, f, n; var r, g, b; // wh + bl cant be > 1 if (ratio > 1) { wh /= ratio; bl /= ratio; } i = Math.floor(6 * h); v = 1 - bl; f = 6 * h - i; //if it is even if ((i & 0x01) !== 0) { f = 1 - f; } n = wh + f * (v - wh); // linear interpolation switch (i) { default: case 6: case 0: r = v; g = n; b = wh; break; case 1: r = n; g = v; b = wh; break; case 2: r = wh; g = v; b = n; break; case 3: r = wh; g = n; b = v; break; case 4: r = n; g = wh; b = v; break; case 5: r = v; g = wh; b = n; break; } return [r * 255, g * 255, b * 255]; }, // http://alvyray.com/Papers/CG/HWB_JGTv208.pdf hsv: function(arg){ var h = arg[0], w = arg[1], b = arg[2], s, v; //if w+b > 100% - take proportion (how many times ) if (w + b >= 100){ s = 0; v = 100 * w/(w+b); } //by default - take wiki formula else { s = 100-(w/(1-b/100)); v = 100-b; } return [h, s, v]; }, hsl: function(arg){ return hsv.hsl(hwb.hsv(arg)); } }; //extend rgb rgb.hwb = function(val) { var r = val[0], g = val[1], b = val[2], h = rgb.hsl(val)[0], w = 1/255 * Math.min(r, Math.min(g, b)); b = 1 - 1/255 * Math.max(r, Math.max(g, b)); return [h, w * 100, b * 100]; }; //keep proper hue on 0 values (conversion to rgb loses hue on zero-lightness) hsv.hwb = function(arg){ var h = arg[0], s = arg[1], v = arg[2]; return [h, v === 0 ? 0 : (v * (1-s/100)), 100 - v]; }; //extend hsl with proper conversions hsl.hwb = function(arg){ return hsv.hwb(hsl.hsv(arg)); };