conversions.js 16 KB

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