source: other-projects/nz-flag-design/trunk/similarity-2d/js-lib/Colour.src.js@ 29627

Last change on this file since 29627 was 29627, checked in by davidb, 9 years ago

Colour conversion JS library

File size: 18.0 KB
Line 
1/*
2
3Colour.js
4
5Objects for handling and processing colours
6
7Created by Stephen Morley - http://code.stephenmorley.org/ - and released under
8the terms of the CC0 1.0 Universal legal code:
9
10http://creativecommons.org/publicdomain/zero/1.0/legalcode
11
12*/
13
14/* An abstract Colour implementation. Concrete Colour implementations should use
15 * an instance of this function as their prototype, and implement the getRGB and
16 * getHSL functions. getRGB should return an object representing the RGB
17 * components of this Colour, with the red, green, and blue components in the
18 * range [0,255] and the alpha component in the range [0,100]. getHSL should
19 * return an object representing the HSL components of this Colour, with the hue
20 * component in the range [0,360), the saturation and lightness components in
21 * the range [0,100], and the alpha component in the range [0,1].
22 */
23function Colour(){
24
25 /* Returns an object representing the RGBA components of this Colour. The red,
26 * green, and blue components are converted to integers in the range [0,255].
27 * The alpha is a value in the range [0,1].
28 */
29 this.getIntegerRGB = function(){
30
31 // get the RGB components of this colour
32 var rgb = this.getRGB();
33
34 // return the integer components
35 return {
36 'r' : Math.round(rgb.r),
37 'g' : Math.round(rgb.g),
38 'b' : Math.round(rgb.b),
39 'a' : rgb.a
40 };
41
42 };
43
44 /* Returns an object representing the RGBA components of this Colour. The red,
45 * green, and blue components are converted to numbers in the range [0,100].
46 * The alpha is a value in the range [0,1].
47 */
48 this.getPercentageRGB = function(){
49
50 // get the RGB components of this colour
51 var rgb = this.getRGB();
52
53 // return the percentage components
54 return {
55 'r' : 100 * rgb.r / 255,
56 'g' : 100 * rgb.g / 255,
57 'b' : 100 * rgb.b / 255,
58 'a' : rgb.a
59 };
60
61 };
62
63 /* Returns a string representing this Colour as a CSS hexadecimal RGB colour
64 * value - that is, a string of the form #RRGGBB where each of RR, GG, and BB
65 * are two-digit hexadecimal numbers.
66 */
67 this.getCSSHexadecimalRGB = function(){
68
69 // get the integer RGB components
70 var rgb = this.getIntegerRGB();
71
72 // determine the hexadecimal equivalents
73 var r16 = rgb.r.toString(16);
74 var g16 = rgb.g.toString(16);
75 var b16 = rgb.b.toString(16);
76
77 // return the CSS RGB colour value
78 return '#'
79 + (r16.length == 2 ? r16 : '0' + r16)
80 + (g16.length == 2 ? g16 : '0' + g16)
81 + (b16.length == 2 ? b16 : '0' + b16);
82
83 };
84
85 /* Returns a string representing this Colour as a CSS integer RGB colour
86 * value - that is, a string of the form rgb(r,g,b) where each of r, g, and b
87 * are integers in the range [0,255].
88 */
89 this.getCSSIntegerRGB = function(){
90
91 // get the integer RGB components
92 var rgb = this.getIntegerRGB();
93
94 // return the CSS RGB colour value
95 return 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')';
96
97 };
98
99 /* Returns a string representing this Colour as a CSS integer RGBA colour
100 * value - that is, a string of the form rgba(r,g,b,a) where each of r, g, and
101 * b are integers in the range [0,255] and a is in the range [0,1].
102 */
103 this.getCSSIntegerRGBA = function(){
104
105 // get the integer RGB components
106 var rgb = this.getIntegerRGB();
107
108 // return the CSS integer RGBA colour value
109 return 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + rgb.a + ')';
110
111 };
112
113 /* Returns a string representing this Colour as a CSS percentage RGB colour
114 * value - that is, a string of the form rgb(r%,g%,b%) where each of r, g, and
115 * b are in the range [0,100].
116 */
117 this.getCSSPercentageRGB = function(){
118
119 // get the percentage RGB components
120 var rgb = this.getPercentageRGB();
121
122 // return the CSS RGB colour value
123 return 'rgb(' + rgb.r + '%,' + rgb.g + '%,' + rgb.b + '%)';
124
125 };
126
127 /* Returns a string representing this Colour as a CSS percentage RGBA colour
128 * value - that is, a string of the form rgba(r%,g%,b%,a) where each of r, g,
129 * and b are in the range [0,100] and a is in the range [0,1].
130 */
131 this.getCSSPercentageRGBA = function(){
132
133 // get the percentage RGB components
134 var rgb = this.getPercentageRGB();
135
136 // return the CSS percentage RGBA colour value
137 return 'rgba(' + rgb.r + '%,' + rgb.g + '%,' + rgb.b + '%,' + rgb.a + ')';
138
139 };
140
141 /* Returns a string representing this Colour as a CSS HSL colour value - that
142 * is, a string of the form hsl(h,s%,l%) where h is in the range [0,360) and
143 * s and l are in the range [0,100].
144 */
145 this.getCSSHSL = function(){
146
147 // get the HSL components
148 var hsl = this.getHSL();
149
150 // return the CSS HSL colour value
151 return 'hsl(' + hsl.h + ',' + hsl.s + '%,' + hsl.l + '%)';
152
153 };
154
155 /* Returns a string representing this Colour as a CSS HSLA colour value - that
156 * is, a string of the form hsla(h,s%,l%,a) where h is in the range [0,360),
157 * s and l are in the range [0,100], and a is in the range [0,1].
158 */
159 this.getCSSHSLA = function(){
160
161 // get the HSL components
162 var hsl = this.getHSL();
163
164 // return the CSS HSL colour value
165 return 'hsla(' + hsl.h + ',' + hsl.s + '%,' + hsl.l + '%,' + hsl.a + ')';
166
167 };
168
169 /* Sets the colour of the specified node to this Colour. This function sets
170 * the CSS 'color' property for the node. The parameter is:
171 *
172 * node - the node whose colour should be set
173 */
174 this.setNodeColour = function(node){
175
176 // set the colour of the node
177 node.style.color = this.getCSSHexadecimalRGB();
178
179 };
180
181 /* Sets the background colour of the specified node to this Colour. This
182 * function sets the CSS 'background-color' property for the node. The
183 * parameter is:
184 *
185 * node - the node whose background colour should be set
186 */
187 this.setNodeBackgroundColour = function(node){
188
189 // set the background colour of the node
190 node.style.backgroundColor = this.getCSSHexadecimalRGB();
191
192 };
193
194}
195
196/* Creates a colour specified in the RGB colour space, with an optional alpha
197 * component. The parameters are:
198 *
199 * r - the red component, clipped to the range [0,255]
200 * g - the green component, clipped to the range [0,255]
201 * b - the blue component, clipped to the range [0,255]
202 * a - the alpha component, clipped to the range [0,1] - this parameter is
203 * optional and defaults to 1
204 */
205RGBColour.prototype = new Colour();
206function RGBColour(r, g, b, a){
207
208 // store the alpha component after clipping it if necessary
209 var alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
210
211 // store the RGB components after clipping them if necessary
212 var rgb =
213 {
214 'r' : Math.max(0, Math.min(255, r)),
215 'g' : Math.max(0, Math.min(255, g)),
216 'b' : Math.max(0, Math.min(255, b))
217 };
218
219 // initialise the HSV and HSL components to null
220 var hsv = null;
221 var hsl = null;
222
223 /* Returns the HSV or HSL hue component of this RGBColour. The hue is in the
224 * range [0,360). The parameters are:
225 *
226 * maximum - the maximum of the RGB component values
227 * range - the range of the RGB component values
228 */
229 function getHue(maximum, range){
230
231 // check whether the range is zero
232 if (range == 0){
233
234 // set the hue to zero (any hue is acceptable as the colour is grey)
235 var hue = 0;
236
237 }else{
238
239 // determine which of the components has the highest value and set the hue
240 switch (maximum){
241
242 // red has the highest value
243 case rgb.r:
244 var hue = (rgb.g - rgb.b) / range * 60;
245 if (hue < 0) hue += 360;
246 break;
247
248 // green has the highest value
249 case rgb.g:
250 var hue = (rgb.b - rgb.r) / range * 60 + 120;
251 break;
252
253 // blue has the highest value
254 case rgb.b:
255 var hue = (rgb.r - rgb.g) / range * 60 + 240;
256 break;
257
258 }
259
260 }
261
262 // return the hue
263 return hue;
264
265 }
266
267 /* Calculates and stores the HSV components of this RGBColour so that they can
268 * be returned be the getHSV function.
269 */
270 function calculateHSV(){
271
272 // get the maximum and range of the RGB component values
273 var maximum = Math.max(rgb.r, rgb.g, rgb.b);
274 var range = maximum - Math.min(rgb.r, rgb.g, rgb.b);
275
276 // store the HSV components
277 hsv =
278 {
279 'h' : getHue(maximum, range),
280 's' : (maximum == 0 ? 0 : 100 * range / maximum),
281 'v' : maximum / 2.55
282 };
283
284 }
285
286 /* Calculates and stores the HSL components of this RGBColour so that they can
287 * be returned be the getHSL function.
288 */
289 function calculateHSL(){
290
291 // get the maximum and range of the RGB component values
292 var maximum = Math.max(rgb.r, rgb.g, rgb.b);
293 var range = maximum - Math.min(rgb.r, rgb.g, rgb.b);
294
295 // determine the lightness in the range [0,1]
296 var l = maximum / 255 - range / 510;
297
298 // store the HSL components
299 hsl =
300 {
301 'h' : getHue(maximum, range),
302 's' : (range == 0 ? 0 : range / 2.55 / (l < 0.5 ? l * 2 : 2 - l * 2)),
303 'l' : 100 * l
304 };
305
306 }
307
308 /* Returns the RGB and alpha components of this RGBColour as an object with r,
309 * g, b, and a properties. r, g, and b are in the range [0,255] and a is in
310 * the range [0,1].
311 */
312 this.getRGB = function(){
313
314 // return the RGB components
315 return {
316 'r' : rgb.r,
317 'g' : rgb.g,
318 'b' : rgb.b,
319 'a' : alpha
320 };
321
322 };
323
324 /* Returns the HSV and alpha components of this RGBColour as an object with h,
325 * s, v, and a properties. h is in the range [0,360), s and v are in the range
326 * [0,100], and a is in the range [0,1].
327 */
328 this.getHSV = function(){
329
330 // calculate the HSV components if necessary
331 if (hsv == null) calculateHSV();
332
333 // return the HSV components
334 return {
335 'h' : hsv.h,
336 's' : hsv.s,
337 'v' : hsv.v,
338 'a' : alpha
339 };
340
341 };
342
343 /* Returns the HSL and alpha components of this RGBColour as an object with h,
344 * s, l, and a properties. h is in the range [0,360), s and l are in the range
345 * [0,100], and a is in the range [0,1].
346 */
347 this.getHSL = function(){
348
349 // calculate the HSV components if necessary
350 if (hsl == null) calculateHSL();
351
352 // return the HSL components
353 return {
354 'h' : hsl.h,
355 's' : hsl.s,
356 'l' : hsl.l,
357 'a' : alpha
358 };
359
360 };
361
362}
363
364/* Creates a colour specified in the HSV colour space, with an optional alpha
365 * component. The parameters are:
366 *
367 * h - the hue component, wrapped to the range [0,360)
368 * s - the saturation component, clipped to the range [0,100]
369 * v - the value component, clipped to the range [0,100]
370 * a - the alpha component, clipped to the range [0,1] - this parameter is
371 * optional and defaults to 1
372 */
373HSVColour.prototype = new Colour();
374function HSVColour(h, s, v, a){
375
376 // store the alpha component after clipping it if necessary
377 var alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
378
379 // store the HSV components after clipping or wrapping them if necessary
380 var hsv =
381 {
382 'h' : (h % 360 + 360) % 360,
383 's' : Math.max(0, Math.min(100, s)),
384 'v' : Math.max(0, Math.min(100, v))
385 };
386
387 // initialise the RGB and HSL components to null
388 var rgb = null;
389 var hsl = null;
390
391 /* Calculates and stores the RGB components of this HSVColour so that they can
392 * be returned be the getRGB function.
393 */
394 function calculateRGB(){
395
396 // check whether the saturation is zero
397 if (hsv.s == 0){
398
399 // set the colour to the appropriate shade of grey
400 var r = hsv.v;
401 var g = hsv.v;
402 var b = hsv.v;
403
404 }else{
405
406 // set some temporary values
407 var f = hsv.h / 60 - Math.floor(hsv.h / 60);
408 var p = hsv.v * (1 - hsv.s / 100);
409 var q = hsv.v * (1 - hsv.s / 100 * f);
410 var t = hsv.v * (1 - hsv.s / 100 * (1 - f));
411
412 // set the RGB colour components to their temporary values
413 switch (Math.floor(hsv.h / 60)){
414 case 0: var r = hsv.v; var g = t; var b = p; break;
415 case 1: var r = q; var g = hsv.v; var b = p; break;
416 case 2: var r = p; var g = hsv.v; var b = t; break;
417 case 3: var r = p; var g = q; var b = hsv.v; break;
418 case 4: var r = t; var g = p; var b = hsv.v; break;
419 case 5: var r = hsv.v; var g = p; var b = q; break;
420 }
421
422 }
423
424 // store the RGB components
425 rgb =
426 {
427 'r' : r * 2.55,
428 'g' : g * 2.55,
429 'b' : b * 2.55
430 };
431
432 }
433
434 /* Calculates and stores the HSL components of this HSVColour so that they can
435 * be returned be the getHSL function.
436 */
437 function calculateHSL(){
438
439 // determine the lightness in the range [0,100]
440 var l = (2 - hsv.s / 100) * hsv.v / 2;
441
442 // store the HSL components
443 hsl =
444 {
445 'h' : hsv.h,
446 's' : hsv.s * hsv.v / (l < 50 ? l * 2 : 200 - l * 2),
447 'l' : l
448 };
449
450 // correct a division-by-zero error
451 if (isNaN(hsl.s)) hsl.s = 0;
452
453 }
454
455 /* Returns the RGB and alpha components of this HSVColour as an object with r,
456 * g, b, and a properties. r, g, and b are in the range [0,255] and a is in
457 * the range [0,1].
458 */
459 this.getRGB = function(){
460
461 // calculate the RGB components if necessary
462 if (rgb == null) calculateRGB();
463
464 // return the RGB components
465 return {
466 'r' : rgb.r,
467 'g' : rgb.g,
468 'b' : rgb.b,
469 'a' : alpha
470 };
471
472 };
473
474 /* Returns the HSV and alpha components of this HSVColour as an object with h,
475 * s, v, and a properties. h is in the range [0,360), s and v are in the range
476 * [0,100], and a is in the range [0,1].
477 */
478 this.getHSV = function(){
479
480 // return the HSV components
481 return {
482 'h' : hsv.h,
483 's' : hsv.s,
484 'v' : hsv.v,
485 'a' : alpha
486 };
487
488 };
489
490 /* Returns the HSL and alpha components of this HSVColour as an object with h,
491 * s, l, and a properties. h is in the range [0,360), s and l are in the range
492 * [0,100], and a is in the range [0,1].
493 */
494 this.getHSL = function(){
495
496 // calculate the HSL components if necessary
497 if (hsl == null) calculateHSL();
498
499 // return the HSL components
500 return {
501 'h' : hsl.h,
502 's' : hsl.s,
503 'l' : hsl.l,
504 'a' : alpha
505 };
506
507 };
508
509}
510
511/* Creates a colour specified in the HSL colour space, with an optional alpha
512 * component. The parameters are:
513 *
514 * h - the hue component, wrapped to the range [0,360)
515 * s - the saturation component, clipped to the range [0,100]
516 * l - the lightness component, clipped to the range [0,100]
517 * a - the alpha component, clipped to the range [0,1] - this parameter is
518 * optional and defaults to 1
519 */
520HSLColour.prototype = new Colour();
521function HSLColour(h, s, l, a){
522
523 // store the alpha component after clipping it if necessary
524 var alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
525
526 // store the HSL components after clipping or wrapping them if necessary
527 var hsl =
528 {
529 'h' : (h % 360 + 360) % 360,
530 's' : Math.max(0, Math.min(100, s)),
531 'l' : Math.max(0, Math.min(100, l))
532 };
533
534 // initialise the RGB and HSV components to null
535 var rgb = null;
536 var hsv = null;
537
538 /* Calculates and stores the RGB components of this HSLColour so that they can
539 * be returned be the getRGB function.
540 */
541 function calculateRGB(){
542
543 // check whether the saturation is zero
544 if (hsl.s == 0){
545
546 // store the RGB components representing the appropriate shade of grey
547 rgb =
548 {
549 'r' : hsl.l * 2.55,
550 'g' : hsl.l * 2.55,
551 'b' : hsl.l * 2.55
552 };
553
554 }else{
555
556 // set some temporary values
557 var p = hsl.l < 50
558 ? hsl.l * (1 + hsl.s / 100)
559 : hsl.l + hsl.s - hsl.l * hsl.s / 100;
560 var q = 2 * hsl.l - p;
561
562 // initialise the RGB components
563 rgb =
564 {
565 'r' : (h + 120) / 60 % 6,
566 'g' : h / 60,
567 'b' : (h + 240) / 60 % 6
568 };
569
570 // loop over the RGB components
571 for (var key in rgb){
572
573 // ensure that the property is not inherited from the root object
574 if (rgb.hasOwnProperty(key)){
575
576 // set the component to its value in the range [0,100]
577 if (rgb[key] < 1){
578 rgb[key] = q + (p - q) * rgb[key];
579 }else if (rgb[key] < 3){
580 rgb[key] = p;
581 }else if (rgb[key] < 4){
582 rgb[key] = q + (p - q) * (4 - rgb[key]);
583 }else{
584 rgb[key] = q;
585 }
586
587 // set the component to its value in the range [0,255]
588 rgb[key] *= 2.55;
589
590 }
591
592 }
593
594 }
595
596 }
597
598 /* Calculates and stores the HSV components of this HSLColour so that they can
599 * be returned be the getHSL function.
600 */
601 function calculateHSV(){
602
603 // set a temporary value
604 var t = hsl.s * (hsl.l < 50 ? hsl.l : 100 - hsl.l) / 100;
605
606 // store the HSV components
607 hsv =
608 {
609 'h' : hsl.h,
610 's' : 200 * t / (hsl.l + t),
611 'v' : t + hsl.l
612 };
613
614 // correct a division-by-zero error
615 if (isNaN(hsv.s)) hsv.s = 0;
616
617 }
618
619 /* Returns the RGB and alpha components of this HSLColour as an object with r,
620 * g, b, and a properties. r, g, and b are in the range [0,255] and a is in
621 * the range [0,1].
622 */
623 this.getRGB = function(){
624
625 // calculate the RGB components if necessary
626 if (rgb == null) calculateRGB();
627
628 // return the RGB components
629 return {
630 'r' : rgb.r,
631 'g' : rgb.g,
632 'b' : rgb.b,
633 'a' : alpha
634 };
635
636 };
637
638 /* Returns the HSV and alpha components of this HSLColour as an object with h,
639 * s, v, and a properties. h is in the range [0,360), s and v are in the range
640 * [0,100], and a is in the range [0,1].
641 */
642 this.getHSV = function(){
643
644 // calculate the HSV components if necessary
645 if (hsv == null) calculateHSV();
646
647 // return the HSV components
648 return {
649 'h' : hsv.h,
650 's' : hsv.s,
651 'v' : hsv.v,
652 'a' : alpha
653 };
654
655 };
656
657 /* Returns the HSL and alpha components of this HSLColour as an object with h,
658 * s, l, and a properties. h is in the range [0,360), s and l are in the range
659 * [0,100], and a is in the range [0,1].
660 */
661 this.getHSL = function(){
662
663 // return the HSL components
664 return {
665 'h' : hsl.h,
666 's' : hsl.s,
667 'l' : hsl.l,
668 'a' : alpha
669 };
670
671 };
672
673}
Note: See TracBrowser for help on using the repository browser.