_depth;){var _deplicate=[];for(var key in _tokens)if(_tokens.hasOwnProperty(key)){var _on=_tokens[key],_nowkey=_on._path.getLast();if(spaces.hasOwnProperty(_nowkey)){var _obj=eval("(spaces."+_nowkey+")");for(var key in _obj)if(_obj.hasOwnProperty(key)){var _temp=cloneObject(_on);_on._path.search(key)||_on._path.getLast()==_target?_temp._terminal=!0:(_temp._path.push(key),_temp._cost+=eval("(spaces."+_nowkey+"."+key+".cost)")),_deplicate.push(_temp)}_obj=null}}_tokens=_deplicate,_deplicate=null,_depth++}if(!_tokens.length)throw Error("No path to target");var _sort=[];for(var key in _tokens)_tokens.hasOwnProperty(key)&&_tokens[key]&&_tokens[key]._path.getLast()==_target&&_sort.push(_tokens[key]);if(_sort.sort(function(a,b){return a.cost>b.cost?-1:1}),_sort.length){for(var _rp=_sort[0]._path,_temp=eval("(_code."+_rp[0]+")"),i=1;i<_rp.length;i++)_temp=eval("(spaces."+_rp[i-1]+"."+_rp[i]+".convert("+JSON.stringify(_temp)+"))");output.push(_temp)}}),output},reset:function(){var a=this;return a.colors=[],!0}},window.ColorConverter=ColorConverter}(window,document);
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | ColorConverter.js - pixelnfinite
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
213 |
214 |
215 |
216 |
217 |
218 |
221 | A JavaScript library that makes converting between color spaces.
222 |
223 |
224 |
227 |
228 |
229 |
230 |
{{space.name}} {{space.remark||""}}
231 |
243 |
244 |
245 |
246 |
247 |
248 |
251 |
Include ColorConverter.js to your page.
252 |
<script src="ColorConverter.min.js"></script>
253 |
254 |
255 |
256 |
259 |
Initialization
260 |
var CC = new ColorConverter();
261 |
262 |
Import colors
263 |
You can push colors through import method.
264 |
/* import a array of colors */
265 | cc.import([
266 | ["HSL", 180, 0.5, 0.1],
267 | ["RGB", 180, 50, 50],
268 | ["RGB", "ffffff"],
269 | ["CMYK", 0, 0, 0],
270 | ...
271 | ]);
272 |
CC will return a array of import result like
273 |
[true, true, true, false, ...]
274 |
275 |
Export colors
276 |
Export colors with a converted data.
277 |
CC.export("Lab"); // {L:0,a:0,b:0}
278 | CC.export("RGB",[0,1]); // {R:180,G:50,B:50},{R:180,G:50,B:50}
279 | CC.export("RGB",1,2); // {R:0,G:0,B:0},{R:0,G:0,B:0}
280 |
281 |
Reset colors
282 |
delete the colors.
283 |
CC.reset(); // true
284 |
285 |
286 |
287 |
288 |
291 |
292 |
negate
293 |
function negate(_space, _color) {
294 | var cc = new ColorConverter();
295 | cc.import([
296 | [_space, _color],
297 | ]);
298 | var _rgb = cc.export("RGB")[0];
299 | for (var i in _rgb) {
300 | if (_rgb.hasOwnProperty(i)) {
301 | _rgb[i] = 255 - _rgb[i];
302 | }
303 | }
304 | cc.reset();
305 | cc.import([
306 | ["RGB", _rgb],
307 | ]);
308 | return cc.export(_space);
309 | };
310 |
311 | console.log(
312 | negate("CMYK", {
313 | C: 0,
314 | M: 0.1,
315 | Y: 0.2,
316 | K: 0.3
317 | })[0]
318 | );
319 |
320 |
lighten / darken
321 |
function lighten(_space, _color, _ratio) {
322 | var cc = new ColorConverter();
323 | cc.import([
324 | [_space, _color],
325 | ]);
326 | var _hsl = cc.export("HSL")[0];
327 | _hsl.L += _hsl.L * _ratio;
328 | cc.reset();
329 | cc.import([
330 | ["HSL", _hsl],
331 | ]);
332 | return cc.export("RGB");
333 | };
334 |
335 | console.log(
336 | lighten("RGB",
337 | {
338 | R: 12,
339 | G: 34,
340 | B: 56,
341 | },
342 | -0.5 /* if ratio < 0 it will be darken function */
343 | )[0]
344 | );
345 |
346 |
saturate / desaturate
347 |
function saturate(_space, _color, _ratio) {
348 | var cc = new ColorConverter();
349 | cc.import([
350 | [_space, _color],
351 | ]);
352 | var _hsl = cc.export("HSL")[0];
353 | _hsl.S += _hsl.S * _ratio;
354 | cc.reset();
355 | cc.import([
356 | ["HSL", _hsl],
357 | ]);
358 | return cc.export("RGB");
359 | };
360 |
361 | console.log(
362 | saturate("RGB",
363 | {
364 | R: 12,
365 | G: 34,
366 | B: 56,
367 | },
368 | -0.5 /* if ratio < 0 it will be desaturate function */
369 | )[0]
370 | );
371 |
372 |
rotate
373 |
function rotate(_space, _color, _degrees) {
374 | var cc = new ColorConverter();
375 | cc.import([
376 | [_space, _color],
377 | ]);
378 | var _hsl = cc.export("HSL")[0];
379 | _hsl.H = (_hsl.H + _degrees) % 360;
380 | _hsl.H = _hsl.H < 0 ? 360 + _hsl.H : _hsl.H;
381 | cc.reset();
382 | cc.import([
383 | ["HSL", _hsl],
384 | ]);
385 | return cc.export(_space);
386 | };
387 |
388 | console.log(
389 | rotate("CMYK", {
390 | C: 0,
391 | M: 0.1,
392 | Y: 0.2,
393 | K: 0.3
394 | }, 15)[0]
395 | );
396 |
397 |
398 |
399 |
402 |
* RGB
403 | * RGBA => RGB
404 | * CMY
405 | * CMYK
406 | * HSV (HSB)
407 | * HSL
408 | * XYZ
409 | * Lab (CIELab)
410 | * LCH
411 | * LUV
412 |
413 |
414 |
415 |
416 |
417 |
420 |
Code and documentation copyright 2015 Rijn, pixelnfinite.com.
421 |
Code released under the MIT license.
422 |
423 |
424 |
427 |
428 |
429 |
430 |
431 |
--------------------------------------------------------------------------------
/ColorConverter.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Color Converter
3 | * @author Rijn
4 | */
5 |
6 | ;
7 | (function(window, document, undefined) {
8 | "use strict";
9 |
10 | /* Rewrite foreach method to support ie */
11 | Array.prototype.forEach = function(fun, context) {
12 | var len = this.length,
13 | context = arguments[1];
14 | if (typeof fun !== "function") {
15 | throw Error("unknown function");
16 | }
17 | for (var i = 0; i < len; i++) {
18 | fun.call(context, this[i], i, this);
19 | }
20 | };
21 | /* Get the last element from Array */
22 | Array.prototype.getLast = function() {
23 | return this instanceof Array ? this[this.length - 1] : false;
24 | };
25 | /* Serach object form Array */
26 | Array.prototype.search = function(str) {
27 | if (this instanceof Array) {
28 | var found = [];
29 | for (var i in this) {
30 | if (this[i] == str) {
31 | found.push(i);
32 | }
33 | }
34 | var num = found.length;
35 | if (num == 0) return false;
36 | if (num == 1) return found[0];
37 | return found;
38 | } else {
39 | return false;
40 | }
41 | };
42 | /* Deep copy Object */
43 | var cloneObject = function(oldObj) {
44 | if (typeof(oldObj) != 'object') return oldObj;
45 | if (oldObj == null) return oldObj;
46 | var newObj = oldObj instanceof Array ? new Array() : new Object();
47 | for (var i in oldObj)
48 | newObj[i] = cloneObject(oldObj[i]);
49 | return newObj;
50 | };
51 | /* Check property */
52 | Object.prototype.check = function() {
53 | if (typeof this !== 'object') return false;
54 | var argu = flatten(arguments);
55 | for (var i = 0; i < argu.length; i++) {
56 | if (!this.hasOwnProperty(argu[i])) {
57 | return false;
58 | }
59 | };
60 | return true;
61 | };
62 |
63 | /* Flatten function */
64 | var flatten = function(input) {
65 | var has = function(obj, key) {
66 | return obj != null && hasOwnProperty.call(obj, key);
67 | },
68 | isArrayLike = function(collection) {
69 | var length = collection && collection.length;
70 | return typeof length == 'number' && length >= 0;
71 | },
72 | /* if obj is array */
73 | isArray = function(obj) {
74 | return toString.call(obj) === '[object Array]';
75 | },
76 | /* if obj is arguments*/
77 | isArguments = function(obj) {
78 | return has(obj, 'callee');
79 | },
80 | output = [],
81 | idx = 0;
82 | /* flatten function from underscore */
83 | for (var i = 0, length = input && input.length; i < length; i++) {
84 | var value = input[i];
85 | if (isArrayLike(value) && (isArray(value) || isArguments(value))) {
86 | value = flatten(value);
87 | var j = 0,
88 | len = value.length;
89 | output.length += len;
90 | while (j < len) {
91 | output[idx++] = value[j++];
92 | }
93 | } else {
94 | output[idx++] = value;
95 | }
96 | }
97 | return output;
98 | },
99 | /* find the minimum or maximum element */
100 | min = function() {
101 | var _input = flatten([arguments]),
102 | tempVal = _input[0];
103 | for (var i = 0; i < _input.length; i++) {
104 | if (tempVal > _input[i]) {
105 | tempVal = _input[i];
106 | }
107 | }
108 | return tempVal;
109 | },
110 | max = function() {
111 | var _input = flatten([arguments]),
112 | tempVal = _input[0];
113 | for (var i = 0; i < _input.length; i++) {
114 | if (tempVal < _input[i]) {
115 | tempVal = _input[i];
116 | }
117 | }
118 | return tempVal;
119 | },
120 | /* AccOperation for Float */
121 | acc = {
122 | div: function(arg1, arg2) {
123 | var t1 = 0,
124 | t2 = 0,
125 | r1, r2;
126 | try {
127 | t1 = arg1.toString().split(".")[1].length
128 | } catch (e) {}
129 | try {
130 | t2 = arg2.toString().split(".")[1].length
131 | } catch (e) {}
132 |
133 | r1 = Number(arg1.toString().replace(".", ""))
134 | r2 = Number(arg2.toString().replace(".", ""))
135 | return acc.mul((r1 / r2), Math.pow(10, t2 - t1));
136 |
137 | },
138 | mul: function(arg1, arg2) {
139 | var m = 0,
140 | s1 = arg1.toString(),
141 | s2 = arg2.toString();
142 | try {
143 | m += s1.split(".")[1].length
144 | } catch (e) {}
145 | try {
146 | m += s2.split(".")[1].length
147 | } catch (e) {}
148 | return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
149 | },
150 | add: function(arg1, arg2) {
151 | var r1, r2, m;
152 | try {
153 | r1 = arg1.toString().split(".")[1].length
154 | } catch (e) {
155 | r1 = 0
156 | }
157 | try {
158 | r2 = arg2.toString().split(".")[1].length
159 | } catch (e) {
160 | r2 = 0
161 | }
162 | m = Math.pow(10, Math.max(r1, r2))
163 | return Number((arg1 * m + arg2 * m) / m);
164 | },
165 | sub: function(arg1, arg2) {
166 | var r1, r2, m, n;
167 | try {
168 | r1 = arg1.toString().split(".")[1].length
169 | } catch (e) {
170 | r1 = 0
171 | }
172 | try {
173 | r2 = arg2.toString().split(".")[1].length
174 | } catch (e) {
175 | r2 = 0
176 | }
177 | m = Math.pow(10, Math.max(r1, r2));
178 | n = (r1 >= r2) ? r1 : r2;
179 | return Number(((arg1 * m - arg2 * m) / m).toFixed(n));
180 | }
181 | },
182 | /* Color spaces defination */
183 | spaces = {
184 | constant: {
185 | Epsilon: 216 / 24389,
186 | Kappa: 24389 / 27,
187 | XYZ_WhiteRefrence: {
188 | X: 95.047,
189 | Y: 100.000,
190 | Z: 108.883,
191 | },
192 | CubicRoot: function(n) {
193 | return Math.pow(n, 1.0 / 3.0);
194 | },
195 | },
196 | RGB: {
197 | import: function() {
198 | var input = flatten(arguments),
199 | rgbColor = [];
200 |
201 | console.log(input);
202 |
203 | if (input[0].check("R", "G", "B")) {
204 | return {
205 | RGB: input[0],
206 | };
207 | };
208 |
209 | if (input.length < 3) {
210 | var reg = /([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/;
211 | var sColor = input[0].toLowerCase();
212 | if (sColor && reg.test(sColor)) {
213 | sColor = reg.exec(sColor)[0];
214 | if (sColor.length === 3) {
215 | var sColorNew = "";
216 | for (var i = 0; i < 3; i += 1) {
217 | sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
218 | }
219 | sColor = sColorNew;
220 | }
221 | var rgbColor = [];
222 | for (var i = 0; i < 6; i += 2) {
223 | rgbColor.push(parseInt("0x" + sColor.slice(i, i + 2)));
224 | }
225 | } else {
226 | return false;
227 | }
228 | } else {
229 | for (var i = 0; i < 3; i++) {
230 | rgbColor[i] = Number(input[i]);
231 | }
232 | }
233 |
234 | for (var i in rgbColor) {
235 | if (rgbColor[i] < 0) return false;
236 | if (rgbColor[i] > 255) return false;
237 | };
238 |
239 | return {
240 | RGB: {
241 | R: rgbColor[0],
242 | G: rgbColor[1],
243 | B: rgbColor[2],
244 | },
245 | };
246 | },
247 | XYZ: {
248 | convert: function(_rgb) {
249 | function PivotRgb(n) {
250 | return (n > 0.04045 ? Math.pow((n + 0.055) / 1.055, 2.4) : n / 12.92) * 100.0;
251 | }
252 | _rgb.R = PivotRgb(_rgb.R / 255);
253 | _rgb.G = PivotRgb(_rgb.G / 255);
254 | _rgb.B = PivotRgb(_rgb.B / 255);
255 |
256 | return {
257 | X: _rgb.R * 0.412453 + _rgb.G * 0.357580 + _rgb.B * 0.180423,
258 | Y: _rgb.R * 0.212671 + _rgb.G * 0.715160 + _rgb.B * 0.072169,
259 | Z: _rgb.R * 0.019334 + _rgb.G * 0.119193 + _rgb.B * 0.950227,
260 | };
261 | },
262 | cost: 1,
263 | },
264 | CMY: {
265 | convert: function(_rgb) {
266 | var c, m, y;
267 |
268 | c = (255 - _rgb.R) / 255;
269 | m = (255 - _rgb.G) / 255;
270 | y = (255 - _rgb.B) / 255;
271 |
272 | return {
273 | C: c,
274 | M: m,
275 | Y: y,
276 | };
277 | },
278 | cost: 0,
279 | },
280 | CMYK: {
281 | convert: function(_rgb) {
282 | var cmyMin = 0,
283 | c, m, y, k;
284 |
285 | k = 0;
286 |
287 | c = (255 - _rgb.R) / 255;
288 | m = (255 - _rgb.G) / 255;
289 | y = (255 - _rgb.B) / 255;
290 |
291 | k = min([c, m, y]);
292 |
293 | if (k == 1.0) {
294 | c = m = y = 0;
295 | } else {
296 | c = (c - k) / (1 - k);
297 | m = (m - k) / (1 - k);
298 | y = (y - k) / (1 - k);
299 | }
300 |
301 | return {
302 | C: c,
303 | M: m,
304 | Y: y,
305 | K: k,
306 | };
307 | },
308 | cost: 0,
309 | },
310 | HSL: {
311 | convert: function(_rgb) {
312 | var R = _rgb.R / 255,
313 | G = _rgb.G / 255,
314 | B = _rgb.B / 255,
315 | Min = min(R, G, B),
316 | Max = max(R, G, B),
317 | del_Max = Max - Min,
318 | L = (Max + Min) / 2.0,
319 | del_R, del_G, del_B,
320 | H, S;
321 |
322 | if (del_Max == 0) {
323 | H = 0;
324 | S = 0;
325 | } else {
326 | if (L < 0.5)
327 | S = del_Max / (Max + Min);
328 | else
329 | S = del_Max / (2 - Max - Min);
330 |
331 | del_R = (((Max - R) / 6.0) + (del_Max / 2.0)) / del_Max;
332 | del_G = (((Max - G) / 6.0) + (del_Max / 2.0)) / del_Max;
333 | del_B = (((Max - B) / 6.0) + (del_Max / 2.0)) / del_Max;
334 |
335 | if (R == Max) H = del_B - del_G;
336 | else if (G == Max) H = (1.0 / 3.0) + del_R - del_B;
337 | else if (B == Max) H = (2.0 / 3.0) + del_G - del_R;
338 |
339 | if (H < 0) H += 1;
340 | if (H > 1) H -= 1;
341 | };
342 |
343 | return {
344 | H: H * 360,
345 | S: S,
346 | L: L,
347 | };
348 | },
349 | cost: 0,
350 | },
351 | HSV: {
352 | convert: function(_rgb) {
353 | var r = _rgb.R / 255,
354 | g = _rgb.G / 255,
355 | b = _rgb.B / 255,
356 | minRGB = min(r, g, b),
357 | maxRGB = max(r, g, b),
358 | H, S, V;
359 |
360 | if (minRGB == maxRGB) {
361 | V = minRGB;
362 | return {
363 | H: 0,
364 | S: 0,
365 | V: V,
366 | }
367 | } else {
368 | var d = (r == minRGB) ? g - b : ((b == minRGB) ? r - g : b - r),
369 | h = (r == minRGB) ? 3 : ((b == minRGB) ? 1 : 5);
370 | H = 60 * (h - d / (maxRGB - minRGB));
371 | S = (maxRGB - minRGB) / maxRGB;
372 | V = maxRGB;
373 | return {
374 | H: H,
375 | S: S,
376 | V: V,
377 | }
378 | }
379 | },
380 | cost: 0,
381 | },
382 | },
383 | CMY: {
384 | import: function() {
385 | var input = flatten(arguments);
386 |
387 | if (input[0].check("C", "M", "Y")) {
388 | return {
389 | CMY: input[0],
390 | };
391 | };
392 |
393 | if (input.length < 3) {
394 | return false;
395 | }
396 | for (var i = 0; i < 3; i++) {
397 | if (input[i] < 0 || input[i] > 1) return false;
398 | }
399 | return {
400 | CMY: {
401 | C: input[0],
402 | M: input[1],
403 | Y: input[2],
404 | },
405 | }
406 | },
407 | RGB: {
408 | convert: function(_cmy) {
409 | var r, g, b;
410 |
411 | r = (1 - _cmy.C) * 255;
412 | g = (1 - _cmy.M) * 255;
413 | b = (1 - _cmy.Y) * 255;
414 |
415 | return {
416 | R: r,
417 | G: g,
418 | B: b,
419 | };
420 | },
421 | cost: 0,
422 | },
423 | },
424 | RGBA: {
425 | import: function() {
426 | var input = flatten(arguments);
427 |
428 | if (input[0].check("R", "G", "B", "A")) {
429 | return {
430 | RGBA: input[0],
431 | };
432 | };
433 |
434 | if (input.length < 7) {
435 | return false;
436 | }
437 | for (var i = 0; i < 7; i++) {
438 | if (input[i] < 0 || input[i] > 255) return false;
439 | }
440 | if (input[3] > 1) return false;
441 | return {
442 | RGBA: {
443 | FR: input[0],
444 | FG: input[1],
445 | FB: input[2],
446 |
447 | Alpha: input[3],
448 | BR: input[4],
449 | BG: input[5],
450 | BB: input[6],
451 |
452 | },
453 | }
454 | },
455 | RGB: {
456 | convert: function(_rgba) {
457 | return {
458 | R: (1 - _rgba.Alpha) * _rgba.BR + _rgba.Alpha * _rgba.FR,
459 | G: (1 - _rgba.Alpha) * _rgba.BG + _rgba.Alpha * _rgba.FG,
460 | B: (1 - _rgba.Alpha) * _rgba.BB + _rgba.Alpha * _rgba.FB,
461 | }
462 | },
463 | cost: 1,
464 | },
465 | },
466 | CMYK: {
467 | import: function() {
468 | var input = flatten(arguments);
469 |
470 | if (input[0].check("C", "M", "Y", "K")) {
471 | return {
472 | CMYK: input[0],
473 | };
474 | };
475 |
476 | if (input.length < 4) {
477 | return false;
478 | }
479 | for (var i = 0; i < 4; i++) {
480 | if (input[i] < 0 || input[i] > 1) return false;
481 | }
482 | return {
483 | CMYK: {
484 | C: input[0],
485 | M: input[1],
486 | Y: input[2],
487 | K: input[3],
488 | },
489 | }
490 | },
491 | RGB: {
492 | convert: function(_cmyk) {
493 | var r, g, b;
494 |
495 | r = ((1 - _cmyk.K) * (1 - _cmyk.C)) * 255;
496 | g = ((1 - _cmyk.K) * (1 - _cmyk.M)) * 255;
497 | b = ((1 - _cmyk.K) * (1 - _cmyk.Y)) * 255;
498 |
499 | return {
500 | R: r,
501 | G: g,
502 | B: b,
503 | };
504 | },
505 | cost: 0,
506 | },
507 | },
508 | HSL: {
509 | import: function() {
510 | var input = flatten(arguments);
511 |
512 | if (input[0].check("H", "S", "L")) {
513 | return {
514 | HSL: input[0],
515 | };
516 | };
517 |
518 | if (input.length < 3) {
519 | return false;
520 | };
521 |
522 | if (input[0] < 0 || input[0] > 360 || input[1] < 0 || input[2] < 0 || input[1] > 1 || input[2] > 1) return false;
523 |
524 | return {
525 | HSL: {
526 | H: input[0],
527 | S: input[1],
528 | L: input[2],
529 | },
530 | };
531 | },
532 | RGB: {
533 | convert: function(_hsl) {
534 | var H = _hsl.H,
535 | S = _hsl.S,
536 | L = _hsl.L,
537 | _r, _g, _b,
538 |
539 | c = acc.mul(acc.sub(1, Math.abs(acc.sub(acc.mul(2, L), 1))), S),
540 | h = H / 60,
541 | x = acc.mul(c, (1 - Math.abs(h % 2 - 1))),
542 | i = parseInt(h),
543 | m = acc.sub(L, acc.div(c, 2));
544 |
545 | switch (i) {
546 | case 0:
547 | _r = c;
548 | _g = x;
549 | _b = 0;
550 | break;
551 | case 1:
552 | _r = x;
553 | _g = c;
554 | _b = 0;
555 | break;
556 | case 2:
557 | _r = 0;
558 | _g = c;
559 | _b = x;
560 | break;
561 | case 3:
562 | _r = 0;
563 | _g = x;
564 | _b = c;
565 | break;
566 | case 4:
567 | _r = x;
568 | _g = 0;
569 | _b = c;
570 | break;
571 | case 5:
572 | _r = c;
573 | _g = 0;
574 | _b = x;
575 | break;
576 | };
577 |
578 | _r = acc.add(_r, m);
579 | _g = acc.add(_g, m);
580 | _b = acc.add(_b, m);
581 |
582 | return {
583 | R: _r * 255,
584 | G: _g * 255,
585 | B: _b * 255,
586 | };
587 | },
588 | cost: 0,
589 | },
590 | },
591 | HSV: {
592 | import: function() {
593 | var input = flatten(arguments);
594 |
595 | if (input[0].check("H", "S", "L")) {
596 | return {
597 | HSL: input[0],
598 | };
599 | };
600 |
601 | if (input.length < 3) {
602 | return false;
603 | }
604 |
605 | if (input[0] < 0 || input[0] > 360 || input[1] < 0 || input[2] < 0 || input[1] > 1 || input[2] > 1) return false;
606 |
607 | return {
608 | HSV: {
609 | H: input[0],
610 | S: input[1],
611 | V: input[2],
612 | },
613 | }
614 | },
615 | RGB: {
616 | convert: function(_hsv) {
617 | var H = _hsv.H,
618 | S = _hsv.S,
619 | V = _hsv.V,
620 | _r, _g, _b,
621 |
622 | c = V * S,
623 | h = H / 60,
624 | x = c * (1 - Math.abs(h % 2 - 1)),
625 | i = parseInt(h),
626 | m = V - c;
627 |
628 | switch (i) {
629 | case 0:
630 | _r = c;
631 | _g = x;
632 | _b = 0;
633 | break;
634 | case 1:
635 | _r = x;
636 | _g = c;
637 | _b = 0;
638 | break;
639 | case 2:
640 | _r = 0;
641 | _g = c;
642 | _b = x;
643 | break;
644 | case 3:
645 | _r = 0;
646 | _g = x;
647 | _b = c;
648 | break;
649 | case 4:
650 | _r = x;
651 | _g = 0;
652 | _b = c;
653 | break;
654 | case 5:
655 | _r = c;
656 | _g = 0;
657 | _b = x;
658 | break;
659 | };
660 | _r += m;
661 | _g += m;
662 | _b += m;
663 | return {
664 | R: _r * 255,
665 | G: _g * 255,
666 | B: _b * 255,
667 | };
668 | },
669 | cost: 0,
670 | },
671 | },
672 | XYZ: {
673 | import: function() {
674 | var input = flatten(arguments);
675 |
676 | if (input[0].check("X", "Y", "Z")) {
677 | return {
678 | XYZ: input[0],
679 | };
680 | };
681 |
682 | if (input.length < 3) {
683 | return false;
684 | }
685 |
686 | return {
687 | XYZ: {
688 | X: input[0],
689 | Y: input[1],
690 | Z: input[2],
691 | },
692 | }
693 | },
694 | RGB: {
695 | convert: function(_xyz) {
696 |
697 | function ToRgb(n) {
698 | var result = 255 * n;
699 | if (result < 0) return 0;
700 | if (result > 255) return 255;
701 | return result;
702 | }
703 |
704 | var x = _xyz.X / 100.0,
705 | y = _xyz.Y / 100.0,
706 | z = _xyz.Z / 100.0,
707 |
708 | r = x * 3.2406 + y * -1.5372 + z * -0.4986,
709 | g = x * -0.9689 + y * 1.8758 + z * 0.0415,
710 | b = x * 0.0557 + y * -0.2040 + z * 1.0570;
711 |
712 | r = r > 0.0031308 ? 1.055 * Math.pow(r, 1 / 2.4) - 0.055 : 12.92 * r;
713 | g = g > 0.0031308 ? 1.055 * Math.pow(g, 1 / 2.4) - 0.055 : 12.92 * g;
714 | b = b > 0.0031308 ? 1.055 * Math.pow(b, 1 / 2.4) - 0.055 : 12.92 * b;
715 |
716 | return {
717 | R: ToRgb(r),
718 | G: ToRgb(g),
719 | B: ToRgb(b),
720 | };
721 | },
722 | cost: 1,
723 | },
724 | Lab: {
725 | convert: function(_xyz) {
726 |
727 | function PivotXyz(n) {
728 | return n > spaces.constant.Epsilon ? spaces.constant.CubicRoot(n) : (spaces.constant.Kappa * n + 16) / 116;
729 | }
730 |
731 | var white = spaces.constant.XYZ_WhiteRefrence,
732 | x = PivotXyz(_xyz.X / white.X),
733 | y = PivotXyz(_xyz.Y / white.Y),
734 | z = PivotXyz(_xyz.Z / white.Z);
735 |
736 | return {
737 | L: Math.max(0, 116 * y - 16),
738 | a: 500 * (x - y),
739 | b: 200 * (y - z),
740 | }
741 | },
742 | cost: 1,
743 | },
744 | LUV: {
745 | convert: function(_xyz) {
746 |
747 | function GetDenominator(xyz) {
748 | return xyz.X + 15.0 * xyz.Y + 3.0 * xyz.Z;
749 | }
750 |
751 | var white = spaces.constant.XYZ_WhiteRefrence,
752 | y = _xyz.Y / white.Y,
753 | L = y > spaces.constant.Epsilon ? 116.0 * spaces.constant.CubicRoot(y) - 16.0 : spaces.constant.Kappa * y,
754 | targetDenominator = GetDenominator(_xyz),
755 | referenceDenominator = GetDenominator(white),
756 | xTarget = targetDenominator == 0 ? 0 : ((4.0 * _xyz.X / targetDenominator) - (4.0 * white.X / referenceDenominator)),
757 | yTarget = targetDenominator == 0 ? 0 : ((9.0 * _xyz.Y / targetDenominator) - (9.0 * white.Y / referenceDenominator)),
758 | U = 13.0 * L * xTarget,
759 | V = 13.0 * L * yTarget;
760 |
761 | return {
762 | L: L,
763 | U: U,
764 | V: V,
765 | }
766 | },
767 | cost: 1,
768 | },
769 | },
770 | Lab: {
771 | import: function() {
772 | var input = flatten(arguments);
773 |
774 | if (input[0].check("L", "a", "b")) {
775 | return {
776 | Lab: input[0],
777 | };
778 | };
779 |
780 | if (input.length < 3) {
781 | return false;
782 | }
783 |
784 | return {
785 | Lab: {
786 | L: input[0],
787 | a: input[1],
788 | b: input[2],
789 | },
790 | };
791 | },
792 | XYZ: {
793 | convert: function(_lab) {
794 | var y = (_lab.L + 16.0) / 116.0,
795 | x = _lab.a / 500.0 + y,
796 | z = y - _lab.b / 200.0,
797 | white = spaces.constant.XYZ_WhiteRefrence,
798 | x3 = x * x * x,
799 | z3 = z * z * z;
800 | return {
801 | X: white.X * (x3 > spaces.constant.Epsilon ? x3 : (x - 16.0 / 116.0) / 7.787),
802 | Y: white.Y * (_lab.L > (spaces.constant.Kappa * spaces.constant.Epsilon) ? Math.pow(((_lab.L + 16.0) / 116.0), 3) : _lab.L / spaces.constant.Kappa),
803 | Z: white.Z * (z3 > spaces.constant.Epsilon ? z3 : (z - 16.0 / 116.0) / 7.787),
804 | };
805 | },
806 | cost: 1,
807 | },
808 | LCH: {
809 | convert: function(_lab) {
810 | var h = Math.atan2(_lab.b, _lab.a);
811 |
812 | if (h > 0) {
813 | h = (h / Math.PI) * 180.0;
814 | } else {
815 | h = 360 - (Math.abs(h) / Math.PI) * 180.0;
816 | }
817 |
818 | if (h < 0) {
819 | h += 360.0;
820 | } else if (h >= 360) {
821 | h -= 360.0;
822 | }
823 |
824 | return {
825 | L: _lab.L,
826 | C: Math.sqrt(_lab.a * _lab.a + _lab.b * _lab.b),
827 | H: h,
828 | }
829 | },
830 | cost: 1,
831 | },
832 | },
833 | LCH: {
834 | import: function() {
835 | var input = flatten(arguments);
836 |
837 | if (input[0].check("L", "C", "H")) {
838 | return {
839 | LCH: input[0],
840 | };
841 | };
842 |
843 | if (input.length < 3) {
844 | return false;
845 | }
846 |
847 | return {
848 | LCH: {
849 | L: input[0],
850 | C: input[1],
851 | H: input[2],
852 | },
853 | };
854 | },
855 | Lab: {
856 | convert: function(_lch) {
857 | var hRadians = _lch.H * Math.PI / 180.0;
858 | return {
859 | L: _lch.L,
860 | a: Math.cos(hRadians) * _lch.C,
861 | b: Math.sin(hRadians) * _lch.C,
862 | };
863 | },
864 | cost: 1,
865 | },
866 | },
867 | LUV: {
868 | import: function() {
869 | var input = flatten(arguments);
870 |
871 | if (input[0].check("L", "U", "V")) {
872 | return {
873 | LUV: input[0],
874 | };
875 | };
876 |
877 | if (input.length < 3) {
878 | return false;
879 | }
880 |
881 | return {
882 | LUV: {
883 | L: input[0],
884 | U: input[1],
885 | V: input[2],
886 | },
887 | };
888 | },
889 | XYZ: {
890 | convert: function(_luv) {
891 |
892 | function GetDenominator(xyz) {
893 | return xyz.X + 15.0 * xyz.Y + 3.0 * xyz.Z;
894 | }
895 |
896 | var white = spaces.constant.XYZ_WhiteRefrence,
897 | c = -1.0 / 3.0,
898 | uPrime = (4.0 * white.X) / GetDenominator(white),
899 | vPrime = (9.0 * white.Y) / GetDenominator(white),
900 | a = (1.0 / 3.0) * ((52.0 * _luv.L) / (_luv.U + 13 * _luv.L * uPrime) - 1.0),
901 | imteL_16_116 = (_luv.L + 16.0) / 116.0,
902 | y = _luv.L > spaces.constant.Kappa * spaces.constant.Epsilon ? imteL_16_116 * imteL_16_116 * imteL_16_116 : _luv.L / spaces.constant.Kappa,
903 | b = -5.0 * y,
904 | d = y * ((39.0 * _luv.L) / (_luv.V + 13.0 * _luv.L * vPrime) - 5.0),
905 | x = (d - b) / (a - c),
906 | z = x * a + b;
907 | return {
908 | X: 100 * x,
909 | Y: 100 * y,
910 | Z: 100 * z,
911 | };
912 | },
913 | cost: 1,
914 | },
915 | },
916 | };
917 |
918 | var defaults = {
919 | colors: [],
920 | };
921 |
922 | /* Main function */
923 | function ColorConverter(options) {
924 | var self = this;
925 | self.colors = [];
926 |
927 | if (!(self instanceof ColorConverter)) {
928 | return new ColorConverter(options);
929 | };
930 |
931 | self.options = options || {};
932 |
933 | for (var i in defaults) {
934 | if (self.options[i] == null) {
935 | self.options[i] = defaults[i];
936 | };
937 | };
938 |
939 | if (!!self.options.colors) {
940 | self.import(self.options.colors);
941 | };
942 | };
943 |
944 | /* Extend functions */
945 | ColorConverter.prototype = {
946 |
947 | constructor: ColorConverter,
948 |
949 | import: function() {
950 | var argu = Array.prototype.slice.call(arguments)[0],
951 | output = [],
952 | self = this;
953 |
954 | for (var i = 0; i < argu.length; i++) {
955 |
956 | var _temp = flatten(argu[i]);
957 | /*split temp*/
958 | var _format = _temp.shift(),
959 | _para = _temp;
960 |
961 | if (!spaces.hasOwnProperty(_format)) {
962 | throw Error("Unsupport color spaces");
963 | };
964 |
965 | var _obj = eval("(spaces." + _format + ".import)");
966 |
967 | if (_obj === undefined) {
968 | throw Error("Cannot convert from " + _format);
969 | };
970 |
971 | var _res = _obj.call(this, _para);
972 |
973 | if (!!_res) {
974 | self.colors.push(_res);
975 | output.push(self.colors.length - 1);
976 | } else {
977 | output.push(false);
978 | };
979 | };
980 |
981 | return output;
982 | },
983 |
984 | export: function() {
985 | var argu = flatten(arguments),
986 | format = argu.shift(),
987 | list = argu,
988 | output = [],
989 | self = this;
990 |
991 | if (!list.length) {
992 | for (var i in self.colors) {
993 | if (self.colors.hasOwnProperty(i)) {
994 | list.push(i);
995 | };
996 | };
997 | };
998 |
999 | list.forEach(function(_i) {
1000 |
1001 | var _code = self.colors[_i];
1002 |
1003 | if (_code === undefined) {
1004 | throw Error("Undefined color");
1005 | };
1006 |
1007 | var _key = (function(_code) {
1008 | for (var i in _code) {
1009 | return i;
1010 | }
1011 | })(_code),
1012 | _temp = _code[_key],
1013 | _tokens = [{
1014 | _path: [_key],
1015 | _cost: 0,
1016 | _terminal: false,
1017 | }],
1018 | _target = format,
1019 | _depth = 0;
1020 |
1021 |
1022 |
1023 | while (!(function(tokens, target) {
1024 | var flag = false;
1025 | for (var key in tokens) {
1026 | if (tokens.hasOwnProperty(key)) {
1027 | if (!tokens[key]._terminal) {
1028 | return false;
1029 | };
1030 | };
1031 | };
1032 | return true;
1033 | })(_tokens, _target) && _depth < 10) {
1034 |
1035 | var _deplicate = [];
1036 |
1037 | for (var key in _tokens) {
1038 | if (_tokens.hasOwnProperty(key)) {
1039 |
1040 | var _on = _tokens[key],
1041 | _nowkey = _on._path.getLast();
1042 |
1043 | if (spaces.hasOwnProperty(_nowkey)) {
1044 |
1045 | var _obj = eval("(spaces." + _nowkey + ")");
1046 |
1047 | for (var key in _obj) {
1048 | if (_obj.hasOwnProperty(key)) {
1049 |
1050 | var _temp = cloneObject(_on);
1051 |
1052 | if (_on._path.search(key) || _on._path.getLast() == _target) {
1053 | _temp._terminal = true;
1054 | } else {
1055 | _temp._path.push(key);
1056 | _temp._cost += eval("(spaces." + _nowkey + "." + key + ".cost)");
1057 | };
1058 |
1059 | _deplicate.push(_temp);
1060 | };
1061 | };
1062 |
1063 | _obj = null;
1064 |
1065 | };
1066 | };
1067 | };
1068 |
1069 | _tokens = _deplicate;
1070 | _deplicate = null;
1071 |
1072 | _depth++;
1073 | };
1074 |
1075 | if (!_tokens.length) {
1076 | throw Error("No path to target");
1077 | };
1078 |
1079 | var _sort = [];
1080 |
1081 | for (var key in _tokens) {
1082 | if (_tokens.hasOwnProperty(key) && _tokens[key] && _tokens[key]._path.getLast() == _target) {
1083 | _sort.push(_tokens[key]);
1084 | };
1085 | };
1086 |
1087 | _sort.sort(function(a, b) {
1088 | return a.cost > b.cost ? -1 : 1;
1089 | });
1090 |
1091 | if (!!_sort.length) {
1092 |
1093 | var _rp = _sort[0]._path,
1094 | _temp = eval("(_code." + _rp[0] + ")");
1095 |
1096 | for (var i = 1; i < _rp.length; i++) {
1097 | _temp = eval("(spaces." + _rp[i - 1] + "." + _rp[i] + ".convert(" + JSON.stringify(_temp) + "))");
1098 | };
1099 |
1100 | output.push(_temp);
1101 |
1102 | }
1103 |
1104 | })
1105 | return output;
1106 | },
1107 |
1108 | reset: function() {
1109 | var self = this;
1110 | self.colors = [];
1111 | return true;
1112 | },
1113 |
1114 | }
1115 |
1116 | window.ColorConverter = ColorConverter;
1117 |
1118 | })(window, document);
1119 |
--------------------------------------------------------------------------------