1 //------------------------------------------------------------------------------
  2 // File: jamColors.jsxinc
  3 // Version: 4.5
  4 // Release Date: 2016-09-29
  5 // Copyright: © 2011-2016 Michel MARIANI <http://www.tonton-pixel.com/blog/>
  6 // Licence: GPL <http://www.gnu.org/licenses/gpl.html>
  7 //------------------------------------------------------------------------------
  8 // This program is free software: you can redistribute it and/or modify
  9 // it under the terms of the GNU General Public License as published by
 10 // the Free Software Foundation, either version 3 of the License, or
 11 // (at your option) any later version.
 12 // 
 13 // This program is distributed in the hope that it will be useful,
 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 // GNU General Public License for more details.
 17 // 
 18 // You should have received a copy of the GNU General Public License
 19 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 20 //------------------------------------------------------------------------------
 21 // Version History:
 22 //  4.5:
 23 //  - Incremented version number to keep in sync with other modules.
 24 //  4.4.5:
 25 //  - Added handling of YCbCr, Lab and XYZ color models.
 26 //  - Removed constraining of component's bounds in HCL color conversion
 27 //    functions.
 28 //  - Added named color Rebecca Purple introduced in CSS 4.
 29 //  4.4:
 30 //  - Normalized error messages.
 31 //  - Added strict mode parameter to jamColors.nameToColor ().
 32 //  - Removed jamColors.w3cNameToRgb () and jamColors.x11NameToRgb (), replaced
 33 //    with jamColors.colorToRgb ().
 34 //  4.3.2:
 35 //  - Removed rounding of components in color conversion functions.
 36 //  4.3.1:
 37 //  - Added constraining of component's bounds in color conversion functions.
 38 //  - Renamed HCL lightness to luminance.
 39 //  4.3:
 40 //  - Initial release.
 41 //------------------------------------------------------------------------------
 42 
 43 /**
 44  * @fileOverview
 45  * @name jamColors.jsxinc
 46  * @author Michel MARIANI
 47  */
 48 
 49 //------------------------------------------------------------------------------
 50 
 51 if (typeof jamColors !== 'object')
 52 {
 53     /**
 54      * Global object (used to simulate a namespace in JavaScript) containing
 55      * a set of color-related functions for scripts written with the
 56      * <a href="http://www.tonton-pixel.com/blog/json-photoshop-scripting/json-action-manager/">JSON Action Manager</a> engine.
 57      * @author Michel MARIANI
 58      * @version 4.5
 59      * @namespace
 60      */
 61     var jamColors = { };
 62     //
 63     (function ()
 64     {
 65         var namedColorsSets =
 66         {
 67             "css": "w3c",
 68             "svg": "w3c",
 69             "w3c":
 70             {
 71                 "colorClass": "RGBColor",
 72                 "colorNames":
 73                 {
 74                     "aliceblue": [ 240, 248, 255 ],
 75                     "antiquewhite": [ 250, 235, 215 ],
 76                     "aqua": [ 0, 255, 255 ],
 77                     "aquamarine": [ 127, 255, 212 ],
 78                     "azure": [ 240, 255, 255 ],
 79                     "beige": [ 245, 245, 220 ],
 80                     "bisque": [ 255, 228, 196 ],
 81                     "black": [ 0, 0, 0 ],
 82                     "blanchedalmond": [ 255, 235, 205 ],
 83                     "blue": [ 0, 0, 255 ],
 84                     "blueviolet": [ 138, 43, 226 ],
 85                     "brown": [ 165, 42, 42 ],
 86                     "burlywood": [ 222, 184, 135 ],
 87                     "cadetblue": [ 95, 158, 160 ],
 88                     "chartreuse": [ 127, 255, 0 ],
 89                     "chocolate": [ 210, 105, 30 ],
 90                     "coral": [ 255, 127, 80 ],
 91                     "cornflowerblue": [ 100, 149, 237 ],
 92                     "cornsilk": [ 255, 248, 220 ],
 93                     "crimson": [ 220, 20, 60 ],
 94                     "cyan": [ 0, 255, 255 ],
 95                     "darkblue": [ 0, 0, 139 ],
 96                     "darkcyan": [ 0, 139, 139 ],
 97                     "darkgoldenrod": [ 184, 134, 11 ],
 98                     "darkgray": [ 169, 169, 169 ],
 99                     "darkgreen": [ 0, 100, 0 ],
100                     "darkgrey": "darkgray",
101                     "darkkhaki": [ 189, 183, 107 ],
102                     "darkmagenta": [ 139, 0, 139 ],
103                     "darkolivegreen": [ 85, 107, 47 ],
104                     "darkorange": [ 255, 140, 0 ],
105                     "darkorchid": [ 153, 50, 204 ],
106                     "darkred": [ 139, 0, 0 ],
107                     "darksalmon": [ 233, 150, 122 ],
108                     "darkseagreen": [ 143, 188, 143 ],
109                     "darkslateblue": [ 72, 61, 139 ],
110                     "darkslategray": [ 47, 79, 79 ],
111                     "darkslategrey": "darkslategray",
112                     "darkturquoise": [ 0, 206, 209 ],
113                     "darkviolet": [ 148, 0, 211 ],
114                     "deeppink": [ 255, 20, 147 ],
115                     "deepskyblue": [ 0, 191, 255 ],
116                     "dimgray": [ 105, 105, 105 ],
117                     "dimgrey": "dimgray",
118                     "dodgerblue": [ 30, 144, 255 ],
119                     "firebrick": [ 178, 34, 34 ],
120                     "floralwhite": [ 255, 250, 240 ],
121                     "forestgreen": [ 34, 139, 34 ],
122                     "fuchsia": [ 255, 0, 255 ],
123                     "gainsboro": [ 220, 220, 220 ],
124                     "ghostwhite": [ 248, 248, 255 ],
125                     "gold": [ 255, 215, 0 ],
126                     "goldenrod": [ 218, 165, 32 ],
127                     "gray": [ 128, 128, 128 ],
128                     "green": [ 0, 128, 0 ],
129                     "greenyellow": [ 173, 255, 47 ],
130                     "grey": "gray",
131                     "honeydew": [ 240, 255, 240 ],
132                     "hotpink": [ 255, 105, 180 ],
133                     "indianred": [ 205, 92, 92 ],
134                     "indigo": [ 75, 0, 130 ],
135                     "ivory": [ 255, 255, 240 ],
136                     "khaki": [ 240, 230, 140 ],
137                     "lavender": [ 230, 230, 250 ],
138                     "lavenderblush": [ 255, 240, 245 ],
139                     "lawngreen": [ 124, 252, 0 ],
140                     "lemonchiffon": [ 255, 250, 205 ],
141                     "lightblue": [ 173, 216, 230 ],
142                     "lightcoral": [ 240, 128, 128 ],
143                     "lightcyan": [ 224, 255, 255 ],
144                     "lightgoldenrodyellow": [ 250, 250, 210 ],
145                     "lightgray": [ 211, 211, 211 ],
146                     "lightgreen": [ 144, 238, 144 ],
147                     "lightgrey": "lightgray",
148                     "lightpink": [ 255, 182, 193 ],
149                     "lightsalmon": [ 255, 160, 122 ],
150                     "lightseagreen": [ 32, 178, 170 ],
151                     "lightskyblue": [ 135, 206, 250 ],
152                     "lightslategray": [ 119, 136, 153 ],
153                     "lightslategrey": "lightslategray",
154                     "lightsteelblue": [ 176, 196, 222 ],
155                     "lightyellow": [ 255, 255, 224 ],
156                     "lime": [ 0, 255, 0 ],
157                     "limegreen": [ 50, 205, 50 ],
158                     "linen": [ 250, 240, 230 ],
159                     "magenta": [ 255, 0, 255 ],
160                     "maroon": [ 128, 0, 0 ],
161                     "mediumaquamarine": [ 102, 205, 170 ],
162                     "mediumblue": [ 0, 0, 205 ],
163                     "mediumorchid": [ 186, 85, 211 ],
164                     "mediumpurple": [ 147, 112, 219 ],
165                     "mediumseagreen": [ 60, 179, 113 ],
166                     "mediumslateblue": [ 123, 104, 238 ],
167                     "mediumspringgreen": [ 0, 250, 154 ],
168                     "mediumturquoise": [ 72, 209, 204 ],
169                     "mediumvioletred": [ 199, 21, 133 ],
170                     "midnightblue": [ 25, 25, 112 ],
171                     "mintcream": [ 245, 255, 250 ],
172                     "mistyrose": [ 255, 228, 225 ],
173                     "moccasin": [ 255, 228, 181 ],
174                     "navajowhite": [ 255, 222, 173 ],
175                     "navy": [ 0, 0, 128 ],
176                     "oldlace": [ 253, 245, 230 ],
177                     "olive": [ 128, 128, 0 ],
178                     "olivedrab": [ 107, 142, 35 ],
179                     "orange": [ 255, 165, 0 ],
180                     "orangered": [ 255, 69, 0 ],
181                     "orchid": [ 218, 112, 214 ],
182                     "palegoldenrod": [ 238, 232, 170 ],
183                     "palegreen": [ 152, 251, 152 ],
184                     "paleturquoise": [ 175, 238, 238 ],
185                     "palevioletred": [ 219, 112, 147 ],
186                     "papayawhip": [ 255, 239, 213 ],
187                     "peachpuff": [ 255, 218, 185 ],
188                     "peru": [ 205, 133, 63 ],
189                     "pink": [ 255, 192, 203 ],
190                     "plum": [ 221, 160, 221 ],
191                     "powderblue": [ 176, 224, 230 ],
192                     "purple": [ 128, 0, 128 ],
193                     "rebeccapurple": [ 102, 51, 153 ],
194                     "red": [ 255, 0, 0 ],
195                     "rosybrown": [ 188, 143, 143 ],
196                     "royalblue": [ 65, 105, 225 ],
197                     "saddlebrown": [ 139, 69, 19 ],
198                     "salmon": [ 250, 128, 114 ],
199                     "sandybrown": [ 244, 164, 96 ],
200                     "seagreen": [ 46, 139, 87 ],
201                     "seashell": [ 255, 245, 238 ],
202                     "sienna": [ 160, 82, 45 ],
203                     "silver": [ 192, 192, 192 ],
204                     "skyblue": [ 135, 206, 235 ],
205                     "slateblue": [ 106, 90, 205 ],
206                     "slategray": [ 112, 128, 144 ],
207                     "slategrey": "slategray",
208                     "snow": [ 255, 250, 250 ],
209                     "springgreen": [ 0, 255, 127 ],
210                     "steelblue": [ 70, 130, 180 ],
211                     "tan": [ 210, 180, 140 ],
212                     "teal": [ 0, 128, 128 ],
213                     "thistle": [ 216, 191, 216 ],
214                     "tomato": [ 255, 99, 71 ],
215                     "turquoise": [ 64, 224, 208 ],
216                     "violet": [ 238, 130, 238 ],
217                     "wheat": [ 245, 222, 179 ],
218                     "white": [ 255, 255, 255 ],
219                     "whitesmoke": [ 245, 245, 245 ],
220                     "yellow": [ 255, 255, 0 ],
221                     "yellowgreen": [ 154, 205, 50 ]
222                 },
223                 "fallbackColor": "black",
224                 "info":
225                 [
226                     "http://www.w3.org/TR/css3-color/#svg-color",
227                     "https://www.w3.org/TR/css-color-4/#changes-from-3",
228                     "http://www.w3.org/TR/SVG/types.html#ColorKeywords",
229                     "http://en.wikipedia.org/wiki/X11_color_names"
230                 ]
231             },
232             "x11":
233             {
234                 "colorClass": "RGBColor",
235                 "colorNames":
236                 {
237                     "aliceblue": [ 240, 248, 255 ],
238                     "antiquewhite": [ 250, 235, 215 ],
239                     "antiquewhite1": [ 255, 239, 219 ],
240                     "antiquewhite2": [ 238, 223, 204 ],
241                     "antiquewhite3": [ 205, 192, 176 ],
242                     "antiquewhite4": [ 139, 131, 120 ],
243                     "aquamarine": [ 127, 255, 212 ],
244                     "aquamarine1": [ 127, 255, 212 ],
245                     "aquamarine2": [ 118, 238, 198 ],
246                     "aquamarine3": [ 102, 205, 170 ],
247                     "aquamarine4": [ 69, 139, 116 ],
248                     "azure": [ 240, 255, 255 ],
249                     "azure1": [ 240, 255, 255 ],
250                     "azure2": [ 224, 238, 238 ],
251                     "azure3": [ 193, 205, 205 ],
252                     "azure4": [ 131, 139, 139 ],
253                     "beige": [ 245, 245, 220 ],
254                     "bisque": [ 255, 228, 196 ],
255                     "bisque1": [ 255, 228, 196 ],
256                     "bisque2": [ 238, 213, 183 ],
257                     "bisque3": [ 205, 183, 158 ],
258                     "bisque4": [ 139, 125, 107 ],
259                     "black": [ 0, 0, 0 ],
260                     "blanchedalmond": [ 255, 235, 205 ],
261                     "blue": [ 0, 0, 255 ],
262                     "blue1": [ 0, 0, 255 ],
263                     "blue2": [ 0, 0, 238 ],
264                     "blue3": [ 0, 0, 205 ],
265                     "blue4": [ 0, 0, 139 ],
266                     "blueviolet": [ 138, 43, 226 ],
267                     "brown": [ 165, 42, 42 ],
268                     "brown1": [ 255, 64, 64 ],
269                     "brown2": [ 238, 59, 59 ],
270                     "brown3": [ 205, 51, 51 ],
271                     "brown4": [ 139, 35, 35 ],
272                     "burlywood": [ 222, 184, 135 ],
273                     "burlywood1": [ 255, 211, 155 ],
274                     "burlywood2": [ 238, 197, 145 ],
275                     "burlywood3": [ 205, 170, 125 ],
276                     "burlywood4": [ 139, 115, 85 ],
277                     "cadetblue": [ 95, 158, 160 ],
278                     "cadetblue1": [ 152, 245, 255 ],
279                     "cadetblue2": [ 142, 229, 238 ],
280                     "cadetblue3": [ 122, 197, 205 ],
281                     "cadetblue4": [ 83, 134, 139 ],
282                     "chartreuse": [ 127, 255, 0 ],
283                     "chartreuse1": [ 127, 255, 0 ],
284                     "chartreuse2": [ 118, 238, 0 ],
285                     "chartreuse3": [ 102, 205, 0 ],
286                     "chartreuse4": [ 69, 139, 0 ],
287                     "chocolate": [ 210, 105, 30 ],
288                     "chocolate1": [ 255, 127, 36 ],
289                     "chocolate2": [ 238, 118, 33 ],
290                     "chocolate3": [ 205, 102, 29 ],
291                     "chocolate4": [ 139, 69, 19 ],
292                     "coral": [ 255, 127, 80 ],
293                     "coral1": [ 255, 114, 86 ],
294                     "coral2": [ 238, 106, 80 ],
295                     "coral3": [ 205, 91, 69 ],
296                     "coral4": [ 139, 62, 47 ],
297                     "cornflowerblue": [ 100, 149, 237 ],
298                     "cornsilk": [ 255, 248, 220 ],
299                     "cornsilk1": [ 255, 248, 220 ],
300                     "cornsilk2": [ 238, 232, 205 ],
301                     "cornsilk3": [ 205, 200, 177 ],
302                     "cornsilk4": [ 139, 136, 120 ],
303                     "cyan": [ 0, 255, 255 ],
304                     "cyan1": [ 0, 255, 255 ],
305                     "cyan2": [ 0, 238, 238 ],
306                     "cyan3": [ 0, 205, 205 ],
307                     "cyan4": [ 0, 139, 139 ],
308                     "darkblue": [ 0, 0, 139 ],
309                     "darkcyan": [ 0, 139, 139 ],
310                     "darkgoldenrod": [ 184, 134, 11 ],
311                     "darkgoldenrod1": [ 255, 185, 15 ],
312                     "darkgoldenrod2": [ 238, 173, 14 ],
313                     "darkgoldenrod3": [ 205, 149, 12 ],
314                     "darkgoldenrod4": [ 139, 101, 8 ],
315                     "darkgray": [ 169, 169, 169 ],
316                     "darkgreen": [ 0, 100, 0 ],
317                     "darkgrey": "darkgray",
318                     "darkkhaki": [ 189, 183, 107 ],
319                     "darkmagenta": [ 139, 0, 139 ],
320                     "darkolivegreen": [ 85, 107, 47 ],
321                     "darkolivegreen1": [ 202, 255, 112 ],
322                     "darkolivegreen2": [ 188, 238, 104 ],
323                     "darkolivegreen3": [ 162, 205, 90 ],
324                     "darkolivegreen4": [ 110, 139, 61 ],
325                     "darkorange": [ 255, 140, 0 ],
326                     "darkorange1": [ 255, 127, 0 ],
327                     "darkorange2": [ 238, 118, 0 ],
328                     "darkorange3": [ 205, 102, 0 ],
329                     "darkorange4": [ 139, 69, 0 ],
330                     "darkorchid": [ 153, 50, 204 ],
331                     "darkorchid1": [ 191, 62, 255 ],
332                     "darkorchid2": [ 178, 58, 238 ],
333                     "darkorchid3": [ 154, 50, 205 ],
334                     "darkorchid4": [ 104, 34, 139 ],
335                     "darkred": [ 139, 0, 0 ],
336                     "darksalmon": [ 233, 150, 122 ],
337                     "darkseagreen": [ 143, 188, 143 ],
338                     "darkseagreen1": [ 193, 255, 193 ],
339                     "darkseagreen2": [ 180, 238, 180 ],
340                     "darkseagreen3": [ 155, 205, 155 ],
341                     "darkseagreen4": [ 105, 139, 105 ],
342                     "darkslateblue": [ 72, 61, 139 ],
343                     "darkslategray": [ 47, 79, 79 ],
344                     "darkslategray1": [ 151, 255, 255 ],
345                     "darkslategray2": [ 141, 238, 238 ],
346                     "darkslategray3": [ 121, 205, 205 ],
347                     "darkslategray4": [ 82, 139, 139 ],
348                     "darkslategrey": "darkslategray",
349                     "darkslategrey1": "darkslategray1",
350                     "darkslategrey2": "darkslategray2",
351                     "darkslategrey3": "darkslategray3",
352                     "darkslategrey4": "darkslategray4",
353                     "darkturquoise": [ 0, 206, 209 ],
354                     "darkviolet": [ 148, 0, 211 ],
355                     "deeppink": [ 255, 20, 147 ],
356                     "deeppink1": [ 255, 20, 147 ],
357                     "deeppink2": [ 238, 18, 137 ],
358                     "deeppink3": [ 205, 16, 118 ],
359                     "deeppink4": [ 139, 10, 80 ],
360                     "deepskyblue": [ 0, 191, 255 ],
361                     "deepskyblue1": [ 0, 191, 255 ],
362                     "deepskyblue2": [ 0, 178, 238 ],
363                     "deepskyblue3": [ 0, 154, 205 ],
364                     "deepskyblue4": [ 0, 104, 139 ],
365                     "dimgray": [ 105, 105, 105 ],
366                     "dimgrey": "dimgray",
367                     "dodgerblue": [ 30, 144, 255 ],
368                     "dodgerblue1": [ 30, 144, 255 ],
369                     "dodgerblue2": [ 28, 134, 238 ],
370                     "dodgerblue3": [ 24, 116, 205 ],
371                     "dodgerblue4": [ 16, 78, 139 ],
372                     "firebrick": [ 178, 34, 34 ],
373                     "firebrick1": [ 255, 48, 48 ],
374                     "firebrick2": [ 238, 44, 44 ],
375                     "firebrick3": [ 205, 38, 38 ],
376                     "firebrick4": [ 139, 26, 26 ],
377                     "floralwhite": [ 255, 250, 240 ],
378                     "forestgreen": [ 34, 139, 34 ],
379                     "gainsboro": [ 220, 220, 220 ],
380                     "ghostwhite": [ 248, 248, 255 ],
381                     "gold": [ 255, 215, 0 ],
382                     "gold1": [ 255, 215, 0 ],
383                     "gold2": [ 238, 201, 0 ],
384                     "gold3": [ 205, 173, 0 ],
385                     "gold4": [ 139, 117, 0 ],
386                     "goldenrod": [ 218, 165, 32 ],
387                     "goldenrod1": [ 255, 193, 37 ],
388                     "goldenrod2": [ 238, 180, 34 ],
389                     "goldenrod3": [ 205, 155, 29 ],
390                     "goldenrod4": [ 139, 105, 20 ],
391                     "gray": [ 190, 190, 190 ],
392                     "gray0": [ 0, 0, 0 ],
393                     "gray1": [ 3, 3, 3 ],
394                     "gray2": [ 5, 5, 5 ],
395                     "gray3": [ 8, 8, 8 ],
396                     "gray4": [ 10, 10, 10 ],
397                     "gray5": [ 13, 13, 13 ],
398                     "gray6": [ 15, 15, 15 ],
399                     "gray7": [ 18, 18, 18 ],
400                     "gray8": [ 20, 20, 20 ],
401                     "gray9": [ 23, 23, 23 ],
402                     "gray10": [ 26, 26, 26 ],
403                     "gray11": [ 28, 28, 28 ],
404                     "gray12": [ 31, 31, 31 ],
405                     "gray13": [ 33, 33, 33 ],
406                     "gray14": [ 36, 36, 36 ],
407                     "gray15": [ 38, 38, 38 ],
408                     "gray16": [ 41, 41, 41 ],
409                     "gray17": [ 43, 43, 43 ],
410                     "gray18": [ 46, 46, 46 ],
411                     "gray19": [ 48, 48, 48 ],
412                     "gray20": [ 51, 51, 51 ],
413                     "gray21": [ 54, 54, 54 ],
414                     "gray22": [ 56, 56, 56 ],
415                     "gray23": [ 59, 59, 59 ],
416                     "gray24": [ 61, 61, 61 ],
417                     "gray25": [ 64, 64, 64 ],
418                     "gray26": [ 66, 66, 66 ],
419                     "gray27": [ 69, 69, 69 ],
420                     "gray28": [ 71, 71, 71 ],
421                     "gray29": [ 74, 74, 74 ],
422                     "gray30": [ 77, 77, 77 ],
423                     "gray31": [ 79, 79, 79 ],
424                     "gray32": [ 82, 82, 82 ],
425                     "gray33": [ 84, 84, 84 ],
426                     "gray34": [ 87, 87, 87 ],
427                     "gray35": [ 89, 89, 89 ],
428                     "gray36": [ 92, 92, 92 ],
429                     "gray37": [ 94, 94, 94 ],
430                     "gray38": [ 97, 97, 97 ],
431                     "gray39": [ 99, 99, 99 ],
432                     "gray40": [ 102, 102, 102 ],
433                     "gray41": [ 105, 105, 105 ],
434                     "gray42": [ 107, 107, 107 ],
435                     "gray43": [ 110, 110, 110 ],
436                     "gray44": [ 112, 112, 112 ],
437                     "gray45": [ 115, 115, 115 ],
438                     "gray46": [ 117, 117, 117 ],
439                     "gray47": [ 120, 120, 120 ],
440                     "gray48": [ 122, 122, 122 ],
441                     "gray49": [ 125, 125, 125 ],
442                     "gray50": [ 127, 127, 127 ],
443                     "gray51": [ 130, 130, 130 ],
444                     "gray52": [ 133, 133, 133 ],
445                     "gray53": [ 135, 135, 135 ],
446                     "gray54": [ 138, 138, 138 ],
447                     "gray55": [ 140, 140, 140 ],
448                     "gray56": [ 143, 143, 143 ],
449                     "gray57": [ 145, 145, 145 ],
450                     "gray58": [ 148, 148, 148 ],
451                     "gray59": [ 150, 150, 150 ],
452                     "gray60": [ 153, 153, 153 ],
453                     "gray61": [ 156, 156, 156 ],
454                     "gray62": [ 158, 158, 158 ],
455                     "gray63": [ 161, 161, 161 ],
456                     "gray64": [ 163, 163, 163 ],
457                     "gray65": [ 166, 166, 166 ],
458                     "gray66": [ 168, 168, 168 ],
459                     "gray67": [ 171, 171, 171 ],
460                     "gray68": [ 173, 173, 173 ],
461                     "gray69": [ 176, 176, 176 ],
462                     "gray70": [ 179, 179, 179 ],
463                     "gray71": [ 181, 181, 181 ],
464                     "gray72": [ 184, 184, 184 ],
465                     "gray73": [ 186, 186, 186 ],
466                     "gray74": [ 189, 189, 189 ],
467                     "gray75": [ 191, 191, 191 ],
468                     "gray76": [ 194, 194, 194 ],
469                     "gray77": [ 196, 196, 196 ],
470                     "gray78": [ 199, 199, 199 ],
471                     "gray79": [ 201, 201, 201 ],
472                     "gray80": [ 204, 204, 204 ],
473                     "gray81": [ 207, 207, 207 ],
474                     "gray82": [ 209, 209, 209 ],
475                     "gray83": [ 212, 212, 212 ],
476                     "gray84": [ 214, 214, 214 ],
477                     "gray85": [ 217, 217, 217 ],
478                     "gray86": [ 219, 219, 219 ],
479                     "gray87": [ 222, 222, 222 ],
480                     "gray88": [ 224, 224, 224 ],
481                     "gray89": [ 227, 227, 227 ],
482                     "gray90": [ 229, 229, 229 ],
483                     "gray91": [ 232, 232, 232 ],
484                     "gray92": [ 235, 235, 235 ],
485                     "gray93": [ 237, 237, 237 ],
486                     "gray94": [ 240, 240, 240 ],
487                     "gray95": [ 242, 242, 242 ],
488                     "gray96": [ 245, 245, 245 ],
489                     "gray97": [ 247, 247, 247 ],
490                     "gray98": [ 250, 250, 250 ],
491                     "gray99": [ 252, 252, 252 ],
492                     "gray100": [ 255, 255, 255 ],
493                     "green": [ 0, 255, 0 ],
494                     "green1": [ 0, 255, 0 ],
495                     "green2": [ 0, 238, 0 ],
496                     "green3": [ 0, 205, 0 ],
497                     "green4": [ 0, 139, 0 ],
498                     "greenyellow": [ 173, 255, 47 ],
499                     "grey": "gray",
500                     "grey0": "gray0",
501                     "grey1": "gray1",
502                     "grey2": "gray2",
503                     "grey3": "gray3",
504                     "grey4": "gray4",
505                     "grey5": "gray5",
506                     "grey6": "gray6",
507                     "grey7": "gray7",
508                     "grey8": "gray8",
509                     "grey9": "gray9",
510                     "grey10": "gray10",
511                     "grey11": "gray11",
512                     "grey12": "gray12",
513                     "grey13": "gray13",
514                     "grey14": "gray14",
515                     "grey15": "gray15",
516                     "grey16": "gray16",
517                     "grey17": "gray17",
518                     "grey18": "gray18",
519                     "grey19": "gray19",
520                     "grey20": "gray20",
521                     "grey21": "gray21",
522                     "grey22": "gray22",
523                     "grey23": "gray23",
524                     "grey24": "gray24",
525                     "grey25": "gray25",
526                     "grey26": "gray26",
527                     "grey27": "gray27",
528                     "grey28": "gray28",
529                     "grey29": "gray29",
530                     "grey30": "gray30",
531                     "grey31": "gray31",
532                     "grey32": "gray32",
533                     "grey33": "gray33",
534                     "grey34": "gray34",
535                     "grey35": "gray35",
536                     "grey36": "gray36",
537                     "grey37": "gray37",
538                     "grey38": "gray38",
539                     "grey39": "gray39",
540                     "grey40": "gray40",
541                     "grey41": "gray41",
542                     "grey42": "gray42",
543                     "grey43": "gray43",
544                     "grey44": "gray44",
545                     "grey45": "gray45",
546                     "grey46": "gray46",
547                     "grey47": "gray47",
548                     "grey48": "gray48",
549                     "grey49": "gray49",
550                     "grey50": "gray50",
551                     "grey51": "gray51",
552                     "grey52": "gray52",
553                     "grey53": "gray53",
554                     "grey54": "gray54",
555                     "grey55": "gray55",
556                     "grey56": "gray56",
557                     "grey57": "gray57",
558                     "grey58": "gray58",
559                     "grey59": "gray59",
560                     "grey60": "gray60",
561                     "grey61": "gray61",
562                     "grey62": "gray62",
563                     "grey63": "gray63",
564                     "grey64": "gray64",
565                     "grey65": "gray65",
566                     "grey66": "gray66",
567                     "grey67": "gray67",
568                     "grey68": "gray68",
569                     "grey69": "gray69",
570                     "grey70": "gray70",
571                     "grey71": "gray71",
572                     "grey72": "gray72",
573                     "grey73": "gray73",
574                     "grey74": "gray74",
575                     "grey75": "gray75",
576                     "grey76": "gray76",
577                     "grey77": "gray77",
578                     "grey78": "gray78",
579                     "grey79": "gray79",
580                     "grey80": "gray80",
581                     "grey81": "gray81",
582                     "grey82": "gray82",
583                     "grey83": "gray83",
584                     "grey84": "gray84",
585                     "grey85": "gray85",
586                     "grey86": "gray86",
587                     "grey87": "gray87",
588                     "grey88": "gray88",
589                     "grey89": "gray89",
590                     "grey90": "gray90",
591                     "grey91": "gray91",
592                     "grey92": "gray92",
593                     "grey93": "gray93",
594                     "grey94": "gray94",
595                     "grey95": "gray95",
596                     "grey96": "gray96",
597                     "grey97": "gray97",
598                     "grey98": "gray98",
599                     "grey99": "gray99",
600                     "grey100": "gray100",
601                     "honeydew": [ 240, 255, 240 ],
602                     "honeydew1": [ 240, 255, 240 ],
603                     "honeydew2": [ 224, 238, 224 ],
604                     "honeydew3": [ 193, 205, 193 ],
605                     "honeydew4": [ 131, 139, 131 ],
606                     "hotpink": [ 255, 105, 180 ],
607                     "hotpink1": [ 255, 110, 180 ],
608                     "hotpink2": [ 238, 106, 167 ],
609                     "hotpink3": [ 205, 96, 144 ],
610                     "hotpink4": [ 139, 58, 98 ],
611                     "indianred": [ 205, 92, 92 ],
612                     "indianred1": [ 255, 106, 106 ],
613                     "indianred2": [ 238, 99, 99 ],
614                     "indianred3": [ 205, 85, 85 ],
615                     "indianred4": [ 139, 58, 58 ],
616                     "ivory": [ 255, 255, 240 ],
617                     "ivory1": [ 255, 255, 240 ],
618                     "ivory2": [ 238, 238, 224 ],
619                     "ivory3": [ 205, 205, 193 ],
620                     "ivory4": [ 139, 139, 131 ],
621                     "khaki": [ 240, 230, 140 ],
622                     "khaki1": [ 255, 246, 143 ],
623                     "khaki2": [ 238, 230, 133 ],
624                     "khaki3": [ 205, 198, 115 ],
625                     "khaki4": [ 139, 134, 78 ],
626                     "lavender": [ 230, 230, 250 ],
627                     "lavenderblush": [ 255, 240, 245 ],
628                     "lavenderblush1": [ 255, 240, 245 ],
629                     "lavenderblush2": [ 238, 224, 229 ],
630                     "lavenderblush3": [ 205, 193, 197 ],
631                     "lavenderblush4": [ 139, 131, 134 ],
632                     "lawngreen": [ 124, 252, 0 ],
633                     "lemonchiffon": [ 255, 250, 205 ],
634                     "lemonchiffon1": [ 255, 250, 205 ],
635                     "lemonchiffon2": [ 238, 233, 191 ],
636                     "lemonchiffon3": [ 205, 201, 165 ],
637                     "lemonchiffon4": [ 139, 137, 112 ],
638                     "lightblue": [ 173, 216, 230 ],
639                     "lightblue1": [ 191, 239, 255 ],
640                     "lightblue2": [ 178, 223, 238 ],
641                     "lightblue3": [ 154, 192, 205 ],
642                     "lightblue4": [ 104, 131, 139 ],
643                     "lightcoral": [ 240, 128, 128 ],
644                     "lightcyan": [ 224, 255, 255 ],
645                     "lightcyan1": [ 224, 255, 255 ],
646                     "lightcyan2": [ 209, 238, 238 ],
647                     "lightcyan3": [ 180, 205, 205 ],
648                     "lightcyan4": [ 122, 139, 139 ],
649                     "lightgoldenrod": [ 238, 221, 130 ],
650                     "lightgoldenrod1": [ 255, 236, 139 ],
651                     "lightgoldenrod2": [ 238, 220, 130 ],
652                     "lightgoldenrod3": [ 205, 190, 112 ],
653                     "lightgoldenrod4": [ 139, 129, 76 ],
654                     "lightgoldenrodyellow": [ 250, 250, 210 ],
655                     "lightgray": [ 211, 211, 211 ],
656                     "lightgreen": [ 144, 238, 144 ],
657                     "lightgrey": "lightgray",
658                     "lightpink": [ 255, 182, 193 ],
659                     "lightpink1": [ 255, 174, 185 ],
660                     "lightpink2": [ 238, 162, 173 ],
661                     "lightpink3": [ 205, 140, 149 ],
662                     "lightpink4": [ 139, 95, 101 ],
663                     "lightsalmon": [ 255, 160, 122 ],
664                     "lightsalmon1": [ 255, 160, 122 ],
665                     "lightsalmon2": [ 238, 149, 114 ],
666                     "lightsalmon3": [ 205, 129, 98 ],
667                     "lightsalmon4": [ 139, 87, 66 ],
668                     "lightseagreen": [ 32, 178, 170 ],
669                     "lightskyblue": [ 135, 206, 250 ],
670                     "lightskyblue1": [ 176, 226, 255 ],
671                     "lightskyblue2": [ 164, 211, 238 ],
672                     "lightskyblue3": [ 141, 182, 205 ],
673                     "lightskyblue4": [ 96, 123, 139 ],
674                     "lightslateblue": [ 132, 112, 255 ],
675                     "lightslategray": [ 119, 136, 153 ],
676                     "lightslategrey": "lightslategray",
677                     "lightsteelblue": [ 176, 196, 222 ],
678                     "lightsteelblue1": [ 202, 225, 255 ],
679                     "lightsteelblue2": [ 188, 210, 238 ],
680                     "lightsteelblue3": [ 162, 181, 205 ],
681                     "lightsteelblue4": [ 110, 123, 139 ],
682                     "lightyellow": [ 255, 255, 224 ],
683                     "lightyellow1": [ 255, 255, 224 ],
684                     "lightyellow2": [ 238, 238, 209 ],
685                     "lightyellow3": [ 205, 205, 180 ],
686                     "lightyellow4": [ 139, 139, 122 ],
687                     "limegreen": [ 50, 205, 50 ],
688                     "linen": [ 250, 240, 230 ],
689                     "magenta": [ 255, 0, 255 ],
690                     "magenta1": [ 255, 0, 255 ],
691                     "magenta2": [ 238, 0, 238 ],
692                     "magenta3": [ 205, 0, 205 ],
693                     "magenta4": [ 139, 0, 139 ],
694                     "maroon": [ 176, 48, 96 ],
695                     "maroon1": [ 255, 52, 179 ],
696                     "maroon2": [ 238, 48, 167 ],
697                     "maroon3": [ 205, 41, 144 ],
698                     "maroon4": [ 139, 28, 98 ],
699                     "mediumaquamarine": [ 102, 205, 170 ],
700                     "mediumblue": [ 0, 0, 205 ],
701                     "mediumorchid": [ 186, 85, 211 ],
702                     "mediumorchid1": [ 224, 102, 255 ],
703                     "mediumorchid2": [ 209, 95, 238 ],
704                     "mediumorchid3": [ 180, 82, 205 ],
705                     "mediumorchid4": [ 122, 55, 139 ],
706                     "mediumpurple": [ 147, 112, 219 ],
707                     "mediumpurple1": [ 171, 130, 255 ],
708                     "mediumpurple2": [ 159, 121, 238 ],
709                     "mediumpurple3": [ 137, 104, 205 ],
710                     "mediumpurple4": [ 93, 71, 139 ],
711                     "mediumseagreen": [ 60, 179, 113 ],
712                     "mediumslateblue": [ 123, 104, 238 ],
713                     "mediumspringgreen": [ 0, 250, 154 ],
714                     "mediumturquoise": [ 72, 209, 204 ],
715                     "mediumvioletred": [ 199, 21, 133 ],
716                     "midnightblue": [ 25, 25, 112 ],
717                     "mintcream": [ 245, 255, 250 ],
718                     "mistyrose": [ 255, 228, 225 ],
719                     "mistyrose1": [ 255, 228, 225 ],
720                     "mistyrose2": [ 238, 213, 210 ],
721                     "mistyrose3": [ 205, 183, 181 ],
722                     "mistyrose4": [ 139, 125, 123 ],
723                     "moccasin": [ 255, 228, 181 ],
724                     "navajowhite": [ 255, 222, 173 ],
725                     "navajowhite1": [ 255, 222, 173 ],
726                     "navajowhite2": [ 238, 207, 161 ],
727                     "navajowhite3": [ 205, 179, 139 ],
728                     "navajowhite4": [ 139, 121, 94 ],
729                     "navy": [ 0, 0, 128 ],
730                     "navyblue": [ 0, 0, 128 ],
731                     "oldlace": [ 253, 245, 230 ],
732                     "olivedrab": [ 107, 142, 35 ],
733                     "olivedrab1": [ 192, 255, 62 ],
734                     "olivedrab2": [ 179, 238, 58 ],
735                     "olivedrab3": [ 154, 205, 50 ],
736                     "olivedrab4": [ 105, 139, 34 ],
737                     "orange": [ 255, 165, 0 ],
738                     "orange1": [ 255, 165, 0 ],
739                     "orange2": [ 238, 154, 0 ],
740                     "orange3": [ 205, 133, 0 ],
741                     "orange4": [ 139, 90, 0 ],
742                     "orangered": [ 255, 69, 0 ],
743                     "orangered1": [ 255, 69, 0 ],
744                     "orangered2": [ 238, 64, 0 ],
745                     "orangered3": [ 205, 55, 0 ],
746                     "orangered4": [ 139, 37, 0 ],
747                     "orchid": [ 218, 112, 214 ],
748                     "orchid1": [ 255, 131, 250 ],
749                     "orchid2": [ 238, 122, 233 ],
750                     "orchid3": [ 205, 105, 201 ],
751                     "orchid4": [ 139, 71, 137 ],
752                     "palegoldenrod": [ 238, 232, 170 ],
753                     "palegreen": [ 152, 251, 152 ],
754                     "palegreen1": [ 154, 255, 154 ],
755                     "palegreen2": [ 144, 238, 144 ],
756                     "palegreen3": [ 124, 205, 124 ],
757                     "palegreen4": [ 84, 139, 84 ],
758                     "paleturquoise": [ 175, 238, 238 ],
759                     "paleturquoise1": [ 187, 255, 255 ],
760                     "paleturquoise2": [ 174, 238, 238 ],
761                     "paleturquoise3": [ 150, 205, 205 ],
762                     "paleturquoise4": [ 102, 139, 139 ],
763                     "palevioletred": [ 219, 112, 147 ],
764                     "palevioletred1": [ 255, 130, 171 ],
765                     "palevioletred2": [ 238, 121, 159 ],
766                     "palevioletred3": [ 205, 104, 137 ],
767                     "palevioletred4": [ 139, 71, 93 ],
768                     "papayawhip": [ 255, 239, 213 ],
769                     "peachpuff": [ 255, 218, 185 ],
770                     "peachpuff1": [ 255, 218, 185 ],
771                     "peachpuff2": [ 238, 203, 173 ],
772                     "peachpuff3": [ 205, 175, 149 ],
773                     "peachpuff4": [ 139, 119, 101 ],
774                     "peru": [ 205, 133, 63 ],
775                     "pink": [ 255, 192, 203 ],
776                     "pink1": [ 255, 181, 197 ],
777                     "pink2": [ 238, 169, 184 ],
778                     "pink3": [ 205, 145, 158 ],
779                     "pink4": [ 139, 99, 108 ],
780                     "plum": [ 221, 160, 221 ],
781                     "plum1": [ 255, 187, 255 ],
782                     "plum2": [ 238, 174, 238 ],
783                     "plum3": [ 205, 150, 205 ],
784                     "plum4": [ 139, 102, 139 ],
785                     "powderblue": [ 176, 224, 230 ],
786                     "purple": [ 160, 32, 240 ],
787                     "purple1": [ 155, 48, 255 ],
788                     "purple2": [ 145, 44, 238 ],
789                     "purple3": [ 125, 38, 205 ],
790                     "purple4": [ 85, 26, 139 ],
791                     "red": [ 255, 0, 0 ],
792                     "red1": [ 255, 0, 0 ],
793                     "red2": [ 238, 0, 0 ],
794                     "red3": [ 205, 0, 0 ],
795                     "red4": [ 139, 0, 0 ],
796                     "rosybrown": [ 188, 143, 143 ],
797                     "rosybrown1": [ 255, 193, 193 ],
798                     "rosybrown2": [ 238, 180, 180 ],
799                     "rosybrown3": [ 205, 155, 155 ],
800                     "rosybrown4": [ 139, 105, 105 ],
801                     "royalblue": [ 65, 105, 225 ],
802                     "royalblue1": [ 72, 118, 255 ],
803                     "royalblue2": [ 67, 110, 238 ],
804                     "royalblue3": [ 58, 95, 205 ],
805                     "royalblue4": [ 39, 64, 139 ],
806                     "saddlebrown": [ 139, 69, 19 ],
807                     "salmon": [ 250, 128, 114 ],
808                     "salmon1": [ 255, 140, 105 ],
809                     "salmon2": [ 238, 130, 98 ],
810                     "salmon3": [ 205, 112, 84 ],
811                     "salmon4": [ 139, 76, 57 ],
812                     "sandybrown": [ 244, 164, 96 ],
813                     "seagreen": [ 46, 139, 87 ],
814                     "seagreen1": [ 84, 255, 159 ],
815                     "seagreen2": [ 78, 238, 148 ],
816                     "seagreen3": [ 67, 205, 128 ],
817                     "seagreen4": [ 46, 139, 87 ],
818                     "seashell": [ 255, 245, 238 ],
819                     "seashell1": [ 255, 245, 238 ],
820                     "seashell2": [ 238, 229, 222 ],
821                     "seashell3": [ 205, 197, 191 ],
822                     "seashell4": [ 139, 134, 130 ],
823                     "sienna": [ 160, 82, 45 ],
824                     "sienna1": [ 255, 130, 71 ],
825                     "sienna2": [ 238, 121, 66 ],
826                     "sienna3": [ 205, 104, 57 ],
827                     "sienna4": [ 139, 71, 38 ],
828                     "skyblue": [ 135, 206, 235 ],
829                     "skyblue1": [ 135, 206, 255 ],
830                     "skyblue2": [ 126, 192, 238 ],
831                     "skyblue3": [ 108, 166, 205 ],
832                     "skyblue4": [ 74, 112, 139 ],
833                     "slateblue": [ 106, 90, 205 ],
834                     "slateblue1": [ 131, 111, 255 ],
835                     "slateblue2": [ 122, 103, 238 ],
836                     "slateblue3": [ 105, 89, 205 ],
837                     "slateblue4": [ 71, 60, 139 ],
838                     "slategray": [ 112, 128, 144 ],
839                     "slategray1": [ 198, 226, 255 ],
840                     "slategray2": [ 185, 211, 238 ],
841                     "slategray3": [ 159, 182, 205 ],
842                     "slategray4": [ 108, 123, 139 ],
843                     "slategrey": "slategray",
844                     "slategrey1": "slategray1",
845                     "slategrey2": "slategray2",
846                     "slategrey3": "slategray3",
847                     "slategrey4": "slategray4",
848                     "snow": [ 255, 250, 250 ],
849                     "snow1": [ 255, 250, 250 ],
850                     "snow2": [ 238, 233, 233 ],
851                     "snow3": [ 205, 201, 201 ],
852                     "snow4": [ 139, 137, 137 ],
853                     "springgreen": [ 0, 255, 127 ],
854                     "springgreen1": [ 0, 255, 127 ],
855                     "springgreen2": [ 0, 238, 118 ],
856                     "springgreen3": [ 0, 205, 102 ],
857                     "springgreen4": [ 0, 139, 69 ],
858                     "steelblue": [ 70, 130, 180 ],
859                     "steelblue1": [ 99, 184, 255 ],
860                     "steelblue2": [ 92, 172, 238 ],
861                     "steelblue3": [ 79, 148, 205 ],
862                     "steelblue4": [ 54, 100, 139 ],
863                     "tan": [ 210, 180, 140 ],
864                     "tan1": [ 255, 165, 79 ],
865                     "tan2": [ 238, 154, 73 ],
866                     "tan3": [ 205, 133, 63 ],
867                     "tan4": [ 139, 90, 43 ],
868                     "thistle": [ 216, 191, 216 ],
869                     "thistle1": [ 255, 225, 255 ],
870                     "thistle2": [ 238, 210, 238 ],
871                     "thistle3": [ 205, 181, 205 ],
872                     "thistle4": [ 139, 123, 139 ],
873                     "tomato": [ 255, 99, 71 ],
874                     "tomato1": [ 255, 99, 71 ],
875                     "tomato2": [ 238, 92, 66 ],
876                     "tomato3": [ 205, 79, 57 ],
877                     "tomato4": [ 139, 54, 38 ],
878                     "turquoise": [ 64, 224, 208 ],
879                     "turquoise1": [ 0, 245, 255 ],
880                     "turquoise2": [ 0, 229, 238 ],
881                     "turquoise3": [ 0, 197, 205 ],
882                     "turquoise4": [ 0, 134, 139 ],
883                     "violet": [ 238, 130, 238 ],
884                     "violetred": [ 208, 32, 144 ],
885                     "violetred1": [ 255, 62, 150 ],
886                     "violetred2": [ 238, 58, 140 ],
887                     "violetred3": [ 205, 50, 120 ],
888                     "violetred4": [ 139, 34, 82 ],
889                     "wheat": [ 245, 222, 179 ],
890                     "wheat1": [ 255, 231, 186 ],
891                     "wheat2": [ 238, 216, 174 ],
892                     "wheat3": [ 205, 186, 150 ],
893                     "wheat4": [ 139, 126, 102 ],
894                     "white": [ 255, 255, 255 ],
895                     "whitesmoke": [ 245, 245, 245 ],
896                     "yellow": [ 255, 255, 0 ],
897                     "yellow1": [ 255, 255, 0 ],
898                     "yellow2": [ 238, 238, 0 ],
899                     "yellow3": [ 205, 205, 0 ],
900                     "yellow4": [ 139, 139, 0 ],
901                     "yellowgreen": [ 154, 205, 50 ]
902                 },
903                 "fallbackColor": "white",
904                 "info":
905                 [
906                     "http://www.thomas-guettler.de/rgb.txt.html",
907                     "http://www.astrouw.edu.pl/~jskowron/colors-x11/rgb.html",
908                     "file://localhost/usr/X11/share/X11/rgb.txt"
909                 ]
910             }
911         };
912         //
913         /**
914          * @description Define a custom named colors set.
915          * @param {String} setName Named colors set name (case-insensitive, whitespace ignored)
916          * @param {Object} setData Named colors set data
917          * <p style="margin: 0.5em 0 0 0em;">
918          * The named colors set data structure is defined as a two or three-element JSON object: <br />
919          * <code>{ "colorClass": <em>colorClass</em>, "colorNames": <em>colorNames</em> }</code> or<br />
920          * <code>{ "colorClass": <em>colorClass</em>, "colorNames": <em>colorNames</em>, "fallbackColor": <em>fallbackColor</em> }</code>.
921          * </p>
922          * <p style="margin: 0.5em 0 0 1.25em;">
923          * <code><em>colorClass</em></code>: string (among "bookColor", "CMYKColorClass", "grayscale", "HSBColorClass", "labColor", "RGBColor")<br />
924          * <code><em>colorNames</em></code>: JSON object { } made of key/value pairs: <code><em>colorName</em></code>: <code><em>variantName</em></code>, or <code><em>colorName</em></code>: <code><em>colorComponents</em></code><br />
925          * <code><em>fallbackColor</em></code>: string (optional; if defined, must be one existing key in the <em>colorNames</em></code> object)
926          * </p>
927          * <p style="margin: 0.5em 0 0 2.5em;">
928          * <code><em>colorName</em></code>: string (strictly lowercase, no whitespace)<br />
929          * <code><em>variantName</em></code>: string (must be one existing key in the <em>colorNames</em></code> object, associated with a <code><em>colorComponents</em></code> value)<br />
930          * <code><em>colorComponents</em></code>: JSON array [ ] whose length and contents depend on <code><em>colorClass</em></code>:
931          * </p>
932          * <table style="margin: 0.5em 0 0 3.75em; border-collapse: collapse;">
933          * <tr style="border: 1px solid #E7E7E7;">
934          * <th style="text-align: left; color: gray; padding: 0.25em 2em;"><code><em>colorClass</em></code></th>
935          * <th style="text-align: left; color: gray; padding: 0.25em 2em;"><code><em>colorComponents</em></code></th>
936          * </tr>
937          * <tr style="border: 1px solid #E7E7E7;">
938          * <td style="padding: 0.25em 2em;"><code>"bookColor"</code></td>
939          * <td style="padding: 0.25em 2em;"><code>[ <em>book</em>, <em>name</em>, <em>bookID</em>, <em>bookKey</em> ]</code><br>or<br><code>[ <em>book</em>, <em>name</em> ]</code><br>or<br><code>[ <em>bookID</em>, <em>bookKey</em> ]</code> </td>
940          * </tr>
941          * <tr style="border: 1px solid #E7E7E7;">
942          * <td style="padding: 0.25em 2em;"><code>"CMYKColorClass"</code></td>
943          * <td style="padding: 0.25em 2em;"><code>[ <em>cyan</em>, <em>magenta</em>, <em>yellowColor</em>, <em>black</em> ]</code></td>
944          * </tr>
945          * <tr style="border: 1px solid #E7E7E7;">
946          * <td style="padding: 0.25em 2em;"><code>"grayscale"</code></td>
947          * <td style="padding: 0.25em 2em;"><code>[ <em>gray</em> ]</code><br>or<br><code><em>gray</em></code></td>
948          * </tr>
949          * <tr style="border: 1px solid #E7E7E7;">
950          * <td style="padding: 0.25em 2em;"><code>"HSBColorClass"</code></td>
951          * <td style="padding: 0.25em 2em;"><code>[ <em>hue</em>, <em>saturation</em>, <em>brightness</em> ]</code></td>
952          * </tr>
953          * <tr style="border: 1px solid #E7E7E7;">
954          * <td style="padding: 0.25em 2em;"><code>"labColor"</code></td>
955          * <td style="padding: 0.25em 2em;"><code>[ <em>luminance</em>, <em>a</em>, <em>b</em> ]</code></td>
956          * </tr>
957          * <tr style="border: 1px solid #E7E7E7;">
958          * <td style="padding: 0.25em 2em;"><code>"RGBColor"</code></td>
959          * <td style="padding: 0.25em 2em;"><code>[ <em>red</em>, <em>green</em>, <em>blue</em> ]</code></td>
960          * </tr>
961          * </table>
962          * <p style="margin: 0.5em 0 0 5em;">
963          * <code><em>book</em></code> : string<br />
964          * <code><em>name</em></code> : string<br />
965          * <code><em>bookID</em></code> : number<br />
966          * <code><em>bookKey</em></code> : string<br />
967          * <code><em>cyan</em></code> : number (0 to 100)<br />
968          * <code><em>magenta</em></code> : number (0 to 100)<br />
969          * <code><em>yellowColor</em></code> : number (0 to 100)<br />
970          * <code><em>black</em></code> : number (0 to 100)<br />
971          * <code><em>gray</em></code> : number (0 to 100)<br />
972          * <code><em>hue</em></code> : number (0 to 360)<br />
973          * <code><em>saturation</em></code> : number (0 to 100)<br />
974          * <code><em>brightness</em></code> : number (0 to 100)<br />
975          * <code><em>luminance</em></code> : number (0 to 100)<br />
976          * <code><em>a</em></code> : number (-128 to 127)<br />
977          * <code><em>b</em></code> : number (-128 to 127)<br />
978          * <code><em>red</em></code> : number (0 to 255)<br />
979          * <code><em>green</em></code> : number (0 to 255)<br />
980          * <code><em>blue</em></code> : number (0 to 255)
981          * </p>
982          * @see jamColors.nameToColor
983          * @see jamColors.enumerateNamedColors
984          * @example
985          * var myNamedColors =
986          * {
987          *     "colorClass": "HSBColorClass",
988          *     "colorNames":
989          *     {
990          *         "casper": [ 0, 0, 100 ],
991          *         "felixthecat": [ 0, 0, 0 ],
992          *         "hulk": [ 80, 80, 70 ],
993          *         "redridinghood": [ 20, 95, 80 ],
994          *         "smurf": [ 197, 80, 94 ],
995          *         "papasmurf": "smurf",
996          *         "smurfette": "smurf",
997          *         "tweety": [ 60, 80, 100 ]
998          *     },
999          *     "fallbackColor": "felixthecat"
1000          * };
1001          * jamColors.<strong>defineNamedColorsSet</strong> ("myset", myNamedColors);
1002          * var names = jamColors.enumerateNamedColors ("My Set");
1003          * alert ("My named colors set:\r" + jamJSON.stringify (names.sort (), 4));
1004          * jamEngine.jsonPlay
1005          * (
1006          *     "set",
1007          *     {
1008          *         "target": { "<reference>": [ { "color": { "<property>": "backgroundColor" } } ] },
1009          *         "to": jamHelpers.nameToColorObject ("My Set", "Red Riding Hood")
1010          *     }
1011          * );
1012          * jamEngine.jsonPlay
1013          * (
1014          *     "set",
1015          *     {
1016          *         "target": { "<reference>": [ { "color": { "<property>": "foregroundColor" } } ] },
1017          *         "to": jamHelpers.nameToColorObject ("My Set", "Papa Smurf")
1018          *     }
1019          * );
1020          */
1021         jamColors.defineNamedColorsSet = function (setName, setData)
1022         {
1023             var setName = setName.replace (/\s/g, "").toLowerCase ();
1024             if (setName in namedColorsSets)
1025             {
1026                 throw new Error ("[jamColors.defineNamedColorsSet] Named colors set already exists: " + setName);
1027             }
1028             else if (setData.constructor !== Object)
1029             {
1030                 throw new Error ("[jamColors.defineNamedColorsSet] JavaScript object expected");
1031             }
1032             else if (!(("colorClass" in setData) && ("colorNames" in setData)))
1033             {
1034                 throw new Error ("[jamColors.defineNamedColorsSet] Data syntax error");
1035             }
1036             else
1037             {
1038                 namedColorsSets[setName] = setData;
1039             }
1040         };
1041         //
1042         function getNamedColorsSet (setName)
1043         {
1044             var setName = setName.replace (/\s/g, "").toLowerCase ();
1045             if (setName in namedColorsSets)
1046             {
1047                 var namedColorsSet = namedColorsSets[setName];
1048                 if (typeof namedColorsSet === 'string')
1049                 {
1050                     namedColorsSet = namedColorsSets[namedColorsSet];
1051                 }
1052             }
1053             else
1054             {
1055                 throw new Error ("[jamColors getNamedColorsSet] Unknown named colors set: " + setName);
1056             }
1057             return namedColorsSet;
1058         }
1059         //
1060         /**
1061          * @description Get an array of all color names belonging to a named colors set.
1062          * @param {String} setName Named colors set name (case-insensitive, whitespace ignored):<br />
1063          * <ul>
1064          * <li>
1065          * "CSS" or "SVG" or "W3C":
1066          * <a href="http://www.w3.org/TR/css3-color/#svg-color">CSS Color Module Level 3 - Extended color keywords</a><br />
1067          * or <a href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">SVG 1.1 (Second Edition) - Recognized color keyword names</a>
1068          * </li>
1069          * <li>"X11": <a href="http://www.thomas-guettler.de/rgb.txt.html">Colors of /usr/lib/X11/rgb.txt</a></li>
1070          * <li>or name of a custom named colors set defined by jamColors.defineNamedColorsSet ()</li>
1071          * </ul>
1072          * @param {Boolean} [excludeVariants] Exclude color names spelling variants (i.e. gray/grey); false by default
1073          * @returns {Array} Array of all color names belonging to the named colors set
1074          * @see jamColors.defineNamedColorsSet
1075          * @example
1076          * var x11Names = jamColors.<strong>enumerateNamedColors</strong> ("X11", true);
1077          * $.writeln (jamJSON.stringify (x11Names, 4));
1078          */
1079         jamColors.enumerateNamedColors = function (setName, excludeVariants)
1080         {
1081             var namedColorsSet = getNamedColorsSet (setName);
1082             var colorNames = namedColorsSet["colorNames"];
1083             var names = [ ];
1084             for (var colorName in colorNames)
1085             {
1086                 if (colorNames.hasOwnProperty (colorName))
1087                 {
1088                     if ((!excludeVariants) || (typeof colorNames[colorName] !== 'string'))
1089                     {
1090                         names.push (colorName);
1091                     }
1092                 }
1093             }
1094             return names;
1095         };
1096         //
1097         /**
1098          * @description Get a color in simplified array format [ class, components ] from a color name belonging to a named colors set.
1099          * @param {String} setName Named colors set name (case-insensitive, whitespace ignored):<br />
1100          * <ul>
1101          * <li>
1102          * "CSS" or "SVG" or "W3C":
1103          * <a href="http://www.w3.org/TR/css3-color/#svg-color">CSS Color Module Level 3 - Extended color keywords</a><br />
1104          * or <a href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">SVG 1.1 (Second Edition) - Recognized color keyword names</a>
1105          * </li>
1106          * <li>"X11": <a href="http://www.thomas-guettler.de/rgb.txt.html">Colors of /usr/lib/X11/rgb.txt</a></li>
1107          * <li>or name of a custom named colors set defined by jamColors.defineNamedColorsSet ()</li>
1108          * </ul>
1109          * @param {String} colorName Color name (case-insensitive, whitespace ignored)
1110          * @param {Boolean} strict Strict mode
1111          * @returns {Array} Color in simplified array format [ class, components ]
1112          * @see jamColors.defineNamedColorsSet
1113          * @example
1114          * alert (jamJSON.stringify (jamColors.<strong>nameToColor</strong> ("W3C", "Fuchsia"))); // -> [ "RGBColor", [ 255, 0, 255 ] ]
1115          * alert (jamJSON.stringify (jamColors.<strong>nameToColor</strong> ("X11", "Navy Blue"))); // -> [ "RGBColor", [ 0, 0, 128 ] ]
1116          */
1117         jamColors.nameToColor = function (setName, colorName, strict)
1118         {
1119             var namedColorsSet = getNamedColorsSet (setName);
1120             var colorNames = namedColorsSet["colorNames"];
1121             var colorName = colorName.replace (/\s/g, "").toLowerCase ();
1122             if (!(colorName in colorNames))
1123             {
1124                 if ((!strict) && ("fallbackColor" in namedColorsSet))
1125                 {
1126                     colorName = namedColorsSet["fallbackColor"];
1127                 }
1128                 else
1129                 {
1130                     throw new Error ("[jamColors.nameToColor] Unknown color name: " + colorName);
1131                 }
1132             }
1133             var colorComponents = colorNames[colorName];
1134             return [ namedColorsSet["colorClass"], (typeof colorComponents === 'string') ? colorNames[colorComponents] : colorComponents ];
1135         };
1136         //
1137         /**
1138          * @description Get a RGB color array [ red, green, blue ] from a RGB color string in HTML/CSS hexadecimal notation.
1139          * @param {String} hexColorString RGB color string in HTML/CSS hexadecimal notation (3 or 6 digits, starting with an optional # sign)
1140          * @returns {Array} RGB color array [ red, green, blue ]
1141          * @see jamColors.rgbToHex
1142          * @example
1143          * var rgbColor = jamColors.<strong>hexToRgb</strong> ("ffdead");
1144          * alert (jamJSON.stringify (rgbColor));  // -> [ 255, 222, 173 ]
1145          */
1146         jamColors.hexToRgb = function (hexColorString)
1147         {
1148             var result = hexColorString.match (/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/);
1149             if (result)
1150             {
1151                 var rgb = result[1];
1152                 if (rgb.length === 3)
1153                 {
1154                     rgb = rgb[0] + rgb[0] + rgb[1] + rgb[1] + rgb[2] + rgb[2];
1155                 }
1156                 var color =
1157                 [
1158                     parseInt (rgb.slice (0, 2), 16),
1159                     parseInt (rgb.slice (2, 4), 16),
1160                     parseInt (rgb.slice (4, 6), 16)
1161                 ];
1162             }
1163             else
1164             {
1165                 throw new Error ("[jamColors.hexToRgb] Invalid HTML/CSS hexadecimal string: " + hexColorString);
1166             }
1167             return color;
1168         };
1169         //
1170         /**
1171          * @description Get a RGB color string in HTML/CSS hexadecimal notation from a RGB color array [ red, green, blue ].
1172          * @param {Array} rgbColor RGB color array [ red, green, blue ]
1173          * @param {Boolean} [noSign] Do not add a leading # sign (false by default)
1174          * @param {Boolean} [lowercase] Use lowercase hexadecimal digits (false by default)
1175          * @returns {String} RGB color string in HTML/CSS hexadecimal notation (6 digits, starting with a # sign)
1176          * @see jamColors.hexToRgb
1177          * @example
1178          * var hexColorString = jamColors.<strong>rgbToHex</strong> ([ 255, 222, 173 ]);
1179          * alert (jamJSON.stringify (hexColorString));  // -> "#FFDEAD"
1180          */
1181         jamColors.rgbToHex = function (rgbColor, noSign, lowercase)
1182         {
1183             if ((rgbColor.constructor === Array) && (rgbColor.length === 3))
1184             {
1185                 var red = Math.round (rgbColor[0]);
1186                 var green = Math.round (rgbColor[1]);
1187                 var blue = Math.round (rgbColor[2]);
1188                 var hexaDigits = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" ];
1189                 var hexColorString = (noSign) ? "" : "#";
1190                 hexColorString += hexaDigits[(red & 0xF0) >> 4] + hexaDigits[red & 0x0F];
1191                 hexColorString += hexaDigits[(green & 0xF0) >> 4] + hexaDigits[green & 0x0F];
1192                 hexColorString += hexaDigits[(blue & 0xF0) >> 4] + hexaDigits[blue & 0x0F];
1193                 if (lowercase)
1194                 {
1195                     hexColorString = hexColorString.toLowerCase ();
1196                 }
1197             }
1198             else
1199             {
1200                 throw new Error ("[jamColors.rgbToHex] Invalid RGB color array");
1201             }
1202             return hexColorString;
1203         };
1204         //
1205         /**
1206          * @description Get a RGB color array [ red, green, blue ] from a color string or a RGB color array.
1207          * @param {String|Array} color Color string (HTML/CSS hexadecimal notation, or color name) or RGB color array
1208          * @returns {Array} rgbColor RGB color array [ red, green, blue ]
1209          * @example
1210          * alert (jamJSON.stringify (jamColors.<strong>colorToRgb</strong> ("green")));         // -> [ 0, 128, 0 ]
1211          * alert (jamJSON.stringify (jamColors.<strong>colorToRgb</strong> ("svg:green")));     // -> [ 0, 128, 0 ]
1212          * alert (jamJSON.stringify (jamColors.<strong>colorToRgb</strong> ("svg/green")));     // -> [ 0, 128, 0 ]
1213          * alert (jamJSON.stringify (jamColors.<strong>colorToRgb</strong> ("x11/green")));     // -> [ 0, 255, 0 ]
1214          * alert (jamJSON.stringify (jamColors.<strong>colorToRgb</strong> ("#00FF00")));       // -> [ 0, 255, 0 ]
1215          * alert (jamJSON.stringify (jamColors.<strong>colorToRgb</strong> ([ 0, 255, 0 ])));   // -> [ 0, 255, 0 ]
1216          */
1217         jamColors.colorToRgb = function (color)
1218         {
1219             var rgb = null;
1220             if (typeof color === 'string')
1221             {
1222                 color = color.trim ();
1223                 if (color[0] === '#')
1224                 {
1225                     rgb = this.hexToRgb (color);
1226                 }
1227                 else
1228                 {
1229                     var defaultSetName = "W3C";
1230                     var names = color.split (/[:\/]/);
1231                     var setName;
1232                     var colorName;
1233                     if (names.length > 1)
1234                     {
1235                         setName = names[0] || defaultSetName;
1236                         colorName = names[1];
1237                     }
1238                     else
1239                     {
1240                         setName = defaultSetName;
1241                         colorName = names[0];
1242                     }
1243                     color = this.nameToColor (setName, colorName, true);
1244                     if (color[0] === "RGBColor")
1245                     {
1246                         rgb = color[1];
1247                     }
1248                     else
1249                     {
1250                         throw new Error ("[jamColors.colorToRgb] Unsupported named color set name: " + setName);
1251                     }
1252                 }
1253             }
1254             else if ((color.constructor === Array) && (color.length === 3))
1255             {
1256                 rgb = color;
1257             }
1258             else
1259             {
1260                 throw new Error ("[jamColors.colorToRgb] Invalid syntax");
1261             }
1262             return rgb;
1263         }
1264         //
1265         function limit (value, min, max)
1266         {
1267             return Math.min (Math.max (min, value), max);
1268         }
1269         //
1270         /**
1271          * @description Convert a HSB color array [ hue, saturation, brightness ] to a RGB color array [ red, green, blue ].
1272          * @param {Array} hsbColor HSB color array [ hue, saturation, brightness ]
1273          * @param {Boolean} [hsbFloatRange] Use float range [0.0, 1.0] instead of [0, 360], [0, 100], [0, 100]
1274          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1275          * @returns {Array} RGB color array [ red, green, blue ]
1276          * @see jamColors.rgbToHsb
1277          * @example
1278          * alert (jamJSON.stringify (jamColors.<strong>hsbToRgb</strong> ([ 0, 100, 100 ])));    // -> [ 255, 0, 0 ]
1279          */
1280         jamColors.hsbToRgb = function (hsbColor, hsbFloatRange, rgbFloatRange)
1281         {
1282             var hue = hsbColor[0];
1283             var saturation = hsbColor[1];
1284             var brightness = hsbColor[2];
1285             if (!hsbFloatRange)
1286             {
1287                 hue /= 360;
1288                 saturation /= 100;
1289                 brightness /= 100;
1290             }
1291             hue -= Math.floor (hue);
1292             saturation = limit (saturation, 0.0, 1.0);
1293             brightness = limit (brightness, 0.0, 1.0);
1294             var red;
1295             var green;
1296             var blue;
1297             var i = Math.floor (hue * 6);
1298             var f = (hue * 6) - i;
1299             var p = brightness * (1 - saturation);
1300             var q = brightness * (1 - (f * saturation));
1301             var t = brightness * (1 - ((1 - f) * saturation));
1302             switch (i % 6)
1303             {
1304                 case 0:
1305                     red = brightness;
1306                     green = t;
1307                     blue = p;
1308                     break;
1309                 case 1:
1310                     red = q;
1311                     green = brightness;
1312                     blue = p;
1313                     break;
1314                 case 2:
1315                     red = p;
1316                     green = brightness;
1317                     blue = t;
1318                     break;
1319                 case 3:
1320                     red = p;
1321                     green = q;
1322                     blue = brightness;
1323                     break;
1324                 case 4:
1325                     red = t;
1326                     green = p;
1327                     blue = brightness;
1328                     break;
1329                 case 5:
1330                     red = brightness;
1331                     green = p;
1332                     blue = q;
1333                     break;
1334             }
1335             if (!rgbFloatRange)
1336             {
1337                 red *= 255;
1338                 green *= 255;
1339                 blue *= 255;
1340             }
1341             return [ red, green, blue ];
1342         };
1343         //
1344         /**
1345          * @description Convert a RGB color array [ red, green, blue ] to a HSB color array [ hue, saturation, brightness ].
1346          * @param {Array} rgbColor RGB color array [ red, green, blue ]
1347          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1348          * @param {Boolean} [hsbFloatRange] Use float range [0.0, 1.0] instead of [0, 360], [0, 100], [0, 100]
1349          * @returns {Array} HSB color array [ hue, saturation, brightness ]
1350          * @see jamColors.hsbToRgb
1351          * @example
1352          * alert (jamJSON.stringify (jamColors.<strong>rgbToHsb</strong> ([ 255, 255, 0 ])));    // -> [ 60, 100, 100 ]
1353          */
1354         jamColors.rgbToHsb = function (rgbColor, rgbFloatRange, hsbFloatRange)
1355         {
1356             var red = rgbColor[0];
1357             var green = rgbColor[1];
1358             var blue = rgbColor[2];
1359             if (!rgbFloatRange)
1360             {
1361                 red /= 255;
1362                 green /= 255;
1363                 blue /= 255;
1364             }
1365             red = limit (red, 0.0, 1.0);
1366             green = limit (green, 0.0, 1.0);
1367             blue = limit (blue, 0.0, 1.0);
1368             var min = Math.min (Math.min (red, green), blue);
1369             var max = Math.max (Math.max (red, green), blue);
1370             var delta = max - min;
1371             var hue = 0;
1372             var saturation = 0;
1373             var brightness = max;
1374             if (delta !== 0)
1375             {
1376                 saturation = delta / max;
1377                 if (max === red)    // Between magenta and yellow
1378                 {
1379                     hue = (0 + ((green - blue) / delta)) / 6;
1380                 }
1381                 else if (max === green) // Between yellow and cyan
1382                 {
1383                     hue = (2 + ((blue - red) / delta)) / 6;
1384                 }
1385                 else if (max === blue)  // Between cyan and magenta
1386                 {
1387                     hue = (4 + ((red - green) / delta)) / 6;
1388                 }
1389                 if (hue < 0)
1390                 {
1391                     hue += 1;
1392                 }
1393                 if (hue > 1)
1394                 {
1395                     hue -= 1;
1396                 }
1397             }
1398             if (!hsbFloatRange)
1399             {
1400                 hue *= 360;
1401                 saturation *= 100;
1402                 brightness *= 100;
1403             }
1404             return [ hue, saturation, brightness ];
1405         };
1406         //
1407         /**
1408          * @description Convert a HSL color array [ hue, saturation, lightness ] to a RGB color array [ red, green, blue ].
1409          * @param {Array} hslColor HSL color array [ hue, saturation, lightness ]
1410          * @param {Boolean} [hslFloatRange] Use float range [0.0, 1.0] instead of [0, 360], [0, 100], [0, 100]
1411          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1412          * @returns {Array} RGB color array [ red, green, blue ]
1413          * @see jamColors.rgbToHsl
1414          * @example
1415          * alert (jamJSON.stringify (jamColors.<strong>hslToRgb</strong> ([ 0, 100, 50 ])));    // -> [ 255, 0, 0 ]
1416          */
1417         jamColors.hslToRgb = function (hslColor, hslFloatRange, rgbFloatRange)
1418         {
1419             var hue = hslColor[0];
1420             var saturation = hslColor[1];
1421             var lightness = hslColor[2];
1422             if (!hslFloatRange)
1423             {
1424                 hue /= 360;
1425                 saturation /= 100;
1426                 lightness /= 100;
1427             }
1428             hue -= Math.floor (hue);
1429             saturation = limit (saturation, 0.0, 1.0);
1430             lightness = limit (lightness, 0.0, 1.0);
1431             var red;
1432             var green;
1433             var blue;
1434             if (saturation === 0)
1435             {
1436                 red = green = blue = lightness; // achromatic
1437             }
1438             else
1439             {
1440                 function hue2rgb (p, q, t)
1441                 {
1442                     if (t < 0) t += 1;
1443                     if (t > 1) t -= 1;
1444                     if (t < 1/6) return p + ((q - p) * t * 6);
1445                     if (t < 1/2) return q;
1446                     if (t < 2/3) return p + ((q - p) * (2/3 - t) * 6);
1447                     return p;
1448                 }
1449                 var q = (lightness < 0.5) ? lightness * (1 + saturation) : lightness + saturation - (lightness * saturation);
1450                 var p = (2 * lightness) - q;
1451                 red = hue2rgb (p, q, hue + 1/3);
1452                 green = hue2rgb (p, q, hue);
1453                 blue = hue2rgb (p, q, hue - 1/3);
1454             }
1455             if (!rgbFloatRange)
1456             {
1457                 red *= 255;
1458                 green *= 255;
1459                 blue *= 255;
1460             }
1461             return [ red, green, blue ];
1462         };
1463         //
1464         /**
1465          * @description Convert a RGB color array [ red, green, blue ] to a HSL color array [ hue, saturation, lightness ].
1466          * @param {Array} rgbColor RGB color array [ red, green, blue ]
1467          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1468          * @param {Boolean} [hslFloatRange] Use float range [0.0, 1.0] instead of [0, 360], [0, 100], [0, 100]
1469          * @returns {Array} HSL color array [ hue, saturation, lightness ]
1470          * @see jamColors.hslToRgb
1471          * @example
1472          * alert (jamJSON.stringify (jamColors.<strong>rgbToHsl</strong> ([ 255, 255, 0 ])));    // -> [ 60, 100, 50 ]
1473          */
1474         jamColors.rgbToHsl = function (rgbColor, rgbFloatRange, hslFloatRange)
1475         {
1476             var red = rgbColor[0];
1477             var green = rgbColor[1];
1478             var blue = rgbColor[2];
1479             if (!rgbFloatRange)
1480             {
1481                 red /= 255;
1482                 green /= 255;
1483                 blue /= 255;
1484             }
1485             red = limit (red, 0.0, 1.0);
1486             green = limit (green, 0.0, 1.0);
1487             blue = limit (blue, 0.0, 1.0);
1488             var min = Math.min (Math.min (red, green), blue);
1489             var max = Math.max (Math.max (red, green), blue);
1490             var delta = max - min;
1491             var hue = 0;
1492             var saturation = 0;
1493             var lightness = (max + min) / 2;
1494             if (delta !== 0)
1495             {
1496                 saturation = (lightness < 0.5) ? delta / (max + min) : delta / (2 - (max + min));
1497                 if (max === red)    // Between magenta and yellow
1498                 {
1499                     hue = (0 + ((green - blue) / delta)) / 6;
1500                 }
1501                 else if (max === green) // Between yellow and cyan
1502                 {
1503                     hue = (2 + ((blue - red) / delta)) / 6;
1504                 }
1505                 else if (max === blue)  // Between cyan and magenta
1506                 {
1507                     hue = (4 + ((red - green) / delta)) / 6;
1508                 }
1509                 if (hue < 0)
1510                 {
1511                     hue += 1;
1512                 }
1513                 if (hue > 1)
1514                 {
1515                     hue -= 1;
1516                 }
1517             }
1518             if (!hslFloatRange)
1519             {
1520                 hue *= 360;
1521                 saturation *= 100;
1522                 lightness *= 100;
1523             }
1524             return [ hue, saturation, lightness ];
1525         };
1526         //
1527         // http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html
1528         // http://www.easyrgb.com/index.php?X=CALC
1529         // http://www.easyrgb.com/index.php?X=MATH&H=07#text1   (XYZ —> RGB)
1530         // http://www.easyrgb.com/index.php?X=MATH&H=07#text2   (RGB —> XYZ)
1531         // http://www.easyrgb.com/index.php?X=MATH&H=07#text7   (XYZ —> CIE-L*ab)
1532         // http://www.easyrgb.com/index.php?X=MATH&H=07#text8   (CIE-L*ab —> XYZ)
1533         // http://www.easyrgb.com/index.php?X=MATH&H=07#text9   (CIE-L*ab —> CIE-L*CH°)
1534         // http://www.easyrgb.com/index.php?X=MATH&H=07#text10  (CIE-L*CH° —>CIE-L*ab)
1535         // http://davidjohnstone.net/pages/lch-lab-colour-gradient-picker
1536         // https://d3js.org/
1537         //
1538         var whiteReference = [ 95.047, 100.000, 108.883 ];  // Observer angle = 2°, Illuminant = D65
1539         //
1540         var t0 = 4 / 29;    // 16 / 116
1541         var t1 = 6 / 29;    // 24 / 116
1542         var t2 = 3 * t1 * t1;
1543         var t3 = t1 * t1 * t1;
1544         //
1545         function rgbToXyz (rgbColor)
1546         {
1547             var red = rgbColor[0];
1548             var green = rgbColor[1];
1549             var blue = rgbColor[2];
1550             red /= 255;
1551             green /= 255;
1552             blue /= 255;
1553             function inverseGamma (n)
1554             {
1555                 // sRGB inverse gamma correction
1556                 return (n > 0.04045) ? Math.pow ((n + 0.055) / 1.055, 2.4) : n / 12.92;
1557             }
1558             red = inverseGamma (red);
1559             green = inverseGamma (green);
1560             blue = inverseGamma (blue);
1561             // Observer angle = 2°, Illuminant = D65
1562             var x = (red * 0.4124564) + (green * 0.3575761) + (blue * 0.1804375);
1563             var y = (red * 0.2126729) + (green * 0.7151522) + (blue * 0.0721750);
1564             var z = (red * 0.0193339) + (green * 0.1191920) + (blue * 0.9503041);
1565             x *= 100;
1566             y *= 100;
1567             z *= 100;
1568             return [ x, y, z ];
1569         }
1570         //
1571         function xyzToRgb (xyzColor)
1572         {
1573             var x = xyzColor[0];
1574             var y = xyzColor[1];
1575             var z = xyzColor[2];
1576             // Observer angle = 2°, Illuminant = D65
1577             x /= 100;
1578             y /= 100;
1579             z /= 100;
1580             function gamma (n)
1581             {
1582                 // sRGB gamma correction
1583                 return (n > 0.0031308) ? 1.055 * Math.pow (n, 1/2.4) - 0.055 : 12.92 * n;
1584             }
1585             var red = gamma ((3.2404542 * x) + (-1.5371385 * y) + (-0.4985314 * z));
1586             var green = gamma ((-0.9692660 * x) + (1.8760108 * y) + (0.0415560 * z));
1587             var blue = gamma ((0.0556434 * x) + (-0.2040259 * y) + (1.0572252 * z));
1588             red *= 255;
1589             green *= 255;
1590             blue *= 255;
1591             return [ red, green, blue ];
1592         }
1593         //
1594         function xyzToLab (xyzColor)
1595         {
1596             var x = xyzColor[0] / whiteReference[0];
1597             var y = xyzColor[1] / whiteReference[1];
1598             var z = xyzColor[2] / whiteReference[2];
1599             function pivot (t)
1600             {
1601                 return (t > t3) ? Math.pow (t, 1/3) : (t / t2) + t0;
1602             }
1603             x = pivot (x);
1604             y = pivot (y);
1605             z = pivot (z);
1606             var luminance = (116 * y) - 16;
1607             var a = 500 * (x - y);
1608             var b = 200 * (y - z);
1609             return [ luminance, a, b ];
1610         }
1611         //
1612         function labToXyz (labColor)
1613         {
1614             var luminance = labColor[0];
1615             var a = labColor[1];
1616             var b = labColor[2];
1617             var y = (luminance + 16) / 116;
1618             var x = y + (a / 500);
1619             var z = y - (b / 200);
1620             function inversePivot (t)
1621             {
1622                 return (t > t1) ? t * t * t : (t - t0) * t2;
1623             }
1624             x = inversePivot (x) * whiteReference[0];
1625             y = inversePivot (y) * whiteReference[1];
1626             z = inversePivot (z) * whiteReference[2];
1627             return [ x, y, z ];
1628         }
1629         //
1630         function labToHcl (labColor)
1631         {
1632             var luminance = labColor[0];
1633             var a = labColor[1];
1634             var b = labColor[2];
1635             var hue = Math.atan2 (b, a);
1636             if (hue < 0)
1637             {
1638                 hue += 2 * Math.PI;
1639             }
1640             hue *= 180 / Math.PI;
1641             var chroma = Math.sqrt ((a * a) + (b * b));
1642             return [ hue, chroma, luminance ];
1643         }
1644         //
1645         function hclToLab (hclColor)
1646         {
1647             var hue = hclColor[0];
1648             var chroma = hclColor[1];
1649             var luminance = hclColor[2];
1650             var a = Math.cos (hue * Math.PI / 180) * chroma;
1651             var b = Math.sin (hue * Math.PI / 180) * chroma;
1652             return [ luminance, a , b ];
1653         }
1654         //
1655         /**
1656          * @description Convert a XYZ color array [ x, y, z ] to a RGB color array [ red, green, blue ].
1657          * @param {Array} xyzColor XYZ color array [ x, y, z ]
1658          * @param {Boolean} [xyzFloatRange] Use float range [0.0, 1.0] instead of [0, 100], [0, 100], [0, 100]
1659          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1660          * @returns {Array} RGB color array [ red, green, blue ]
1661          * @see jamColors.rgbToXyz
1662          * @example
1663          * alert (jamJSON.stringify (jamColors.<strong>xyzToRgb</strong> ([ 59, 28, 97 ])));
1664          */
1665         jamColors.xyzToRgb = function (xyzColor, xyzFloatRange, rgbFloatRange)
1666         {
1667             var x = xyzColor[0];
1668             var y = xyzColor[1];
1669             var z = xyzColor[2];
1670             if (xyzFloatRange)
1671             {
1672                 x *= 100;
1673                 y *= 100;
1674                 z *= 100;
1675             }
1676             var rgbColor = xyzToRgb ([ x, y, z ]);
1677             var red = rgbColor[0];
1678             var green = rgbColor[1];
1679             var blue = rgbColor[2];
1680             if (rgbFloatRange)
1681             {
1682                 red /= 255;
1683                 green /= 255;
1684                 blue /= 255;
1685             }
1686             return [ red, green, blue ];
1687         };
1688         //
1689         /**
1690          * @description Convert a RGB color array [ red, green, blue ] to a XYZ color array [ x, y, z ].
1691          * @param {Array} rgbColor RGB color array [ red, green, blue ]
1692          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1693          * @param {Boolean} [xyzFloatRange] Use float range [0.0, 1.0] instead of [0, 100], [0, 100], [0, 100]
1694          * @returns {Array} XYZ color array [ x, y, z ]
1695          * @see jamColors.xyzToRgb
1696          * @example
1697          * alert (jamJSON.stringify (jamColors.<strong>rgbToXyz</strong> ([ 255, 0, 255 ])));
1698          */
1699         jamColors.rgbToXyz = function (rgbColor, rgbFloatRange, xyzFloatRange)
1700         {
1701             var red = rgbColor[0];
1702             var green = rgbColor[1];
1703             var blue = rgbColor[2];
1704             if (rgbFloatRange)
1705             {
1706                 red *= 255;
1707                 green *= 255;
1708                 blue *= 255;
1709             }
1710             var xyzColor = rgbToXyz ([ red, green, blue ]);
1711             var x = xyzColor[0];
1712             var y = xyzColor[1];
1713             var z = xyzColor[2];
1714             if (xyzFloatRange)
1715             {
1716                 x /= 100;
1717                 y /= 100;
1718                 z /= 100;
1719             }
1720             return [ x, y, z ];
1721         };
1722         //
1723         /**
1724          * @description Convert a Lab color array [ luminance, a, b ] to a RGB color array [ red, green, blue ].
1725          * @param {Array} labColor Lab color array [ luminance, a, b ]
1726          * @param {Boolean} [labFloatRange] Use float range [0.0, 1.0] instead of [0, 100], [-128, 128], [-128, 128]
1727          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1728          * @returns {Array} RGB color array [ red, green, blue ]
1729          * @see jamColors.rgbToLab
1730          * @example
1731          * var labColor = jamColors.rgbToLab ([ 0, 0, 255 ], false, true);
1732          * alert (jamJSON.stringify (jamColors.<strong>labToRgb</strong> (labColor, true)));
1733          */
1734         jamColors.labToRgb = function (labColor, labFloatRange, rgbFloatRange)
1735         {
1736             var luminance = labColor[0];
1737             var a = labColor[1];
1738             var b = labColor[2];
1739             if (labFloatRange)
1740             {
1741                 luminance *= 100;
1742                 a *= 256; a -= 128;
1743                 b *= 256; b -= 128;
1744             }
1745             var rgbColor = xyzToRgb (labToXyz ([ luminance, a, b ]));
1746             var red = rgbColor[0];
1747             var green = rgbColor[1];
1748             var blue = rgbColor[2];
1749             if (rgbFloatRange)
1750             {
1751                 red /= 255;
1752                 green /= 255;
1753                 blue /= 255;
1754             }
1755             return [ red, green, blue ];
1756         };
1757         //
1758         /**
1759          * @description Convert a RGB color array [ red, green, blue ] to a Lab color array [ luminance, a, b ].
1760          * @param {Array} rgbColor RGB color array [ red, green, blue ]
1761          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1762          * @param {Boolean} [labFloatRange] Use float range [0.0, 1.0] instead of [0, 100], [-128, 128], [-128, 128]
1763          * @returns {Array} Lab color array [ luminance, a, b ]
1764          * @see jamColors.labToRgb
1765          * @example
1766          * var labColor = jamColors.<strong>rgbToLab</strong> ([ 215, 25, 28 ], false, true);
1767          * alert (jamJSON.stringify (jamColors.labToRgb (labColor, true)));
1768          */
1769         jamColors.rgbToLab = function (rgbColor, rgbFloatRange, labFloatRange)
1770         {
1771             var red = rgbColor[0];
1772             var green = rgbColor[1];
1773             var blue = rgbColor[2];
1774             if (rgbFloatRange)
1775             {
1776                 red *= 255;
1777                 green *= 255;
1778                 blue *= 255;
1779             }
1780             var labColor = xyzToLab (rgbToXyz ([ red, green, blue ]));
1781             var luminance = labColor[0];
1782             var a = labColor[1];
1783             var b = labColor[2];
1784             if (labFloatRange)
1785             {
1786                 luminance /= 100;
1787                 a += 128; a /= 256;
1788                 b += 128; b /= 256;
1789             }
1790             return [ luminance, a, b ];
1791         };
1792         //
1793         /**
1794          * @description Convert a HCL color array [ hue, chroma, luminance ] to a RGB color array [ red, green, blue ].
1795          * @param {Array} hclColor HCL color array [ hue, chroma, luminance ]
1796          * @param {Boolean} [hclFloatRange] Use float range [0.0, 1.0] instead of [0, 360], [0, 128], [0, 100]
1797          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1798          * @returns {Array} RGB color array [ red, green, blue ]
1799          * @see jamColors.rgbToHcl
1800          * @example
1801          * var hclColor = jamColors.rgbToHcl ([ 0, 0, 255 ], false, true);
1802          * alert (jamJSON.stringify (jamColors.<strong>hclToRgb</strong> (hclColor, true)));
1803          */
1804         jamColors.hclToRgb = function (hclColor, hclFloatRange, rgbFloatRange)
1805         {
1806             var hue = hclColor[0];
1807             var chroma = hclColor[1];
1808             var luminance = hclColor[2];
1809             if (hclFloatRange)
1810             {
1811                 hue *= 360;
1812                 chroma *= 128;
1813                 luminance *= 100;
1814             }
1815             var rgbColor = xyzToRgb (labToXyz (hclToLab ([ hue, chroma, luminance ])));
1816             var red = rgbColor[0];
1817             var green = rgbColor[1];
1818             var blue = rgbColor[2];
1819             if (rgbFloatRange)
1820             {
1821                 red /= 255;
1822                 green /= 255;
1823                 blue /= 255;
1824             }
1825             return [ red, green, blue ];
1826         };
1827         //
1828         /**
1829          * @description Convert a RGB color array [ red, green, blue ] to a HCL color array [ hue, chroma, luminance ].
1830          * @param {Array} rgbColor RGB color array [ red, green, blue ]
1831          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1832          * @param {Boolean} [hclFloatRange] Use float range [0.0, 1.0] instead of [0, 360], [0, 128], [0, 100]
1833          * @returns {Array} HCL color array [ hue, chroma, luminance ]
1834          * @see jamColors.hclToRgb
1835          * @example
1836          * var hclColor = jamColors.<strong>rgbToHcl</strong> ([ 215, 25, 28 ], false, true);
1837          * alert (jamJSON.stringify (jamColors.hclToRgb (hclColor, true)));
1838          */
1839         jamColors.rgbToHcl = function (rgbColor, rgbFloatRange, hclFloatRange)
1840         {
1841             var red = rgbColor[0];
1842             var green = rgbColor[1];
1843             var blue = rgbColor[2];
1844             if (rgbFloatRange)
1845             {
1846                 red *= 255;
1847                 green *= 255;
1848                 blue *= 255;
1849             }
1850             var hclColor = labToHcl (xyzToLab (rgbToXyz ([ red, green, blue ])));
1851             var hue = hclColor[0];
1852             var chroma = hclColor[1];
1853             var luminance = hclColor[2];
1854             if (hclFloatRange)
1855             {
1856                 hue /= 360;
1857                 chroma /= 128;
1858                 luminance /= 100;
1859             }
1860             return [ hue, chroma, luminance ];
1861         };
1862         //
1863         // YCbCr <https://en.wikipedia.org/wiki/YCbCr>
1864         // Intuitive Colorization of Temperature in Thermal Cameras <http://www.diva-portal.org/smash/get/diva2:797457/FULLTEXT01.pdf>
1865         // Color Conversion <http://www.equasys.de/colorconversion.html>
1866         //
1867         /**
1868          * @description Convert a YCbCr color array [ y, cb, cr ] to a RGB color array [ red, green, blue ].
1869          * @param {Array} ycbcrColor YCbCr color array [ y, cb, cr ]
1870          * @param {Boolean} [ycbcrFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1871          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1872          * @returns {Array} RGB color array [ red, green, blue ]
1873          * @see jamColors.rgbToYcbcr
1874          * @example
1875          * var ycbcrColor = jamColors.rgbToYcbcr ([ 128, 128, 128 ]);
1876          * alert (jamJSON.stringify (jamColors.<strong>ycbcrToRgb</strong> (ycbcrColor))); // -> [ 128, 128, 128 ]
1877          */
1878         jamColors.ycbcrToRgb = function (ycbcrColor, ycbcrFloatRange, rgbFloatRange)
1879         {
1880             var y = ycbcrColor[0];
1881             var cb = ycbcrColor[1];
1882             var cr = ycbcrColor[2];
1883             if (ycbcrFloatRange)
1884             {
1885                 y *= 255;
1886                 cb *= 255;
1887                 cr *= 255;
1888             }
1889             var red = y + (1.402 * (cr - 128));
1890             var green = y - (0.34414 * (cb - 128)) - (0.71414 * (cr - 128));
1891             var blue = y + (1.772 * (cb - 128));
1892             if (rgbFloatRange)
1893             {
1894                 red /= 255;
1895                 green /= 255;
1896                 blue /= 255;
1897             }
1898             return [ red, green, blue ];
1899         };
1900         //
1901         /**
1902          * @description Convert a RGB color array [ red, green, blue ] to a YCbCr color array [ y, cb, cr ].
1903          * @param {Array} rgbColor RGB color array [ red, green, blue ]
1904          * @param {Boolean} [rgbFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1905          * @param {Boolean} [ycbcrFloatRange] Use float range [0.0, 1.0] instead of [0, 255]
1906          * @returns {Array} YCbCr color array [ y, cb, cr ]
1907          * @see jamColors.ycbcrToRgb
1908          * @example
1909          * var ycbcrColor = jamColors.<strong>rgbToYcbcr</strong> ([ 128, 128, 128 ], false, true);
1910          * alert (jamJSON.stringify (jamColors.ycbcrToRgb (ycbcrColor, true))); // -> [ 128, 128, 128 ]
1911          */
1912         jamColors.rgbToYcbcr = function (rgbColor, rgbFloatRange, ycbcrFloatRange)
1913         {
1914             var red = rgbColor[0];
1915             var green = rgbColor[1];
1916             var blue = rgbColor[2];
1917             if (rgbFloatRange)
1918             {
1919                 red *= 255;
1920                 green *= 255;
1921                 blue *= 255;
1922             }
1923             var y = 0 + (0.299 * red) + (0.587 * green) + (0.114 * blue);
1924             var cb = 128 - (0.168736 * red) - (0.331264 * green) + (0.5 * blue);
1925             var cr = 128 + (0.5 * red) - (0.418688 * green) - (0.081312 * blue);
1926             if (ycbcrFloatRange)
1927             {
1928                 y /= 255;
1929                 cb /= 255;
1930                 cr /= 255;
1931             }
1932             return [ y, cb, cr ];
1933         };
1934     } ());
1935 }
1936 
1937 //------------------------------------------------------------------------------
1938 
1939