/js/BubbleDots/lib/color.js
JavaScript | 261 lines | 159 code | 27 blank | 75 comment | 19 complexity | 1827978974dc39644c08e30cc5adf5e9 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
1/** 2 * @author Hyperandroid || http://hyperandroid.com/ 3 * 4 * Helper classes for color manipulation. 5 * 6 **/ 7 8(function() { 9 CAAT = (typeof CAAT === 'undefined') ? {} : CAAT; 10 11 /** 12 * Class with color utilities. 13 * 14 * @constructor 15 */ 16 CAAT.Color = function() { 17 return this; 18 }; 19 CAAT.Color.prototype= { 20 /** 21 * HSV to RGB color conversion 22 * <p> 23 * H runs from 0 to 360 degrees<br> 24 * S and V run from 0 to 100 25 * <p> 26 * Ported from the excellent java algorithm by Eugene Vishnevsky at: 27 * http://www.cs.rit.edu/~ncs/color/t_convert.html 28 * 29 * @static 30 */ 31 hsvToRgb: function(h, s, v) 32 { 33 var r, g, b; 34 var i; 35 var f, p, q, t; 36 37 // Make sure our arguments stay in-range 38 h = Math.max(0, Math.min(360, h)); 39 s = Math.max(0, Math.min(100, s)); 40 v = Math.max(0, Math.min(100, v)); 41 42 // We accept saturation and value arguments from 0 to 100 because that's 43 // how Photoshop represents those values. Internally, however, the 44 // saturation and value are calculated from a range of 0 to 1. We make 45 // That conversion here. 46 s /= 100; 47 v /= 100; 48 49 if(s == 0) { 50 // Achromatic (grey) 51 r = g = b = v; 52 return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; 53 } 54 55 h /= 60; // sector 0 to 5 56 i = Math.floor(h); 57 f = h - i; // factorial part of h 58 p = v * (1 - s); 59 q = v * (1 - s * f); 60 t = v * (1 - s * (1 - f)); 61 62 switch(i) { 63 case 0: 64 r = v; 65 g = t; 66 b = p; 67 break; 68 69 case 1: 70 r = q; 71 g = v; 72 b = p; 73 break; 74 75 case 2: 76 r = p; 77 g = v; 78 b = t; 79 break; 80 81 case 3: 82 r = p; 83 g = q; 84 b = v; 85 break; 86 87 case 4: 88 r = t; 89 g = p; 90 b = v; 91 break; 92 93 default: // case 5: 94 r = v; 95 g = p; 96 b = q; 97 } 98 99 return new CAAT.Color.RGB(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)); 100 }, 101 /** 102 * Enumeration to define types of color ramps. 103 * @enum {number} 104 */ 105 RampEnumeration : { 106 RAMP_RGBA: 0, 107 RAMP_RGB: 1, 108 RAMP_CHANNEL_RGB: 2, 109 RAMP_CHANNEL_RGBA: 3, 110 RAMP_CHANNEL_RGB_ARRAY: 4, 111 RAMP_CHANNEL_RGBA_ARRAY:5 112 }, 113 114 /** 115 * Interpolate the color between two given colors. The return value will be a calculated color 116 * among the two given initial colors which corresponds to the 'step'th color of the 'nsteps' 117 * calculated colors. 118 * @param r0 {number} initial color red component. 119 * @param g0 {number} initial color green component. 120 * @param b0 {number} initial color blue component. 121 * @param r1 {number} final color red component. 122 * @param g1 {number} final color green component. 123 * @param b1 {number} final color blue component. 124 * @param nsteps {number} number of colors to calculate including the two given colors. If 16 is passed as value, 125 * 14 colors plus the two initial ones will be calculated. 126 * @param step {number} return this color index of all the calculated colors. 127 * 128 * @return { r{number}, g{number}, b{number} } return an object with the new calculated color components. 129 * @static 130 */ 131 interpolate : function( r0, g0, b0, r1, g1, b1, nsteps, step) { 132 if ( step<=0 ) { 133 return { 134 r:r0, 135 g:g0, 136 b:b0 137 }; 138 } else if ( step>=nsteps ) { 139 return { 140 r:r1, 141 g:g1, 142 b:b1 143 }; 144 } 145 146 var r= (r0+ (r1-r0)/nsteps*step)>>0; 147 var g= (g0+ (g1-g0)/nsteps*step)>>0; 148 var b= (b0+ (b1-b0)/nsteps*step)>>0; 149 150 if ( r>255 ) {r=255;} else if (r<0) {r=0;} 151 if ( g>255 ) {g=255;} else if (g<0) {g=0;} 152 if ( b>255 ) {b=255;} else if (b<0) {b=0;} 153 154 return { 155 r:r, 156 g:g, 157 b:b 158 }; 159 }, 160 /** 161 * Generate a ramp of colors from an array of given colors. 162 * @param fromColorsArray {[number]} an array of colors. each color is defined by an integer number from which 163 * color components will be extracted. Be aware of the alpha component since it will also be interpolated for 164 * new colors. 165 * @param rampSize {number} number of colors to produce. 166 * @param returnType {CAAT.ColorUtils.RampEnumeration} a value of CAAT.ColorUtils.RampEnumeration enumeration. 167 * 168 * @return { [{number},{number},{number},{number}] } an array of integers each of which represents a color of 169 * the calculated color ramp. 170 * 171 * @static 172 */ 173 makeRGBColorRamp : function( fromColorsArray, rampSize, returnType ) { 174 175 var ramp= []; 176 var nc= fromColorsArray.length-1; 177 var chunk= rampSize/nc; 178 179 for( var i=0; i<nc; i++ ) { 180 var c= fromColorsArray[i]; 181 var a0= (c>>24)&0xff; 182 var r0= (c&0xff0000)>>16; 183 var g0= (c&0xff00)>>8; 184 var b0= c&0xff; 185 186 var c1= fromColorsArray[i+1]; 187 var a1= (c1>>24)&0xff; 188 var r1= (c1&0xff0000)>>16; 189 var g1= (c1&0xff00)>>8; 190 var b1= c1&0xff; 191 192 var da= (a1-a0)/chunk; 193 var dr= (r1-r0)/chunk; 194 var dg= (g1-g0)/chunk; 195 var db= (b1-b0)/chunk; 196 197 for( var j=0; j<chunk; j++ ) { 198 var na= (a0+da*j)>>0; 199 var nr= (r0+dr*j)>>0; 200 var ng= (g0+dg*j)>>0; 201 var nb= (b0+db*j)>>0; 202 203 switch( returnType ) { 204 case this.RampEnumeration.RAMP_RGBA: 205 ramp.push( 'argb('+na+','+nr+','+ng+','+nb+')' ); 206 break; 207 case this.RampEnumeration.RAMP_RGB: 208 ramp.push( 'rgb('+nr+','+ng+','+nb+')' ); 209 break; 210 case this.RampEnumeration.RAMP_CHANNEL_RGB: 211 ramp.push( 0xff000000 | nr<<16 | ng<<8 | nb ); 212 break; 213 case this.RampEnumeration.RAMP_CHANNEL_RGBA: 214 ramp.push( na<<24 | nr<<16 | ng<<8 | nb ); 215 break; 216 case this.RampEnumeration.RAMP_CHANNEL_RGBA_ARRAY: 217 ramp.push([ nr, ng, nb, na ]); 218 break; 219 case this.RampEnumeration.RAMP_CHANNEL_RGB_ARRAY: 220 ramp.push([ nr, ng, nb ]); 221 break; 222 } 223 } 224 } 225 226 return ramp; 227 228 } 229 }; 230})(); 231 232(function() { 233 /** 234 * RGB color implementation 235 * @param r {number} an integer in the range 0..255 236 * @param g {number} an integer in the range 0..255 237 * @param b {number} an integer in the range 0..255 238 * 239 * @constructor 240 */ 241 CAAT.Color.RGB = function(r, g, b) { 242 this.r = r || 255; 243 this.g = g || 255; 244 this.b = b || 255; 245 return this; 246 }; 247 CAAT.Color.RGB.prototype= { 248 r: 255, 249 g: 255, 250 b: 255, 251 252 /** 253 * Get color hexadecimal representation. 254 * @return {string} a string with color hexadecimal representation. 255 */ 256 toHex: function() { 257 // See: http://jsperf.com/rgb-decimal-to-hex/5 258 return ('000000' + ((this.r << 16) + (this.g << 8) + this.b).toString(16)).slice(-6); 259 } 260 }; 261})();