conversions.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. /* MIT license */
  2. var cssKeywords = require('color-name');
  3. // NOTE: conversions should only return primitive values (i.e. arrays, or
  4. // values that give correct `typeof` results).
  5. // do not use box values types (i.e. Number(), String(), etc.)
  6. var reverseKeywords = {};
  7. for (var key in cssKeywords) {
  8. if (cssKeywords.hasOwnProperty(key)) {
  9. reverseKeywords[cssKeywords[key]] = key;
  10. }
  11. }
  12. var convert = module.exports = {
  13. rgb: {channels: 3, labels: 'rgb'},
  14. hsl: {channels: 3, labels: 'hsl'},
  15. hsv: {channels: 3, labels: 'hsv'},
  16. hwb: {channels: 3, labels: 'hwb'},
  17. cmyk: {channels: 4, labels: 'cmyk'},
  18. xyz: {channels: 3, labels: 'xyz'},
  19. lab: {channels: 3, labels: 'lab'},
  20. lch: {channels: 3, labels: 'lch'},
  21. hex: {channels: 1, labels: ['hex']},
  22. keyword: {channels: 1, labels: ['keyword']},
  23. ansi16: {channels: 1, labels: ['ansi16']},
  24. ansi256: {channels: 1, labels: ['ansi256']},
  25. hcg: {channels: 3, labels: ['h', 'c', 'g']},
  26. apple: {channels: 3, labels: ['r16', 'g16', 'b16']},
  27. gray: {channels: 1, labels: ['gray']}
  28. };
  29. // hide .channels and .labels properties
  30. for (var model in convert) {
  31. if (convert.hasOwnProperty(model)) {
  32. if (!('channels' in convert[model])) {
  33. throw new Error('missing channels property: ' + model);
  34. }
  35. if (!('labels' in convert[model])) {
  36. throw new Error('missing channel labels property: ' + model);
  37. }
  38. if (convert[model].labels.length !== convert[model].channels) {
  39. throw new Error('channel and label counts mismatch: ' + model);
  40. }
  41. var channels = convert[model].channels;
  42. var labels = convert[model].labels;
  43. delete convert[model].channels;
  44. delete convert[model].labels;
  45. Object.defineProperty(convert[model], 'channels', {value: channels});
  46. Object.defineProperty(convert[model], 'labels', {value: labels});
  47. }
  48. }
  49. convert.rgb.hsl = function (rgb) {
  50. var r = rgb[0] / 255;
  51. var g = rgb[1] / 255;
  52. var b = rgb[2] / 255;
  53. var min = Math.min(r, g, b);
  54. var max = Math.max(r, g, b);
  55. var delta = max - min;
  56. var h;
  57. var s;
  58. var l;
  59. if (max === min) {
  60. h = 0;
  61. } else if (r === max) {
  62. h = (g - b) / delta;
  63. } else if (g === max) {
  64. h = 2 + (b - r) / delta;
  65. } else if (b === max) {
  66. h = 4 + (r - g) / delta;
  67. }
  68. h = Math.min(h * 60, 360);
  69. if (h < 0) {
  70. h += 360;
  71. }
  72. l = (min + max) / 2;
  73. if (max === min) {
  74. s = 0;
  75. } else if (l <= 0.5) {
  76. s = delta / (max + min);
  77. } else {
  78. s = delta / (2 - max - min);
  79. }
  80. return [h, s * 100, l * 100];
  81. };
  82. convert.rgb.hsv = function (rgb) {
  83. var rdif;
  84. var gdif;
  85. var bdif;
  86. var h;
  87. var s;
  88. var r = rgb[0] / 255;
  89. var g = rgb[1] / 255;
  90. var b = rgb[2] / 255;
  91. var v = Math.max(r, g, b);
  92. var diff = v - Math.min(r, g, b);
  93. var diffc = function (c) {
  94. return (v - c) / 6 / diff + 1 / 2;
  95. };
  96. if (diff === 0) {
  97. h = s = 0;
  98. } else {
  99. s = diff / v;
  100. rdif = diffc(r);
  101. gdif = diffc(g);
  102. bdif = diffc(b);
  103. if (r === v) {
  104. h = bdif - gdif;
  105. } else if (g === v) {
  106. h = (1 / 3) + rdif - bdif;
  107. } else if (b === v) {
  108. h = (2 / 3) + gdif - rdif;
  109. }
  110. if (h < 0) {
  111. h += 1;
  112. } else if (h > 1) {
  113. h -= 1;
  114. }
  115. }
  116. return [
  117. h * 360,
  118. s * 100,
  119. v * 100
  120. ];
  121. };
  122. convert.rgb.hwb = function (rgb) {
  123. var r = rgb[0];
  124. var g = rgb[1];
  125. var b = rgb[2];
  126. var h = convert.rgb.hsl(rgb)[0];
  127. var w = 1 / 255 * Math.min(r, Math.min(g, b));
  128. b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
  129. return [h, w * 100, b * 100];
  130. };
  131. convert.rgb.cmyk = function (rgb) {
  132. var r = rgb[0] / 255;
  133. var g = rgb[1] / 255;
  134. var b = rgb[2] / 255;
  135. var c;
  136. var m;
  137. var y;
  138. var k;
  139. k = Math.min(1 - r, 1 - g, 1 - b);
  140. c = (1 - r - k) / (1 - k) || 0;
  141. m = (1 - g - k) / (1 - k) || 0;
  142. y = (1 - b - k) / (1 - k) || 0;
  143. return [c * 100, m * 100, y * 100, k * 100];
  144. };
  145. /**
  146. * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
  147. * */
  148. function comparativeDistance(x, y) {
  149. return (
  150. Math.pow(x[0] - y[0], 2) +
  151. Math.pow(x[1] - y[1], 2) +
  152. Math.pow(x[2] - y[2], 2)
  153. );
  154. }
  155. convert.rgb.keyword = function (rgb) {
  156. var reversed = reverseKeywords[rgb];
  157. if (reversed) {
  158. return reversed;
  159. }
  160. var currentClosestDistance = Infinity;
  161. var currentClosestKeyword;
  162. for (var keyword in cssKeywords) {
  163. if (cssKeywords.hasOwnProperty(keyword)) {
  164. var value = cssKeywords[keyword];
  165. // Compute comparative distance
  166. var distance = comparativeDistance(rgb, value);
  167. // Check if its less, if so set as closest
  168. if (distance < currentClosestDistance) {
  169. currentClosestDistance = distance;
  170. currentClosestKeyword = keyword;
  171. }
  172. }
  173. }
  174. return currentClosestKeyword;
  175. };
  176. convert.keyword.rgb = function (keyword) {
  177. return cssKeywords[keyword];
  178. };
  179. convert.rgb.xyz = function (rgb) {
  180. var r = rgb[0] / 255;
  181. var g = rgb[1] / 255;
  182. var b = rgb[2] / 255;
  183. // assume sRGB
  184. r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92);
  185. g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92);
  186. b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92);
  187. var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
  188. var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
  189. var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
  190. return [x * 100, y * 100, z * 100];
  191. };
  192. convert.rgb.lab = function (rgb) {
  193. var xyz = convert.rgb.xyz(rgb);
  194. var x = xyz[0];
  195. var y = xyz[1];
  196. var z = xyz[2];
  197. var l;
  198. var a;
  199. var b;
  200. x /= 95.047;
  201. y /= 100;
  202. z /= 108.883;
  203. x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116);
  204. y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116);
  205. z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116);
  206. l = (116 * y) - 16;
  207. a = 500 * (x - y);
  208. b = 200 * (y - z);
  209. return [l, a, b];
  210. };
  211. convert.hsl.rgb = function (hsl) {
  212. var h = hsl[0] / 360;
  213. var s = hsl[1] / 100;
  214. var l = hsl[2] / 100;
  215. var t1;
  216. var t2;
  217. var t3;
  218. var rgb;
  219. var val;
  220. if (s === 0) {
  221. val = l * 255;
  222. return [val, val, val];
  223. }
  224. if (l < 0.5) {
  225. t2 = l * (1 + s);
  226. } else {
  227. t2 = l + s - l * s;
  228. }
  229. t1 = 2 * l - t2;
  230. rgb = [0, 0, 0];
  231. for (var i = 0; i < 3; i++) {
  232. t3 = h + 1 / 3 * -(i - 1);
  233. if (t3 < 0) {
  234. t3++;
  235. }
  236. if (t3 > 1) {
  237. t3--;
  238. }
  239. if (6 * t3 < 1) {
  240. val = t1 + (t2 - t1) * 6 * t3;
  241. } else if (2 * t3 < 1) {
  242. val = t2;
  243. } else if (3 * t3 < 2) {
  244. val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
  245. } else {
  246. val = t1;
  247. }
  248. rgb[i] = val * 255;
  249. }
  250. return rgb;
  251. };
  252. convert.hsl.hsv = function (hsl) {
  253. var h = hsl[0];
  254. var s = hsl[1] / 100;
  255. var l = hsl[2] / 100;
  256. var smin = s;
  257. var lmin = Math.max(l, 0.01);
  258. var sv;
  259. var v;
  260. l *= 2;
  261. s *= (l <= 1) ? l : 2 - l;
  262. smin *= lmin <= 1 ? lmin : 2 - lmin;
  263. v = (l + s) / 2;
  264. sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
  265. return [h, sv * 100, v * 100];
  266. };
  267. convert.hsv.rgb = function (hsv) {
  268. var h = hsv[0] / 60;
  269. var s = hsv[1] / 100;
  270. var v = hsv[2] / 100;
  271. var hi = Math.floor(h) % 6;
  272. var f = h - Math.floor(h);
  273. var p = 255 * v * (1 - s);
  274. var q = 255 * v * (1 - (s * f));
  275. var t = 255 * v * (1 - (s * (1 - f)));
  276. v *= 255;
  277. switch (hi) {
  278. case 0:
  279. return [v, t, p];
  280. case 1:
  281. return [q, v, p];
  282. case 2:
  283. return [p, v, t];
  284. case 3:
  285. return [p, q, v];
  286. case 4:
  287. return [t, p, v];
  288. case 5:
  289. return [v, p, q];
  290. }
  291. };
  292. convert.hsv.hsl = function (hsv) {
  293. var h = hsv[0];
  294. var s = hsv[1] / 100;
  295. var v = hsv[2] / 100;
  296. var vmin = Math.max(v, 0.01);
  297. var lmin;
  298. var sl;
  299. var l;
  300. l = (2 - s) * v;
  301. lmin = (2 - s) * vmin;
  302. sl = s * vmin;
  303. sl /= (lmin <= 1) ? lmin : 2 - lmin;
  304. sl = sl || 0;
  305. l /= 2;
  306. return [h, sl * 100, l * 100];
  307. };
  308. // http://dev.w3.org/csswg/css-color/#hwb-to-rgb
  309. convert.hwb.rgb = function (hwb) {
  310. var h = hwb[0] / 360;
  311. var wh = hwb[1] / 100;
  312. var bl = hwb[2] / 100;
  313. var ratio = wh + bl;
  314. var i;
  315. var v;
  316. var f;
  317. var n;
  318. // wh + bl cant be > 1
  319. if (ratio > 1) {
  320. wh /= ratio;
  321. bl /= ratio;
  322. }
  323. i = Math.floor(6 * h);
  324. v = 1 - bl;
  325. f = 6 * h - i;
  326. if ((i & 0x01) !== 0) {
  327. f = 1 - f;
  328. }
  329. n = wh + f * (v - wh); // linear interpolation
  330. var r;
  331. var g;
  332. var b;
  333. switch (i) {
  334. default:
  335. case 6:
  336. case 0: r = v; g = n; b = wh; break;
  337. case 1: r = n; g = v; b = wh; break;
  338. case 2: r = wh; g = v; b = n; break;
  339. case 3: r = wh; g = n; b = v; break;
  340. case 4: r = n; g = wh; b = v; break;
  341. case 5: r = v; g = wh; b = n; break;
  342. }
  343. return [r * 255, g * 255, b * 255];
  344. };
  345. convert.cmyk.rgb = function (cmyk) {
  346. var c = cmyk[0] / 100;
  347. var m = cmyk[1] / 100;
  348. var y = cmyk[2] / 100;
  349. var k = cmyk[3] / 100;
  350. var r;
  351. var g;
  352. var b;
  353. r = 1 - Math.min(1, c * (1 - k) + k);
  354. g = 1 - Math.min(1, m * (1 - k) + k);
  355. b = 1 - Math.min(1, y * (1 - k) + k);
  356. return [r * 255, g * 255, b * 255];
  357. };
  358. convert.xyz.rgb = function (xyz) {
  359. var x = xyz[0] / 100;
  360. var y = xyz[1] / 100;
  361. var z = xyz[2] / 100;
  362. var r;
  363. var g;
  364. var b;
  365. r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
  366. g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
  367. b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
  368. // assume sRGB
  369. r = r > 0.0031308
  370. ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055)
  371. : r * 12.92;
  372. g = g > 0.0031308
  373. ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055)
  374. : g * 12.92;
  375. b = b > 0.0031308
  376. ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055)
  377. : b * 12.92;
  378. r = Math.min(Math.max(0, r), 1);
  379. g = Math.min(Math.max(0, g), 1);
  380. b = Math.min(Math.max(0, b), 1);
  381. return [r * 255, g * 255, b * 255];
  382. };
  383. convert.xyz.lab = function (xyz) {
  384. var x = xyz[0];
  385. var y = xyz[1];
  386. var z = xyz[2];
  387. var l;
  388. var a;
  389. var b;
  390. x /= 95.047;
  391. y /= 100;
  392. z /= 108.883;
  393. x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116);
  394. y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116);
  395. z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116);
  396. l = (116 * y) - 16;
  397. a = 500 * (x - y);
  398. b = 200 * (y - z);
  399. return [l, a, b];
  400. };
  401. convert.lab.xyz = function (lab) {
  402. var l = lab[0];
  403. var a = lab[1];
  404. var b = lab[2];
  405. var x;
  406. var y;
  407. var z;
  408. y = (l + 16) / 116;
  409. x = a / 500 + y;
  410. z = y - b / 200;
  411. var y2 = Math.pow(y, 3);
  412. var x2 = Math.pow(x, 3);
  413. var z2 = Math.pow(z, 3);
  414. y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787;
  415. x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787;
  416. z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787;
  417. x *= 95.047;
  418. y *= 100;
  419. z *= 108.883;
  420. return [x, y, z];
  421. };
  422. convert.lab.lch = function (lab) {
  423. var l = lab[0];
  424. var a = lab[1];
  425. var b = lab[2];
  426. var hr;
  427. var h;
  428. var c;
  429. hr = Math.atan2(b, a);
  430. h = hr * 360 / 2 / Math.PI;
  431. if (h < 0) {
  432. h += 360;
  433. }
  434. c = Math.sqrt(a * a + b * b);
  435. return [l, c, h];
  436. };
  437. convert.lch.lab = function (lch) {
  438. var l = lch[0];
  439. var c = lch[1];
  440. var h = lch[2];
  441. var a;
  442. var b;
  443. var hr;
  444. hr = h / 360 * 2 * Math.PI;
  445. a = c * Math.cos(hr);
  446. b = c * Math.sin(hr);
  447. return [l, a, b];
  448. };
  449. convert.rgb.ansi16 = function (args) {
  450. var r = args[0];
  451. var g = args[1];
  452. var b = args[2];
  453. var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization
  454. value = Math.round(value / 50);
  455. if (value === 0) {
  456. return 30;
  457. }
  458. var ansi = 30
  459. + ((Math.round(b / 255) << 2)
  460. | (Math.round(g / 255) << 1)
  461. | Math.round(r / 255));
  462. if (value === 2) {
  463. ansi += 60;
  464. }
  465. return ansi;
  466. };
  467. convert.hsv.ansi16 = function (args) {
  468. // optimization here; we already know the value and don't need to get
  469. // it converted for us.
  470. return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
  471. };
  472. convert.rgb.ansi256 = function (args) {
  473. var r = args[0];
  474. var g = args[1];
  475. var b = args[2];
  476. // we use the extended greyscale palette here, with the exception of
  477. // black and white. normal palette only has 4 greyscale shades.
  478. if (r === g && g === b) {
  479. if (r < 8) {
  480. return 16;
  481. }
  482. if (r > 248) {
  483. return 231;
  484. }
  485. return Math.round(((r - 8) / 247) * 24) + 232;
  486. }
  487. var ansi = 16
  488. + (36 * Math.round(r / 255 * 5))
  489. + (6 * Math.round(g / 255 * 5))
  490. + Math.round(b / 255 * 5);
  491. return ansi;
  492. };
  493. convert.ansi16.rgb = function (args) {
  494. var color = args % 10;
  495. // handle greyscale
  496. if (color === 0 || color === 7) {
  497. if (args > 50) {
  498. color += 3.5;
  499. }
  500. color = color / 10.5 * 255;
  501. return [color, color, color];
  502. }
  503. var mult = (~~(args > 50) + 1) * 0.5;
  504. var r = ((color & 1) * mult) * 255;
  505. var g = (((color >> 1) & 1) * mult) * 255;
  506. var b = (((color >> 2) & 1) * mult) * 255;
  507. return [r, g, b];
  508. };
  509. convert.ansi256.rgb = function (args) {
  510. // handle greyscale
  511. if (args >= 232) {
  512. var c = (args - 232) * 10 + 8;
  513. return [c, c, c];
  514. }
  515. args -= 16;
  516. var rem;
  517. var r = Math.floor(args / 36) / 5 * 255;
  518. var g = Math.floor((rem = args % 36) / 6) / 5 * 255;
  519. var b = (rem % 6) / 5 * 255;
  520. return [r, g, b];
  521. };
  522. convert.rgb.hex = function (args) {
  523. var integer = ((Math.round(args[0]) & 0xFF) << 16)
  524. + ((Math.round(args[1]) & 0xFF) << 8)
  525. + (Math.round(args[2]) & 0xFF);
  526. var string = integer.toString(16).toUpperCase();
  527. return '000000'.substring(string.length) + string;
  528. };
  529. convert.hex.rgb = function (args) {
  530. var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
  531. if (!match) {
  532. return [0, 0, 0];
  533. }
  534. var colorString = match[0];
  535. if (match[0].length === 3) {
  536. colorString = colorString.split('').map(function (char) {
  537. return char + char;
  538. }).join('');
  539. }
  540. var integer = parseInt(colorString, 16);
  541. var r = (integer >> 16) & 0xFF;
  542. var g = (integer >> 8) & 0xFF;
  543. var b = integer & 0xFF;
  544. return [r, g, b];
  545. };
  546. convert.rgb.hcg = function (rgb) {
  547. var r = rgb[0] / 255;
  548. var g = rgb[1] / 255;
  549. var b = rgb[2] / 255;
  550. var max = Math.max(Math.max(r, g), b);
  551. var min = Math.min(Math.min(r, g), b);
  552. var chroma = (max - min);
  553. var grayscale;
  554. var hue;
  555. if (chroma < 1) {
  556. grayscale = min / (1 - chroma);
  557. } else {
  558. grayscale = 0;
  559. }
  560. if (chroma <= 0) {
  561. hue = 0;
  562. } else
  563. if (max === r) {
  564. hue = ((g - b) / chroma) % 6;
  565. } else
  566. if (max === g) {
  567. hue = 2 + (b - r) / chroma;
  568. } else {
  569. hue = 4 + (r - g) / chroma + 4;
  570. }
  571. hue /= 6;
  572. hue %= 1;
  573. return [hue * 360, chroma * 100, grayscale * 100];
  574. };
  575. convert.hsl.hcg = function (hsl) {
  576. var s = hsl[1] / 100;
  577. var l = hsl[2] / 100;
  578. var c = 1;
  579. var f = 0;
  580. if (l < 0.5) {
  581. c = 2.0 * s * l;
  582. } else {
  583. c = 2.0 * s * (1.0 - l);
  584. }
  585. if (c < 1.0) {
  586. f = (l - 0.5 * c) / (1.0 - c);
  587. }
  588. return [hsl[0], c * 100, f * 100];
  589. };
  590. convert.hsv.hcg = function (hsv) {
  591. var s = hsv[1] / 100;
  592. var v = hsv[2] / 100;
  593. var c = s * v;
  594. var f = 0;
  595. if (c < 1.0) {
  596. f = (v - c) / (1 - c);
  597. }
  598. return [hsv[0], c * 100, f * 100];
  599. };
  600. convert.hcg.rgb = function (hcg) {
  601. var h = hcg[0] / 360;
  602. var c = hcg[1] / 100;
  603. var g = hcg[2] / 100;
  604. if (c === 0.0) {
  605. return [g * 255, g * 255, g * 255];
  606. }
  607. var pure = [0, 0, 0];
  608. var hi = (h % 1) * 6;
  609. var v = hi % 1;
  610. var w = 1 - v;
  611. var mg = 0;
  612. switch (Math.floor(hi)) {
  613. case 0:
  614. pure[0] = 1; pure[1] = v; pure[2] = 0; break;
  615. case 1:
  616. pure[0] = w; pure[1] = 1; pure[2] = 0; break;
  617. case 2:
  618. pure[0] = 0; pure[1] = 1; pure[2] = v; break;
  619. case 3:
  620. pure[0] = 0; pure[1] = w; pure[2] = 1; break;
  621. case 4:
  622. pure[0] = v; pure[1] = 0; pure[2] = 1; break;
  623. default:
  624. pure[0] = 1; pure[1] = 0; pure[2] = w;
  625. }
  626. mg = (1.0 - c) * g;
  627. return [
  628. (c * pure[0] + mg) * 255,
  629. (c * pure[1] + mg) * 255,
  630. (c * pure[2] + mg) * 255
  631. ];
  632. };
  633. convert.hcg.hsv = function (hcg) {
  634. var c = hcg[1] / 100;
  635. var g = hcg[2] / 100;
  636. var v = c + g * (1.0 - c);
  637. var f = 0;
  638. if (v > 0.0) {
  639. f = c / v;
  640. }
  641. return [hcg[0], f * 100, v * 100];
  642. };
  643. convert.hcg.hsl = function (hcg) {
  644. var c = hcg[1] / 100;
  645. var g = hcg[2] / 100;
  646. var l = g * (1.0 - c) + 0.5 * c;
  647. var s = 0;
  648. if (l > 0.0 && l < 0.5) {
  649. s = c / (2 * l);
  650. } else
  651. if (l >= 0.5 && l < 1.0) {
  652. s = c / (2 * (1 - l));
  653. }
  654. return [hcg[0], s * 100, l * 100];
  655. };
  656. convert.hcg.hwb = function (hcg) {
  657. var c = hcg[1] / 100;
  658. var g = hcg[2] / 100;
  659. var v = c + g * (1.0 - c);
  660. return [hcg[0], (v - c) * 100, (1 - v) * 100];
  661. };
  662. convert.hwb.hcg = function (hwb) {
  663. var w = hwb[1] / 100;
  664. var b = hwb[2] / 100;
  665. var v = 1 - b;
  666. var c = v - w;
  667. var g = 0;
  668. if (c < 1) {
  669. g = (v - c) / (1 - c);
  670. }
  671. return [hwb[0], c * 100, g * 100];
  672. };
  673. convert.apple.rgb = function (apple) {
  674. return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255];
  675. };
  676. convert.rgb.apple = function (rgb) {
  677. return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535];
  678. };
  679. convert.gray.rgb = function (args) {
  680. return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
  681. };
  682. convert.gray.hsl = convert.gray.hsv = function (args) {
  683. return [0, 0, args[0]];
  684. };
  685. convert.gray.hwb = function (gray) {
  686. return [0, 100, gray[0]];
  687. };
  688. convert.gray.cmyk = function (gray) {
  689. return [0, 0, 0, gray[0]];
  690. };
  691. convert.gray.lab = function (gray) {
  692. return [gray[0], 0, 0];
  693. };
  694. convert.gray.hex = function (gray) {
  695. var val = Math.round(gray[0] / 100 * 255) & 0xFF;
  696. var integer = (val << 16) + (val << 8) + val;
  697. var string = integer.toString(16).toUpperCase();
  698. return '000000'.substring(string.length) + string;
  699. };
  700. convert.rgb.gray = function (rgb) {
  701. var val = (rgb[0] + rgb[1] + rgb[2]) / 3;
  702. return [val / 255 * 100];
  703. };