/** * @license * * chroma.js - JavaScript library for color conversions * * Copyright (c) 2011-2017, Gregor Aisch * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The name Gregor Aisch may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL GREGOR AISCH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ (function() { var Color, DEG2RAD, LAB_CONSTANTS, PI, PITHIRD, RAD2DEG, TWOPI, _average_lrgb, _guess_formats, _guess_formats_sorted, _input, _interpolators, abs, atan2, bezier, blend, blend_f, brewer, burn, chroma, clip_rgb, cmyk2rgb, colors, cos, css2rgb, darken, dodge, each, floor, hcg2rgb, hex2rgb, hsi2rgb, hsl2css, hsl2rgb, hsv2rgb, interpolate, interpolate_hsx, interpolate_lab, interpolate_lrgb, interpolate_num, interpolate_rgb, lab2lch, lab2rgb, lab_xyz, lch2lab, lch2rgb, lighten, limit, log, luminance_x, m, max, multiply, normal, num2rgb, overlay, pow, rgb2cmyk, rgb2css, rgb2hcg, rgb2hex, rgb2hsi, rgb2hsl, rgb2hsv, rgb2lab, rgb2lch, rgb2luminance, rgb2num, rgb2temperature, rgb2xyz, rgb_xyz, rnd, root, round, screen, sin, sqrt, temperature2rgb, type, unpack, w3cx11, xyz_lab, xyz_rgb, slice = [].slice; type = (function() { /* for browser-safe type checking+ ported from jQuery's $.type */ var classToType, len, name, o, ref; classToType = {}; ref = "Boolean Number String Function Array Date RegExp Undefined Null".split(" "); for (o = 0, len = ref.length; o < len; o++) { name = ref[o]; classToType["[object " + name + "]"] = name.toLowerCase(); } return function(obj) { var strType; strType = Object.prototype.toString.call(obj); return classToType[strType] || "object"; }; })(); limit = function(x, min, max) { if (min == null) { min = 0; } if (max == null) { max = 1; } if (x < min) { x = min; } if (x > max) { x = max; } return x; }; unpack = function(args) { if (args.length >= 3) { return Array.prototype.slice.call(args); } else { return args[0]; } }; clip_rgb = function(rgb) { var i, o; rgb._clipped = false; rgb._unclipped = rgb.slice(0); for (i = o = 0; o < 3; i = ++o) { if (i < 3) { if (rgb[i] < 0 || rgb[i] > 255) { rgb._clipped = true; } if (rgb[i] < 0) { rgb[i] = 0; } if (rgb[i] > 255) { rgb[i] = 255; } } else if (i === 3) { if (rgb[i] < 0) { rgb[i] = 0; } if (rgb[i] > 1) { rgb[i] = 1; } } } if (!rgb._clipped) { delete rgb._unclipped; } return rgb; }; PI = Math.PI, round = Math.round, cos = Math.cos, floor = Math.floor, pow = Math.pow, log = Math.log, sin = Math.sin, sqrt = Math.sqrt, atan2 = Math.atan2, max = Math.max, abs = Math.abs; TWOPI = PI * 2; PITHIRD = PI / 3; DEG2RAD = PI / 180; RAD2DEG = 180 / PI; chroma = function() { if (arguments[0] instanceof Color) { return arguments[0]; } return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, arguments, function(){}); }; chroma["default"] = chroma; _interpolators = []; if ((typeof module !== "undefined" && module !== null) && (module.exports != null)) { module.exports = chroma; } if (typeof define === 'function' && define.amd) { define([], function() { return chroma; }); } else { root = typeof exports !== "undefined" && exports !== null ? exports : this; root.chroma = chroma; } chroma.version = '1.3.7'; _input = {}; _guess_formats = []; _guess_formats_sorted = false; Color = (function() { function Color() { var arg, args, chk, len, len1, me, mode, o, w; me = this; args = []; for (o = 0, len = arguments.length; o < len; o++) { arg = arguments[o]; if (arg != null) { args.push(arg); } } if (args.length > 1) { mode = args[args.length - 1]; } if (_input[mode] != null) { me._rgb = clip_rgb(_input[mode](unpack(args.slice(0, -1)))); } else { if (!_guess_formats_sorted) { _guess_formats = _guess_formats.sort(function(a, b) { return b.p - a.p; }); _guess_formats_sorted = true; } for (w = 0, len1 = _guess_formats.length; w < len1; w++) { chk = _guess_formats[w]; mode = chk.test.apply(chk, args); if (mode) { break; } } if (mode) { me._rgb = clip_rgb(_input[mode].apply(_input, args)); } } if (me._rgb == null) { console.warn('unknown format: ' + args); } if (me._rgb == null) { me._rgb = [0, 0, 0]; } if (me._rgb.length === 3) { me._rgb.push(1); } } Color.prototype.toString = function() { return this.hex(); }; Color.prototype.clone = function() { return chroma(me._rgb); }; return Color; })(); chroma._input = _input; /** ColorBrewer colors for chroma.js Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania State University. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. @preserve */ chroma.brewer = brewer = { OrRd: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#b30000', '#7f0000'], PuBu: ['#fff7fb', '#ece7f2', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#045a8d', '#023858'], BuPu: ['#f7fcfd', '#e0ecf4', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#810f7c', '#4d004b'], Oranges: ['#fff5eb', '#fee6ce', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#a63603', '#7f2704'], BuGn: ['#f7fcfd', '#e5f5f9', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#006d2c', '#00441b'], YlOrBr: ['#ffffe5', '#fff7bc', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#993404', '#662506'], YlGn: ['#ffffe5', '#f7fcb9', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#006837', '#004529'], Reds: ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#a50f15', '#67000d'], RdPu: ['#fff7f3', '#fde0dd', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177', '#49006a'], Greens: ['#f7fcf5', '#e5f5e0', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#006d2c', '#00441b'], YlGnBu: ['#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#253494', '#081d58'], Purples: ['#fcfbfd', '#efedf5', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#54278f', '#3f007d'], GnBu: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#0868ac', '#084081'], Greys: ['#ffffff', '#f0f0f0', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525', '#000000'], YlOrRd: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#bd0026', '#800026'], PuRd: ['#f7f4f9', '#e7e1ef', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#980043', '#67001f'], Blues: ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#08519c', '#08306b'], PuBuGn: ['#fff7fb', '#ece2f0', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016c59', '#014636'], Viridis: ['#440154', '#482777', '#3f4a8a', '#31678e', '#26838f', '#1f9d8a', '#6cce5a', '#b6de2b', '#fee825'], Spectral: ['#9e0142', '#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#e6f598', '#abdda4', '#66c2a5', '#3288bd', '#5e4fa2'], RdYlGn: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', '#006837'], RdBu: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#f7f7f7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac', '#053061'], PiYG: ['#8e0152', '#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#f7f7f7', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221', '#276419'], PRGn: ['#40004b', '#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837', '#00441b'], RdYlBu: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee090', '#ffffbf', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695'], BrBG: ['#543005', '#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#f5f5f5', '#c7eae5', '#80cdc1', '#35978f', '#01665e', '#003c30'], RdGy: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#ffffff', '#e0e0e0', '#bababa', '#878787', '#4d4d4d', '#1a1a1a'], PuOr: ['#7f3b08', '#b35806', '#e08214', '#fdb863', '#fee0b6', '#f7f7f7', '#d8daeb', '#b2abd2', '#8073ac', '#542788', '#2d004b'], Set2: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', '#e5c494', '#b3b3b3'], Accent: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f', '#bf5b17', '#666666'], Set1: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf', '#999999'], Set3: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5', '#ffed6f'], Dark2: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d', '#666666'], Paired: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99', '#b15928'], Pastel2: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae', '#f1e2cc', '#cccccc'], Pastel1: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd', '#fddaec', '#f2f2f2'] }; (function() { var key, results; results = []; for (key in brewer) { results.push(brewer[key.toLowerCase()] = brewer[key]); } return results; })(); /** X11 color names http://www.w3.org/TR/css3-color/#svg-color */ w3cx11 = { aliceblue: '#f0f8ff', antiquewhite: '#faebd7', aqua: '#00ffff', aquamarine: '#7fffd4', azure: '#f0ffff', beige: '#f5f5dc', bisque: '#ffe4c4', black: '#000000', blanchedalmond: '#ffebcd', blue: '#0000ff', blueviolet: '#8a2be2', brown: '#a52a2a', burlywood: '#deb887', cadetblue: '#5f9ea0', chartreuse: '#7fff00', chocolate: '#d2691e', coral: '#ff7f50', cornflower: '#6495ed', cornflowerblue: '#6495ed', cornsilk: '#fff8dc', crimson: '#dc143c', cyan: '#00ffff', darkblue: '#00008b', darkcyan: '#008b8b', darkgoldenrod: '#b8860b', darkgray: '#a9a9a9', darkgreen: '#006400', darkgrey: '#a9a9a9', darkkhaki: '#bdb76b', darkmagenta: '#8b008b', darkolivegreen: '#556b2f', darkorange: '#ff8c00', darkorchid: '#9932cc', darkred: '#8b0000', darksalmon: '#e9967a', darkseagreen: '#8fbc8f', darkslateblue: '#483d8b', darkslategray: '#2f4f4f', darkslategrey: '#2f4f4f', darkturquoise: '#00ced1', darkviolet: '#9400d3', deeppink: '#ff1493', deepskyblue: '#00bfff', dimgray: '#696969', dimgrey: '#696969', dodgerblue: '#1e90ff', firebrick: '#b22222', floralwhite: '#fffaf0', forestgreen: '#228b22', fuchsia: '#ff00ff', gainsboro: '#dcdcdc', ghostwhite: '#f8f8ff', gold: '#ffd700', goldenrod: '#daa520', gray: '#808080', green: '#008000', greenyellow: '#adff2f', grey: '#808080', honeydew: '#f0fff0', hotpink: '#ff69b4', indianred: '#cd5c5c', indigo: '#4b0082', ivory: '#fffff0', khaki: '#f0e68c', laserlemon: '#ffff54', lavender: '#e6e6fa', lavenderblush: '#fff0f5', lawngreen: '#7cfc00', lemonchiffon: '#fffacd', lightblue: '#add8e6', lightcoral: '#f08080', lightcyan: '#e0ffff', lightgoldenrod: '#fafad2', lightgoldenrodyellow: '#fafad2', lightgray: '#d3d3d3', lightgreen: '#90ee90', lightgrey: '#d3d3d3', lightpink: '#ffb6c1', lightsalmon: '#ffa07a', lightseagreen: '#20b2aa', lightskyblue: '#87cefa', lightslategray: '#778899', lightslategrey: '#778899', lightsteelblue: '#b0c4de', lightyellow: '#ffffe0', lime: '#00ff00', limegreen: '#32cd32', linen: '#faf0e6', magenta: '#ff00ff', maroon: '#800000', maroon2: '#7f0000', maroon3: '#b03060', mediumaquamarine: '#66cdaa', mediumblue: '#0000cd', mediumorchid: '#ba55d3', mediumpurple: '#9370db', mediumseagreen: '#3cb371', mediumslateblue: '#7b68ee', mediumspringgreen: '#00fa9a', mediumturquoise: '#48d1cc', mediumvioletred: '#c71585', midnightblue: '#191970', mintcream: '#f5fffa', mistyrose: '#ffe4e1', moccasin: '#ffe4b5', navajowhite: '#ffdead', navy: '#000080', oldlace: '#fdf5e6', olive: '#808000', olivedrab: '#6b8e23', orange: '#ffa500', orangered: '#ff4500', orchid: '#da70d6', palegoldenrod: '#eee8aa', palegreen: '#98fb98', paleturquoise: '#afeeee', palevioletred: '#db7093', papayawhip: '#ffefd5', peachpuff: '#ffdab9', peru: '#cd853f', pink: '#ffc0cb', plum: '#dda0dd', powderblue: '#b0e0e6', purple: '#800080', purple2: '#7f007f', purple3: '#a020f0', rebeccapurple: '#663399', red: '#ff0000', rosybrown: '#bc8f8f', royalblue: '#4169e1', saddlebrown: '#8b4513', salmon: '#fa8072', sandybrown: '#f4a460', seagreen: '#2e8b57', seashell: '#fff5ee', sienna: '#a0522d', silver: '#c0c0c0', skyblue: '#87ceeb', slateblue: '#6a5acd', slategray: '#708090', slategrey: '#708090', snow: '#fffafa', springgreen: '#00ff7f', steelblue: '#4682b4', tan: '#d2b48c', teal: '#008080', thistle: '#d8bfd8', tomato: '#ff6347', turquoise: '#40e0d0', violet: '#ee82ee', wheat: '#f5deb3', white: '#ffffff', whitesmoke: '#f5f5f5', yellow: '#ffff00', yellowgreen: '#9acd32' }; chroma.colors = colors = w3cx11; lab2rgb = function() { var a, args, b, g, l, r, x, y, z; args = unpack(arguments); l = args[0], a = args[1], b = args[2]; y = (l + 16) / 116; x = isNaN(a) ? y : y + a / 500; z = isNaN(b) ? y : y - b / 200; y = LAB_CONSTANTS.Yn * lab_xyz(y); x = LAB_CONSTANTS.Xn * lab_xyz(x); z = LAB_CONSTANTS.Zn * lab_xyz(z); r = xyz_rgb(3.2404542 * x - 1.5371385 * y - 0.4985314 * z); g = xyz_rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z); b = xyz_rgb(0.0556434 * x - 0.2040259 * y + 1.0572252 * z); return [r, g, b, args.length > 3 ? args[3] : 1]; }; xyz_rgb = function(r) { return 255 * (r <= 0.00304 ? 12.92 * r : 1.055 * pow(r, 1 / 2.4) - 0.055); }; lab_xyz = function(t) { if (t > LAB_CONSTANTS.t1) { return t * t * t; } else { return LAB_CONSTANTS.t2 * (t - LAB_CONSTANTS.t0); } }; LAB_CONSTANTS = { Kn: 18, Xn: 0.950470, Yn: 1, Zn: 1.088830, t0: 0.137931034, t1: 0.206896552, t2: 0.12841855, t3: 0.008856452 }; rgb2lab = function() { var b, g, r, ref, ref1, x, y, z; ref = unpack(arguments), r = ref[0], g = ref[1], b = ref[2]; ref1 = rgb2xyz(r, g, b), x = ref1[0], y = ref1[1], z = ref1[2]; return [116 * y - 16, 500 * (x - y), 200 * (y - z)]; }; rgb_xyz = function(r) { if ((r /= 255) <= 0.04045) { return r / 12.92; } else { return pow((r + 0.055) / 1.055, 2.4); } }; xyz_lab = function(t) { if (t > LAB_CONSTANTS.t3) { return pow(t, 1 / 3); } else { return t / LAB_CONSTANTS.t2 + LAB_CONSTANTS.t0; } }; rgb2xyz = function() { var b, g, r, ref, x, y, z; ref = unpack(arguments), r = ref[0], g = ref[1], b = ref[2]; r = rgb_xyz(r); g = rgb_xyz(g); b = rgb_xyz(b); x = xyz_lab((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / LAB_CONSTANTS.Xn); y = xyz_lab((0.2126729 * r + 0.7151522 * g + 0.0721750 * b) / LAB_CONSTANTS.Yn); z = xyz_lab((0.0193339 * r + 0.1191920 * g + 0.9503041 * b) / LAB_CONSTANTS.Zn); return [x, y, z]; }; chroma.lab = function() { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, slice.call(arguments).concat(['lab']), function(){}); }; _input.lab = lab2rgb; Color.prototype.lab = function() { return rgb2lab(this._rgb); }; bezier = function(colors) { var I, I0, I1, c, lab0, lab1, lab2, lab3, ref, ref1, ref2; colors = (function() { var len, o, results; results = []; for (o = 0, len = colors.length; o < len; o++) { c = colors[o]; results.push(chroma(c)); } return results; })(); if (colors.length === 2) { ref = (function() { var len, o, results; results = []; for (o = 0, len = colors.length; o < len; o++) { c = colors[o]; results.push(c.lab()); } return results; })(), lab0 = ref[0], lab1 = ref[1]; I = function(t) { var i, lab; lab = (function() { var o, results; results = []; for (i = o = 0; o <= 2; i = ++o) { results.push(lab0[i] + t * (lab1[i] - lab0[i])); } return results; })(); return chroma.lab.apply(chroma, lab); }; } else if (colors.length === 3) { ref1 = (function() { var len, o, results; results = []; for (o = 0, len = colors.length; o < len; o++) { c = colors[o]; results.push(c.lab()); } return results; })(), lab0 = ref1[0], lab1 = ref1[1], lab2 = ref1[2]; I = function(t) { var i, lab; lab = (function() { var o, results; results = []; for (i = o = 0; o <= 2; i = ++o) { results.push((1 - t) * (1 - t) * lab0[i] + 2 * (1 - t) * t * lab1[i] + t * t * lab2[i]); } return results; })(); return chroma.lab.apply(chroma, lab); }; } else if (colors.length === 4) { ref2 = (function() { var len, o, results; results = []; for (o = 0, len = colors.length; o < len; o++) { c = colors[o]; results.push(c.lab()); } return results; })(), lab0 = ref2[0], lab1 = ref2[1], lab2 = ref2[2], lab3 = ref2[3]; I = function(t) { var i, lab; lab = (function() { var o, results; results = []; for (i = o = 0; o <= 2; i = ++o) { results.push((1 - t) * (1 - t) * (1 - t) * lab0[i] + 3 * (1 - t) * (1 - t) * t * lab1[i] + 3 * (1 - t) * t * t * lab2[i] + t * t * t * lab3[i]); } return results; })(); return chroma.lab.apply(chroma, lab); }; } else if (colors.length === 5) { I0 = bezier(colors.slice(0, 3)); I1 = bezier(colors.slice(2, 5)); I = function(t) { if (t < 0.5) { return I0(t * 2); } else { return I1((t - 0.5) * 2); } }; } return I; }; chroma.bezier = function(colors) { var f; f = bezier(colors); f.scale = function() { return chroma.scale(f); }; return f; }; /* chroma.js Copyright (c) 2011-2013, Gregor Aisch All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The name Gregor Aisch may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GREGOR AISCH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @source: https://github.com/gka/chroma.js */ chroma.cubehelix = function(start, rotations, hue, gamma, lightness) { var dh, dl, f; if (start == null) { start = 300; } if (rotations == null) { rotations = -1.5; } if (hue == null) { hue = 1; } if (gamma == null) { gamma = 1; } if (lightness == null) { lightness = [0, 1]; } dh = 0; if (type(lightness) === 'array') { dl = lightness[1] - lightness[0]; } else { dl = 0; lightness = [lightness, lightness]; } f = function(fract) { var a, amp, b, cos_a, g, h, l, r, sin_a; a = TWOPI * ((start + 120) / 360 + rotations * fract); l = pow(lightness[0] + dl * fract, gamma); h = dh !== 0 ? hue[0] + fract * dh : hue; amp = h * l * (1 - l) / 2; cos_a = cos(a); sin_a = sin(a); r = l + amp * (-0.14861 * cos_a + 1.78277 * sin_a); g = l + amp * (-0.29227 * cos_a - 0.90649 * sin_a); b = l + amp * (+1.97294 * cos_a); return chroma(clip_rgb([r * 255, g * 255, b * 255])); }; f.start = function(s) { if (s == null) { return start; } start = s; return f; }; f.rotations = function(r) { if (r == null) { return rotations; } rotations = r; return f; }; f.gamma = function(g) { if (g == null) { return gamma; } gamma = g; return f; }; f.hue = function(h) { if (h == null) { return hue; } hue = h; if (type(hue) === 'array') { dh = hue[1] - hue[0]; if (dh === 0) { hue = hue[1]; } } else { dh = 0; } return f; }; f.lightness = function(h) { if (h == null) { return lightness; } if (type(h) === 'array') { lightness = h; dl = h[1] - h[0]; } else { lightness = [h, h]; dl = 0; } return f; }; f.scale = function() { return chroma.scale(f); }; f.hue(hue); return f; }; chroma.random = function() { var code, digits, i, o; digits = '0123456789abcdef'; code = '#'; for (i = o = 0; o < 6; i = ++o) { code += digits.charAt(floor(Math.random() * 16)); } return new Color(code); }; _interpolators = []; interpolate = function(col1, col2, f, m) { var interpol, len, o, res; if (f == null) { f = 0.5; } if (m == null) { m = 'rgb'; } /* interpolates between colors f = 0 --> me f = 1 --> col */ if (type(col1) !== 'object') { col1 = chroma(col1); } if (type(col2) !== 'object') { col2 = chroma(col2); } for (o = 0, len = _interpolators.length; o < len; o++) { interpol = _interpolators[o]; if (m === interpol[0]) { res = interpol[1](col1, col2, f, m); break; } } if (res == null) { throw "color mode " + m + " is not supported"; } return res.alpha(col1.alpha() + f * (col2.alpha() - col1.alpha())); }; chroma.interpolate = interpolate; Color.prototype.interpolate = function(col2, f, m) { return interpolate(this, col2, f, m); }; chroma.mix = interpolate; Color.prototype.mix = Color.prototype.interpolate; _input.rgb = function() { var k, ref, results, v; ref = unpack(arguments); results = []; for (k in ref) { v = ref[k]; results.push(v); } return results; }; chroma.rgb = function() { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, slice.call(arguments).concat(['rgb']), function(){}); }; Color.prototype.rgb = function(round) { if (round == null) { round = true; } if (round) { return this._rgb.map(Math.round).slice(0, 3); } else { return this._rgb.slice(0, 3); } }; Color.prototype.rgba = function(round) { if (round == null) { round = true; } if (!round) { return this._rgb.slice(0); } return [Math.round(this._rgb[0]), Math.round(this._rgb[1]), Math.round(this._rgb[2]), this._rgb[3]]; }; _guess_formats.push({ p: 3, test: function(n) { var a; a = unpack(arguments); if (type(a) === 'array' && a.length === 3) { return 'rgb'; } if (a.length === 4 && type(a[3]) === "number" && a[3] >= 0 && a[3] <= 1) { return 'rgb'; } } }); _input.lrgb = _input.rgb; interpolate_lrgb = function(col1, col2, f, m) { var xyz0, xyz1; xyz0 = col1._rgb; xyz1 = col2._rgb; return new Color(sqrt(pow(xyz0[0], 2) * (1 - f) + pow(xyz1[0], 2) * f), sqrt(pow(xyz0[1], 2) * (1 - f) + pow(xyz1[1], 2) * f), sqrt(pow(xyz0[2], 2) * (1 - f) + pow(xyz1[2], 2) * f), m); }; _average_lrgb = function(colors) { var col, f, len, o, rgb, xyz; f = 1 / colors.length; xyz = [0, 0, 0, 0]; for (o = 0, len = colors.length; o < len; o++) { col = colors[o]; rgb = col._rgb; xyz[0] += pow(rgb[0], 2) * f; xyz[1] += pow(rgb[1], 2) * f; xyz[2] += pow(rgb[2], 2) * f; xyz[3] += rgb[3] * f; } xyz[0] = sqrt(xyz[0]); xyz[1] = sqrt(xyz[1]); xyz[2] = sqrt(xyz[2]); return new Color(xyz); }; _interpolators.push(['lrgb', interpolate_lrgb]); chroma.average = function(colors, mode) { var A, alpha, c, cnt, dx, dy, first, i, l, len, o, xyz, xyz2; if (mode == null) { mode = 'rgb'; } l = colors.length; colors = colors.map(function(c) { return chroma(c); }); first = colors.splice(0, 1)[0]; if (mode === 'lrgb') { return _average_lrgb(colors); } xyz = first.get(mode); cnt = []; dx = 0; dy = 0; for (i in xyz) { xyz[i] = xyz[i] || 0; cnt.push(isNaN(xyz[i]) ? 0 : 1); if (mode.charAt(i) === 'h' && !isNaN(xyz[i])) { A = xyz[i] / 180 * PI; dx += cos(A); dy += sin(A); } } alpha = first.alpha(); for (o = 0, len = colors.length; o < len; o++) { c = colors[o]; xyz2 = c.get(mode); alpha += c.alpha(); for (i in xyz) { if (!isNaN(xyz2[i])) { cnt[i] += 1; if (mode.charAt(i) === 'h') { A = xyz2[i] / 180 * PI; dx += cos(A); dy += sin(A); } else { xyz[i] += xyz2[i]; } } } } for (i in xyz) { if (mode.charAt(i) === 'h') { A = atan2(dy / cnt[i], dx / cnt[i]) / PI * 180; while (A < 0) { A += 360; } while (A >= 360) { A -= 360; } xyz[i] = A; } else { xyz[i] = xyz[i] / cnt[i]; } } return chroma(xyz, mode).alpha(alpha / l); }; hex2rgb = function(hex) { var a, b, g, r, rgb, u; if (hex.match(/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)) { if (hex.length === 4 || hex.length === 7) { hex = hex.substr(1); } if (hex.length === 3) { hex = hex.split(""); hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; } u = parseInt(hex, 16); r = u >> 16; g = u >> 8 & 0xFF; b = u & 0xFF; return [r, g, b, 1]; } if (hex.match(/^#?([A-Fa-f0-9]{8})$/)) { if (hex.length === 9) { hex = hex.substr(1); } u = parseInt(hex, 16); r = u >> 24 & 0xFF; g = u >> 16 & 0xFF; b = u >> 8 & 0xFF; a = round((u & 0xFF) / 0xFF * 100) / 100; return [r, g, b, a]; } if ((_input.css != null) && (rgb = _input.css(hex))) { return rgb; } throw "unknown color: " + hex; }; rgb2hex = function(channels, mode) { var a, b, g, hxa, r, str, u; if (mode == null) { mode = 'rgb'; } r = channels[0], g = channels[1], b = channels[2], a = channels[3]; r = Math.round(r); g = Math.round(g); b = Math.round(b); u = r << 16 | g << 8 | b; str = "000000" + u.toString(16); str = str.substr(str.length - 6); hxa = '0' + round(a * 255).toString(16); hxa = hxa.substr(hxa.length - 2); return "#" + (function() { switch (mode.toLowerCase()) { case 'rgba': return str + hxa; case 'argb': return hxa + str; default: return str; } })(); }; _input.hex = function(h) { return hex2rgb(h); }; chroma.hex = function() { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, slice.call(arguments).concat(['hex']), function(){}); }; Color.prototype.hex = function(mode) { if (mode == null) { mode = 'rgb'; } return rgb2hex(this._rgb, mode); }; _guess_formats.push({ p: 4, test: function(n) { if (arguments.length === 1 && type(n) === "string") { return 'hex'; } } }); hsl2rgb = function() { var args, b, c, g, h, i, l, o, r, ref, s, t1, t2, t3; args = unpack(arguments); h = args[0], s = args[1], l = args[2]; if (s === 0) { r = g = b = l * 255; } else { t3 = [0, 0, 0]; c = [0, 0, 0]; t2 = l < 0.5 ? l * (1 + s) : l + s - l * s; t1 = 2 * l - t2; h /= 360; t3[0] = h + 1 / 3; t3[1] = h; t3[2] = h - 1 / 3; for (i = o = 0; o <= 2; i = ++o) { if (t3[i] < 0) { t3[i] += 1; } if (t3[i] > 1) { t3[i] -= 1; } if (6 * t3[i] < 1) { c[i] = t1 + (t2 - t1) * 6 * t3[i]; } else if (2 * t3[i] < 1) { c[i] = t2; } else if (3 * t3[i] < 2) { c[i] = t1 + (t2 - t1) * ((2 / 3) - t3[i]) * 6; } else { c[i] = t1; } } ref = [round(c[0] * 255), round(c[1] * 255), round(c[2] * 255)], r = ref[0], g = ref[1], b = ref[2]; } if (args.length > 3) { return [r, g, b, args[3]]; } else { return [r, g, b]; } }; rgb2hsl = function(r, g, b) { var h, l, min, ref, s; if (r !== void 0 && r.length >= 3) { ref = r, r = ref[0], g = ref[1], b = ref[2]; } r /= 255; g /= 255; b /= 255; min = Math.min(r, g, b); max = Math.max(r, g, b); l = (max + min) / 2; if (max === min) { s = 0; h = Number.NaN; } else { s = l < 0.5 ? (max - min) / (max + min) : (max - min) / (2 - max - min); } if (r === max) { h = (g - b) / (max - min); } else if (g === max) { h = 2 + (b - r) / (max - min); } else if (b === max) { h = 4 + (r - g) / (max - min); } h *= 60; if (h < 0) { h += 360; } return [h, s, l]; }; chroma.hsl = function() { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, slice.call(arguments).concat(['hsl']), function(){}); }; _input.hsl = hsl2rgb; Color.prototype.hsl = function() { return rgb2hsl(this._rgb); }; hsv2rgb = function() { var args, b, f, g, h, i, p, q, r, ref, ref1, ref2, ref3, ref4, ref5, s, t, v; args = unpack(arguments); h = args[0], s = args[1], v = args[2]; v *= 255; if (s === 0) { r = g = b = v; } else { if (h === 360) { h = 0; } if (h > 360) { h -= 360; } if (h < 0) { h += 360; } h /= 60; i = floor(h); f = h - i; p = v * (1 - s); q = v * (1 - s * f); t = v * (1 - s * (1 - f)); switch (i) { case 0: ref = [v, t, p], r = ref[0], g = ref[1], b = ref[2]; break; case 1: ref1 = [q, v, p], r = ref1[0], g = ref1[1], b = ref1[2]; break; case 2: ref2 = [p, v, t], r = ref2[0], g = ref2[1], b = ref2[2]; break; case 3: ref3 = [p, q, v], r = ref3[0], g = ref3[1], b = ref3[2]; break; case 4: ref4 = [t, p, v], r = ref4[0], g = ref4[1], b = ref4[2]; break; case 5: ref5 = [v, p, q], r = ref5[0], g = ref5[1], b = ref5[2]; } } return [r, g, b, args.length > 3 ? args[3] : 1]; }; rgb2hsv = function() { var b, delta, g, h, min, r, ref, s, v; ref = unpack(arguments), r = ref[0], g = ref[1], b = ref[2]; min = Math.min(r, g, b); max = Math.max(r, g, b); delta = max - min; v = max / 255.0; if (max === 0) { h = Number.NaN; s = 0; } else { s = delta / max; if (r === max) { h = (g - b) / delta; } if (g === max) { h = 2 + (b - r) / delta; } if (b === max) { h = 4 + (r - g) / delta; } h *= 60; if (h < 0) { h += 360; } } return [h, s, v]; }; chroma.hsv = function() { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, slice.call(arguments).concat(['hsv']), function(){}); }; _input.hsv = hsv2rgb; Color.prototype.hsv = function() { return rgb2hsv(this._rgb); }; num2rgb = function(num) { var b, g, r; if (type(num) === "number" && num >= 0 && num <= 0xFFFFFF) { r = num >> 16; g = (num >> 8) & 0xFF; b = num & 0xFF; return [r, g, b, 1]; } console.warn("unknown num color: " + num); return [0, 0, 0, 1]; }; rgb2num = function() { var b, g, r, ref; ref = unpack(arguments), r = ref[0], g = ref[1], b = ref[2]; return (r << 16) + (g << 8) + b; }; chroma.num = function(num) { return new Color(num, 'num'); }; Color.prototype.num = function(mode) { if (mode == null) { mode = 'rgb'; } return rgb2num(this._rgb, mode); }; _input.num = num2rgb; _guess_formats.push({ p: 1, test: function(n) { if (arguments.length === 1 && type(n) === "number" && n >= 0 && n <= 0xFFFFFF) { return 'num'; } } }); hcg2rgb = function() { var _c, _g, args, b, c, f, g, h, i, p, q, r, ref, ref1, ref2, ref3, ref4, ref5, t, v; args = unpack(arguments); h = args[0], c = args[1], _g = args[2]; c = c / 100; g = g / 100 * 255; _c = c * 255; if (c === 0) { r = g = b = _g; } else { if (h === 360) { h = 0; } if (h > 360) { h -= 360; } if (h < 0) { h += 360; } h /= 60; i = floor(h); f = h - i; p = _g * (1 - c); q = p + _c * (1 - f); t = p + _c * f; v = p + _c; switch (i) { case 0: ref = [v, t, p], r = ref[0], g = ref[1], b = ref[2]; break; case 1: ref1 = [q, v, p], r = ref1[0], g = ref1[1], b = ref1[2]; break; case 2: ref2 = [p, v, t], r = ref2[0], g = ref2[1], b = ref2[2]; break; case 3: ref3 = [p, q, v], r = ref3[0], g = ref3[1], b = ref3[2]; break; case 4: ref4 = [t, p, v], r = ref4[0], g = ref4[1], b = ref4[2]; break; case 5: ref5 = [v, p, q], r = ref5[0], g = ref5[1], b = ref5[2]; } } return [r, g, b, args.length > 3 ? args[3] : 1]; }; rgb2hcg = function() { var _g, b, c, delta, g, h, min, r, ref; ref = unpack(arguments), r = ref[0], g = ref[1], b = ref[2]; min = Math.min(r, g, b); max = Math.max(r, g, b); delta = max - min; c = delta * 100 / 255; _g = min / (255 - delta) * 100; if (delta === 0) { h = Number.NaN; } else { if (r === max) { h = (g - b) / delta; } if (g === max) { h = 2 + (b - r) / delta; } if (b === max) { h = 4 + (r - g) / delta; } h *= 60; if (h < 0) { h += 360; } } return [h, c, _g]; }; chroma.hcg = function() { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, slice.call(arguments).concat(['hcg']), function(){}); }; _input.hcg = hcg2rgb; Color.prototype.hcg = function() { return rgb2hcg(this._rgb); }; css2rgb = function(css) { var aa, ab, hsl, i, m, o, rgb, w; css = css.toLowerCase(); if ((chroma.colors != null) && chroma.colors[css]) { return hex2rgb(chroma.colors[css]); } if (m = css.match(/rgb\(\s*(\-?\d+),\s*(\-?\d+)\s*,\s*(\-?\d+)\s*\)/)) { rgb = m.slice(1, 4); for (i = o = 0; o <= 2; i = ++o) { rgb[i] = +rgb[i]; } rgb[3] = 1; } else if (m = css.match(/rgba\(\s*(\-?\d+),\s*(\-?\d+)\s*,\s*(\-?\d+)\s*,\s*([01]|[01]?\.\d+)\)/)) { rgb = m.slice(1, 5); for (i = w = 0; w <= 3; i = ++w) { rgb[i] = +rgb[i]; } } else if (m = css.match(/rgb\(\s*(\-?\d+(?:\.\d+)?)%,\s*(\-?\d+(?:\.\d+)?)%\s*,\s*(\-?\d+(?:\.\d+)?)%\s*\)/)) { rgb = m.slice(1, 4); for (i = aa = 0; aa <= 2; i = ++aa) { rgb[i] = round(rgb[i] * 2.55); } rgb[3] = 1; } else if (m = css.match(/rgba\(\s*(\-?\d+(?:\.\d+)?)%,\s*(\-?\d+(?:\.\d+)?)%\s*,\s*(\-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)/)) { rgb = m.slice(1, 5); for (i = ab = 0; ab <= 2; i = ++ab) { rgb[i] = round(rgb[i] * 2.55); } rgb[3] = +rgb[3]; } else if (m = css.match(/hsl\(\s*(\-?\d+(?:\.\d+)?),\s*(\-?\d+(?:\.\d+)?)%\s*,\s*(\-?\d+(?:\.\d+)?)%\s*\)/)) { hsl = m.slice(1, 4); hsl[1] *= 0.01; hsl[2] *= 0.01; rgb = hsl2rgb(hsl); rgb[3] = 1; } else if (m = css.match(/hsla\(\s*(\-?\d+(?:\.\d+)?),\s*(\-?\d+(?:\.\d+)?)%\s*,\s*(\-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)/)) { hsl = m.slice(1, 4); hsl[1] *= 0.01; hsl[2] *= 0.01; rgb = hsl2rgb(hsl); rgb[3] = +m[4]; } return rgb; }; rgb2css = function(rgba) { var mode; mode = rgba[3] < 1 ? 'rgba' : 'rgb'; if (mode === 'rgb') { return mode + '(' + rgba.slice(0, 3).map(round).join(',') + ')'; } else if (mode === 'rgba') { return mode + '(' + rgba.slice(0, 3).map(round).join(',') + ',' + rgba[3] + ')'; } else { } }; rnd = function(a) { return round(a * 100) / 100; }; hsl2css = function(hsl, alpha) { var mode; mode = alpha < 1 ? 'hsla' : 'hsl'; hsl[0] = rnd(hsl[0] || 0); hsl[1] = rnd(hsl[1] * 100) + '%'; hsl[2] = rnd(hsl[2] * 100) + '%'; if (mode === 'hsla') { hsl[3] = alpha; } return mode + '(' + hsl.join(',') + ')'; }; _input.css = function(h) { return css2rgb(h); }; chroma.css = function() { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, slice.call(arguments).concat(['css']), function(){}); }; Color.prototype.css = function(mode) { if (mode == null) { mode = 'rgb'; } if (mode.slice(0, 3) === 'rgb') { return rgb2css(this._rgb); } else if (mode.slice(0, 3) === 'hsl') { return hsl2css(this.hsl(), this.alpha()); } }; _input.named = function(name) { return hex2rgb(w3cx11[name]); }; _guess_formats.push({ p: 5, test: function(n) { if (arguments.length === 1 && (w3cx11[n] != null)) { return 'named'; } } }); Color.prototype.name = function(n) { var h, k; if (arguments.length) { if (w3cx11[n]) { this._rgb = hex2rgb(w3cx11[n]); } this._rgb[3] = 1; this; } h = this.hex(); for (k in w3cx11) { if (h === w3cx11[k]) { return k; } } return h; }; lch2lab = function() { /* Convert from a qualitative parameter h and a quantitative parameter l to a 24-bit pixel. These formulas were invented by David Dalrymple to obtain maximum contrast without going out of gamut if the parameters are in the range 0-1. A saturation multiplier was added by Gregor Aisch */ var c, h, l, ref; ref = unpack(arguments), l = ref[0], c = ref[1], h = ref[2]; h = h * DEG2RAD; return [l, cos(h) * c, sin(h) * c]; }; lch2rgb = function() { var L, a, args, b, c, g, h, l, r, ref, ref1; args = unpack(arguments); l = args[0], c = args[1], h = args[2]; ref = lch2lab(l, c, h), L = ref[0], a = ref[1], b = ref[2]; ref1 = lab2rgb(L, a, b), r = ref1[0], g = ref1[1], b = ref1[2]; return [r, g, b, args.length > 3 ? args[3] : 1]; }; lab2lch = function() { var a, b, c, h, l, ref; ref = unpack(arguments), l = ref[0], a = ref[1], b = ref[2]; c = sqrt(a * a + b * b); h = (atan2(b, a) * RAD2DEG + 360) % 360; if (round(c * 10000) === 0) { h = Number.NaN; } return [l, c, h]; }; rgb2lch = function() { var a, b, g, l, r, ref, ref1; ref = unpack(arguments), r = ref[0], g = ref[1], b = ref[2]; ref1 = rgb2lab(r, g, b), l = ref1[0], a = ref1[1], b = ref1[2]; return lab2lch(l, a, b); }; chroma.lch = function() { var args; args = unpack(arguments); return new Color(args, 'lch'); }; chroma.hcl = function() { var args; args = unpack(arguments); return new Color(args, 'hcl'); }; _input.lch = lch2rgb; _input.hcl = function() { var c, h, l, ref; ref = unpack(arguments), h = ref[0], c = ref[1], l = ref[2]; return lch2rgb([l, c, h]); }; Color.prototype.lch = function() { return rgb2lch(this._rgb); }; Color.prototype.hcl = function() { return rgb2lch(this._rgb).reverse(); }; rgb2cmyk = function(mode) { var b, c, f, g, k, m, r, ref, y; if (mode == null) { mode = 'rgb'; } ref = unpack(arguments), r = ref[0], g = ref[1], b = ref[2]; r = r / 255; g = g / 255; b = b / 255; k = 1 - Math.max(r, Math.max(g, b)); f = k < 1 ? 1 / (1 - k) : 0; c = (1 - r - k) * f; m = (1 - g - k) * f; y = (1 - b - k) * f; return [c, m, y, k]; }; cmyk2rgb = function() { var alpha, args, b, c, g, k, m, r, y; args = unpack(arguments); c = args[0], m = args[1], y = args[2], k = args[3]; alpha = args.length > 4 ? args[4] : 1; if (k === 1) { return [0, 0, 0, alpha]; } r = c >= 1 ? 0 : 255 * (1 - c) * (1 - k); g = m >= 1 ? 0 : 255 * (1 - m) * (1 - k); b = y >= 1 ? 0 : 255 * (1 - y) * (1 - k); return [r, g, b, alpha]; }; _input.cmyk = function() { return cmyk2rgb(unpack(arguments)); }; chroma.cmyk = function() { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, slice.call(arguments).concat(['cmyk']), function(){}); }; Color.prototype.cmyk = function() { return rgb2cmyk(this._rgb); }; _input.gl = function() { var i, k, o, rgb, v; rgb = (function() { var ref, results; ref = unpack(arguments); results = []; for (k in ref) { v = ref[k]; results.push(v); } return results; }).apply(this, arguments); for (i = o = 0; o <= 2; i = ++o) { rgb[i] *= 255; } return rgb; }; chroma.gl = function() { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, slice.call(arguments).concat(['gl']), function(){}); }; Color.prototype.gl = function() { var rgb; rgb = this._rgb; return [rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, rgb[3]]; }; rgb2luminance = function(r, g, b) { var ref; ref = unpack(arguments), r = ref[0], g = ref[1], b = ref[2]; r = luminance_x(r); g = luminance_x(g); b = luminance_x(b); return 0.2126 * r + 0.7152 * g + 0.0722 * b; }; luminance_x = function(x) { x /= 255; if (x <= 0.03928) { return x / 12.92; } else { return pow((x + 0.055) / 1.055, 2.4); } }; interpolate_rgb = function(col1, col2, f, m) { var xyz0, xyz1; xyz0 = col1._rgb; xyz1 = col2._rgb; return new Color(xyz0[0] + f * (xyz1[0] - xyz0[0]), xyz0[1] + f * (xyz1[1] - xyz0[1]), xyz0[2] + f * (xyz1[2] - xyz0[2]), m); }; _interpolators.push(['rgb', interpolate_rgb]); Color.prototype.luminance = function(lum, mode) { var cur_lum, eps, max_iter, rgba, test; if (mode == null) { mode = 'rgb'; } if (!arguments.length) { return rgb2luminance(this._rgb); } rgba = this._rgb; if (lum === 0) { rgba = [0, 0, 0, this._rgb[3]]; } else if (lum === 1) { rgba = [255, 255, 255, this[3]]; } else { cur_lum = rgb2luminance(this._rgb); eps = 1e-7; max_iter = 20; test = function(l, h) { var lm, m; m = l.interpolate(h, 0.5, mode); lm = m.luminance(); if (Math.abs(lum - lm) < eps || !max_iter--) { return m; } if (lm > lum) { return test(l, m); } return test(m, h); }; if (cur_lum > lum) { rgba = test(chroma('black'), this).rgba(); } else { rgba = test(this, chroma('white')).rgba(); } } return chroma(rgba).alpha(this.alpha()); }; temperature2rgb = function(kelvin) { var b, g, r, temp; temp = kelvin / 100; if (temp < 66) { r = 255; g = -155.25485562709179 - 0.44596950469579133 * (g = temp - 2) + 104.49216199393888 * log(g); b = temp < 20 ? 0 : -254.76935184120902 + 0.8274096064007395 * (b = temp - 10) + 115.67994401066147 * log(b); } else { r = 351.97690566805693 + 0.114206453784165 * (r = temp - 55) - 40.25366309332127 * log(r); g = 325.4494125711974 + 0.07943456536662342 * (g = temp - 50) - 28.0852963507957 * log(g); b = 255; } return [r, g, b]; }; rgb2temperature = function() { var b, eps, g, maxTemp, minTemp, r, ref, rgb, temp; ref = unpack(arguments), r = ref[0], g = ref[1], b = ref[2]; minTemp = 1000; maxTemp = 40000; eps = 0.4; while (maxTemp - minTemp > eps) { temp = (maxTemp + minTemp) * 0.5; rgb = temperature2rgb(temp); if ((rgb[2] / rgb[0]) >= (b / r)) { maxTemp = temp; } else { minTemp = temp; } } return round(temp); }; chroma.temperature = chroma.kelvin = function() { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, slice.call(arguments).concat(['temperature']), function(){}); }; _input.temperature = _input.kelvin = _input.K = temperature2rgb; Color.prototype.temperature = function() { return rgb2temperature(this._rgb); }; Color.prototype.kelvin = Color.prototype.temperature; chroma.contrast = function(a, b) { var l1, l2, ref, ref1; if ((ref = type(a)) === 'string' || ref === 'number') { a = new Color(a); } if ((ref1 = type(b)) === 'string' || ref1 === 'number') { b = new Color(b); } l1 = a.luminance(); l2 = b.luminance(); if (l1 > l2) { return (l1 + 0.05) / (l2 + 0.05); } else { return (l2 + 0.05) / (l1 + 0.05); } }; chroma.distance = function(a, b, mode) { var d, i, l1, l2, ref, ref1, sum_sq; if (mode == null) { mode = 'lab'; } if ((ref = type(a)) === 'string' || ref === 'number') { a = new Color(a); } if ((ref1 = type(b)) === 'string' || ref1 === 'number') { b = new Color(b); } l1 = a.get(mode); l2 = b.get(mode); sum_sq = 0; for (i in l1) { d = (l1[i] || 0) - (l2[i] || 0); sum_sq += d * d; } return Math.sqrt(sum_sq); }; chroma.deltaE = function(a, b, L, C) { var L1, L2, a1, a2, b1, b2, c1, c2, c4, dH2, delA, delB, delC, delL, f, h1, ref, ref1, ref2, ref3, sc, sh, sl, t, v1, v2, v3; if (L == null) { L = 1; } if (C == null) { C = 1; } if ((ref = type(a)) === 'string' || ref === 'number') { a = new Color(a); } if ((ref1 = type(b)) === 'string' || ref1 === 'number') { b = new Color(b); } ref2 = a.lab(), L1 = ref2[0], a1 = ref2[1], b1 = ref2[2]; ref3 = b.lab(), L2 = ref3[0], a2 = ref3[1], b2 = ref3[2]; c1 = sqrt(a1 * a1 + b1 * b1); c2 = sqrt(a2 * a2 + b2 * b2); sl = L1 < 16.0 ? 0.511 : (0.040975 * L1) / (1.0 + 0.01765 * L1); sc = (0.0638 * c1) / (1.0 + 0.0131 * c1) + 0.638; h1 = c1 < 0.000001 ? 0.0 : (atan2(b1, a1) * 180.0) / PI; while (h1 < 0) { h1 += 360; } while (h1 >= 360) { h1 -= 360; } t = (h1 >= 164.0) && (h1 <= 345.0) ? 0.56 + abs(0.2 * cos((PI * (h1 + 168.0)) / 180.0)) : 0.36 + abs(0.4 * cos((PI * (h1 + 35.0)) / 180.0)); c4 = c1 * c1 * c1 * c1; f = sqrt(c4 / (c4 + 1900.0)); sh = sc * (f * t + 1.0 - f); delL = L1 - L2; delC = c1 - c2; delA = a1 - a2; delB = b1 - b2; dH2 = delA * delA + delB * delB - delC * delC; v1 = delL / (L * sl); v2 = delC / (C * sc); v3 = sh; return sqrt(v1 * v1 + v2 * v2 + (dH2 / (v3 * v3))); }; Color.prototype.get = function(modechan) { var channel, i, me, mode, ref, src; me = this; ref = modechan.split('.'), mode = ref[0], channel = ref[1]; src = me[mode](); if (channel) { i = mode.indexOf(channel); if (i > -1) { return src[i]; } else { return console.warn('unknown channel ' + channel + ' in mode ' + mode); } } else { return src; } }; Color.prototype.set = function(modechan, value) { var channel, i, me, mode, ref, src; me = this; ref = modechan.split('.'), mode = ref[0], channel = ref[1]; if (channel) { src = me[mode](); i = mode.indexOf(channel); if (i > -1) { if (type(value) === 'string') { switch (value.charAt(0)) { case '+': src[i] += +value; break; case '-': src[i] += +value; break; case '*': src[i] *= +(value.substr(1)); break; case '/': src[i] /= +(value.substr(1)); break; default: src[i] = +value; } } else { src[i] = value; } } else { console.warn('unknown channel ' + channel + ' in mode ' + mode); } } else { src = value; } return chroma(src, mode).alpha(me.alpha()); }; Color.prototype.clipped = function() { return this._rgb._clipped || false; }; Color.prototype.alpha = function(a) { if (arguments.length) { return chroma.rgb([this._rgb[0], this._rgb[1], this._rgb[2], a]); } return this._rgb[3]; }; Color.prototype.darken = function(amount) { var lab, me; if (amount == null) { amount = 1; } me = this; lab = me.lab(); lab[0] -= LAB_CONSTANTS.Kn * amount; return chroma.lab(lab).alpha(me.alpha()); }; Color.prototype.brighten = function(amount) { if (amount == null) { amount = 1; } return this.darken(-amount); }; Color.prototype.darker = Color.prototype.darken; Color.prototype.brighter = Color.prototype.brighten; Color.prototype.saturate = function(amount) { var lch, me; if (amount == null) { amount = 1; } me = this; lch = me.lch(); lch[1] += amount * LAB_CONSTANTS.Kn; if (lch[1] < 0) { lch[1] = 0; } return chroma.lch(lch).alpha(me.alpha()); }; Color.prototype.desaturate = function(amount) { if (amount == null) { amount = 1; } return this.saturate(-amount); }; Color.prototype.premultiply = function() { var a, rgb; rgb = this.rgb(); a = this.alpha(); return chroma(rgb[0] * a, rgb[1] * a, rgb[2] * a, a); }; blend = function(bottom, top, mode) { if (!blend[mode]) { throw 'unknown blend mode ' + mode; } return blend[mode](bottom, top); }; blend_f = function(f) { return function(bottom, top) { var c0, c1; c0 = chroma(top).rgb(); c1 = chroma(bottom).rgb(); return chroma(f(c0, c1), 'rgb'); }; }; each = function(f) { return function(c0, c1) { var i, o, out; out = []; for (i = o = 0; o <= 3; i = ++o) { out[i] = f(c0[i], c1[i]); } return out; }; }; normal = function(a, b) { return a; }; multiply = function(a, b) { return a * b / 255; }; darken = function(a, b) { if (a > b) { return b; } else { return a; } }; lighten = function(a, b) { if (a > b) { return a; } else { return b; } }; screen = function(a, b) { return 255 * (1 - (1 - a / 255) * (1 - b / 255)); }; overlay = function(a, b) { if (b < 128) { return 2 * a * b / 255; } else { return 255 * (1 - 2 * (1 - a / 255) * (1 - b / 255)); } }; burn = function(a, b) { return 255 * (1 - (1 - b / 255) / (a / 255)); }; dodge = function(a, b) { if (a === 255) { return 255; } a = 255 * (b / 255) / (1 - a / 255); if (a > 255) { return 255; } else { return a; } }; blend.normal = blend_f(each(normal)); blend.multiply = blend_f(each(multiply)); blend.screen = blend_f(each(screen)); blend.overlay = blend_f(each(overlay)); blend.darken = blend_f(each(darken)); blend.lighten = blend_f(each(lighten)); blend.dodge = blend_f(each(dodge)); blend.burn = blend_f(each(burn)); chroma.blend = blend; chroma.analyze = function(data) { var len, o, r, val; r = { min: Number.MAX_VALUE, max: Number.MAX_VALUE * -1, sum: 0, values: [], count: 0 }; for (o = 0, len = data.length; o < len; o++) { val = data[o]; if ((val != null) && !isNaN(val)) { r.values.push(val); r.sum += val; if (val < r.min) { r.min = val; } if (val > r.max) { r.max = val; } r.count += 1; } } r.domain = [r.min, r.max]; r.limits = function(mode, num) { return chroma.limits(r, mode, num); }; return r; }; chroma.scale = function(colors, positions) { var _classes, _colorCache, _colors, _correctLightness, _domain, _fixed, _gamma, _max, _min, _mode, _nacol, _out, _padding, _pos, _spread, _useCache, classifyValue, f, getClass, getColor, resetCache, setColors, tmap; _mode = 'rgb'; _nacol = chroma('#ccc'); _spread = 0; _fixed = false; _domain = [0, 1]; _pos = []; _padding = [0, 0]; _classes = false; _colors = []; _out = false; _min = 0; _max = 1; _correctLightness = false; _colorCache = {}; _useCache = true; _gamma = 1; setColors = function(colors) { var c, col, o, ref, ref1, w; if (colors == null) { colors = ['#fff', '#000']; } if ((colors != null) && type(colors) === 'string' && (chroma.brewer != null)) { colors = chroma.brewer[colors] || chroma.brewer[colors.toLowerCase()] || colors; } if (type(colors) === 'array') { colors = colors.slice(0); for (c = o = 0, ref = colors.length - 1; 0 <= ref ? o <= ref : o >= ref; c = 0 <= ref ? ++o : --o) { col = colors[c]; if (type(col) === "string") { colors[c] = chroma(col); } } _pos.length = 0; for (c = w = 0, ref1 = colors.length - 1; 0 <= ref1 ? w <= ref1 : w >= ref1; c = 0 <= ref1 ? ++w : --w) { _pos.push(c / (colors.length - 1)); } } resetCache(); return _colors = colors; }; getClass = function(value) { var i, n; if (_classes != null) { n = _classes.length - 1; i = 0; while (i < n && value >= _classes[i]) { i++; } return i - 1; } return 0; }; tmap = function(t) { return t; }; classifyValue = function(value) { var i, maxc, minc, n, val; val = value; if (_classes.length > 2) { n = _classes.length - 1; i = getClass(value); minc = _classes[0] + (_classes[1] - _classes[0]) * (0 + _spread * 0.5); maxc = _classes[n - 1] + (_classes[n] - _classes[n - 1]) * (1 - _spread * 0.5); val = _min + ((_classes[i] + (_classes[i + 1] - _classes[i]) * 0.5 - minc) / (maxc - minc)) * (_max - _min); } return val; }; getColor = function(val, bypassMap) { var c, col, i, k, o, p, ref, t; if (bypassMap == null) { bypassMap = false; } if (isNaN(val)) { return _nacol; } if (!bypassMap) { if (_classes && _classes.length > 2) { c = getClass(val); t = c / (_classes.length - 2); } else if (_max !== _min) { t = (val - _min) / (_max - _min); } else { t = 1; } } else { t = val; } if (!bypassMap) { t = tmap(t); } if (_gamma !== 1) { t = pow(t, _gamma); } t = _padding[0] + (t * (1 - _padding[0] - _padding[1])); t = Math.min(1, Math.max(0, t)); k = Math.floor(t * 10000); if (_useCache && _colorCache[k]) { col = _colorCache[k]; } else { if (type(_colors) === 'array') { for (i = o = 0, ref = _pos.length - 1; 0 <= ref ? o <= ref : o >= ref; i = 0 <= ref ? ++o : --o) { p = _pos[i]; if (t <= p) { col = _colors[i]; break; } if (t >= p && i === _pos.length - 1) { col = _colors[i]; break; } if (t > p && t < _pos[i + 1]) { t = (t - p) / (_pos[i + 1] - p); col = chroma.interpolate(_colors[i], _colors[i + 1], t, _mode); break; } } } else if (type(_colors) === 'function') { col = _colors(t); } if (_useCache) { _colorCache[k] = col; } } return col; }; resetCache = function() { return _colorCache = {}; }; setColors(colors); f = function(v) { var c; c = chroma(getColor(v)); if (_out && c[_out]) { return c[_out](); } else { return c; } }; f.classes = function(classes) { var d; if (classes != null) { if (type(classes) === 'array') { _classes = classes; _domain = [classes[0], classes[classes.length - 1]]; } else { d = chroma.analyze(_domain); if (classes === 0) { _classes = [d.min, d.max]; } else { _classes = chroma.limits(d, 'e', classes); } } return f; } return _classes; }; f.domain = function(domain) { var c, d, k, len, o, ref, w; if (!arguments.length) { return _domain; } _min = domain[0]; _max = domain[domain.length - 1]; _pos = []; k = _colors.length; if (domain.length === k && _min !== _max) { for (o = 0, len = domain.length; o < len; o++) { d = domain[o]; _pos.push((d - _min) / (_max - _min)); } } else { for (c = w = 0, ref = k - 1; 0 <= ref ? w <= ref : w >= ref; c = 0 <= ref ? ++w : --w) { _pos.push(c / (k - 1)); } } _domain = [_min, _max]; return f; }; f.mode = function(_m) { if (!arguments.length) { return _mode; } _mode = _m; resetCache(); return f; }; f.range = function(colors, _pos) { setColors(colors, _pos); return f; }; f.out = function(_o) { _out = _o; return f; }; f.spread = function(val) { if (!arguments.length) { return _spread; } _spread = val; return f; }; f.correctLightness = function(v) { if (v == null) { v = true; } _correctLightness = v; resetCache(); if (_correctLightness) { tmap = function(t) { var L0, L1, L_actual, L_diff, L_ideal, max_iter, pol, t0, t1; L0 = getColor(0, true).lab()[0]; L1 = getColor(1, true).lab()[0]; pol = L0 > L1; L_actual = getColor(t, true).lab()[0]; L_ideal = L0 + (L1 - L0) * t; L_diff = L_actual - L_ideal; t0 = 0; t1 = 1; max_iter = 20; while (Math.abs(L_diff) > 1e-2 && max_iter-- > 0) { (function() { if (pol) { L_diff *= -1; } if (L_diff < 0) { t0 = t; t += (t1 - t) * 0.5; } else { t1 = t; t += (t0 - t) * 0.5; } L_actual = getColor(t, true).lab()[0]; return L_diff = L_actual - L_ideal; })(); } return t; }; } else { tmap = function(t) { return t; }; } return f; }; f.padding = function(p) { if (p != null) { if (type(p) === 'number') { p = [p, p]; } _padding = p; return f; } else { return _padding; } }; f.colors = function(numColors, out) { var dd, dm, i, o, ref, result, results, samples, w; if (arguments.length < 2) { out = 'hex'; } result = []; if (arguments.length === 0) { result = _colors.slice(0); } else if (numColors === 1) { result = [f(0.5)]; } else if (numColors > 1) { dm = _domain[0]; dd = _domain[1] - dm; result = (function() { results = []; for (var o = 0; 0 <= numColors ? o < numColors : o > numColors; 0 <= numColors ? o++ : o--){ results.push(o); } return results; }).apply(this).map(function(i) { return f(dm + i / (numColors - 1) * dd); }); } else { colors = []; samples = []; if (_classes && _classes.length > 2) { for (i = w = 1, ref = _classes.length; 1 <= ref ? w < ref : w > ref; i = 1 <= ref ? ++w : --w) { samples.push((_classes[i - 1] + _classes[i]) * 0.5); } } else { samples = _domain; } result = samples.map(function(v) { return f(v); }); } if (chroma[out]) { result = result.map(function(c) { return c[out](); }); } return result; }; f.cache = function(c) { if (c != null) { _useCache = c; return f; } else { return _useCache; } }; f.gamma = function(g) { if (g != null) { _gamma = g; return f; } else { return _gamma; } }; return f; }; if (chroma.scales == null) { chroma.scales = {}; } chroma.scales.cool = function() { return chroma.scale([chroma.hsl(180, 1, .9), chroma.hsl(250, .7, .4)]); }; chroma.scales.hot = function() { return chroma.scale(['#000', '#f00', '#ff0', '#fff'], [0, .25, .75, 1]).mode('rgb'); }; chroma.analyze = function(data, key, filter) { var add, k, len, o, r, val, visit; r = { min: Number.MAX_VALUE, max: Number.MAX_VALUE * -1, sum: 0, values: [], count: 0 }; if (filter == null) { filter = function() { return true; }; } add = function(val) { if ((val != null) && !isNaN(val)) { r.values.push(val); r.sum += val; if (val < r.min) { r.min = val; } if (val > r.max) { r.max = val; } r.count += 1; } }; visit = function(val, k) { if (filter(val, k)) { if ((key != null) && type(key) === 'function') { return add(key(val)); } else if ((key != null) && type(key) === 'string' || type(key) === 'number') { return add(val[key]); } else { return add(val); } } }; if (type(data) === 'array') { for (o = 0, len = data.length; o < len; o++) { val = data[o]; visit(val); } } else { for (k in data) { val = data[k]; visit(val, k); } } r.domain = [r.min, r.max]; r.limits = function(mode, num) { return chroma.limits(r, mode, num); }; return r; }; chroma.limits = function(data, mode, num) { var aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, assignments, best, centroids, cluster, clusterSizes, dist, i, j, kClusters, limits, max_log, min, min_log, mindist, n, nb_iters, newCentroids, o, p, pb, pr, ref, ref1, ref10, ref11, ref12, ref13, ref14, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, repeat, sum, tmpKMeansBreaks, v, value, values, w; if (mode == null) { mode = 'equal'; } if (num == null) { num = 7; } if (type(data) === 'array') { data = chroma.analyze(data); } min = data.min; max = data.max; sum = data.sum; values = data.values.sort(function(a, b) { return a - b; }); if (num === 1) { return [min, max]; } limits = []; if (mode.substr(0, 1) === 'c') { limits.push(min); limits.push(max); } if (mode.substr(0, 1) === 'e') { limits.push(min); for (i = o = 1, ref = num - 1; 1 <= ref ? o <= ref : o >= ref; i = 1 <= ref ? ++o : --o) { limits.push(min + (i / num) * (max - min)); } limits.push(max); } else if (mode.substr(0, 1) === 'l') { if (min <= 0) { throw 'Logarithmic scales are only possible for values > 0'; } min_log = Math.LOG10E * log(min); max_log = Math.LOG10E * log(max); limits.push(min); for (i = w = 1, ref1 = num - 1; 1 <= ref1 ? w <= ref1 : w >= ref1; i = 1 <= ref1 ? ++w : --w) { limits.push(pow(10, min_log + (i / num) * (max_log - min_log))); } limits.push(max); } else if (mode.substr(0, 1) === 'q') { limits.push(min); for (i = aa = 1, ref2 = num - 1; 1 <= ref2 ? aa <= ref2 : aa >= ref2; i = 1 <= ref2 ? ++aa : --aa) { p = (values.length - 1) * i / num; pb = floor(p); if (pb === p) { limits.push(values[pb]); } else { pr = p - pb; limits.push(values[pb] * (1 - pr) + values[pb + 1] * pr); } } limits.push(max); } else if (mode.substr(0, 1) === 'k') { /* implementation based on http://code.google.com/p/figue/source/browse/trunk/figue.js#336 simplified for 1-d input values */ n = values.length; assignments = new Array(n); clusterSizes = new Array(num); repeat = true; nb_iters = 0; centroids = null; centroids = []; centroids.push(min); for (i = ab = 1, ref3 = num - 1; 1 <= ref3 ? ab <= ref3 : ab >= ref3; i = 1 <= ref3 ? ++ab : --ab) { centroids.push(min + (i / num) * (max - min)); } centroids.push(max); while (repeat) { for (j = ac = 0, ref4 = num - 1; 0 <= ref4 ? ac <= ref4 : ac >= ref4; j = 0 <= ref4 ? ++ac : --ac) { clusterSizes[j] = 0; } for (i = ad = 0, ref5 = n - 1; 0 <= ref5 ? ad <= ref5 : ad >= ref5; i = 0 <= ref5 ? ++ad : --ad) { value = values[i]; mindist = Number.MAX_VALUE; for (j = ae = 0, ref6 = num - 1; 0 <= ref6 ? ae <= ref6 : ae >= ref6; j = 0 <= ref6 ? ++ae : --ae) { dist = abs(centroids[j] - value); if (dist < mindist) { mindist = dist; best = j; } } clusterSizes[best]++; assignments[i] = best; } newCentroids = new Array(num); for (j = af = 0, ref7 = num - 1; 0 <= ref7 ? af <= ref7 : af >= ref7; j = 0 <= ref7 ? ++af : --af) { newCentroids[j] = null; } for (i = ag = 0, ref8 = n - 1; 0 <= ref8 ? ag <= ref8 : ag >= ref8; i = 0 <= ref8 ? ++ag : --ag) { cluster = assignments[i]; if (newCentroids[cluster] === null) { newCentroids[cluster] = values[i]; } else { newCentroids[cluster] += values[i]; } } for (j = ah = 0, ref9 = num - 1; 0 <= ref9 ? ah <= ref9 : ah >= ref9; j = 0 <= ref9 ? ++ah : --ah) { newCentroids[j] *= 1 / clusterSizes[j]; } repeat = false; for (j = ai = 0, ref10 = num - 1; 0 <= ref10 ? ai <= ref10 : ai >= ref10; j = 0 <= ref10 ? ++ai : --ai) { if (newCentroids[j] !== centroids[i]) { repeat = true; break; } } centroids = newCentroids; nb_iters++; if (nb_iters > 200) { repeat = false; } } kClusters = {}; for (j = aj = 0, ref11 = num - 1; 0 <= ref11 ? aj <= ref11 : aj >= ref11; j = 0 <= ref11 ? ++aj : --aj) { kClusters[j] = []; } for (i = ak = 0, ref12 = n - 1; 0 <= ref12 ? ak <= ref12 : ak >= ref12; i = 0 <= ref12 ? ++ak : --ak) { cluster = assignments[i]; kClusters[cluster].push(values[i]); } tmpKMeansBreaks = []; for (j = al = 0, ref13 = num - 1; 0 <= ref13 ? al <= ref13 : al >= ref13; j = 0 <= ref13 ? ++al : --al) { tmpKMeansBreaks.push(kClusters[j][0]); tmpKMeansBreaks.push(kClusters[j][kClusters[j].length - 1]); } tmpKMeansBreaks = tmpKMeansBreaks.sort(function(a, b) { return a - b; }); limits.push(tmpKMeansBreaks[0]); for (i = am = 1, ref14 = tmpKMeansBreaks.length - 1; am <= ref14; i = am += 2) { v = tmpKMeansBreaks[i]; if (!isNaN(v) && limits.indexOf(v) === -1) { limits.push(v); } } } return limits; }; hsi2rgb = function(h, s, i) { /* borrowed from here: http://hummer.stanford.edu/museinfo/doc/examples/humdrum/keyscape2/hsi2rgb.cpp */ var args, b, g, r; args = unpack(arguments); h = args[0], s = args[1], i = args[2]; if (isNaN(h)) { h = 0; } h /= 360; if (h < 1 / 3) { b = (1 - s) / 3; r = (1 + s * cos(TWOPI * h) / cos(PITHIRD - TWOPI * h)) / 3; g = 1 - (b + r); } else if (h < 2 / 3) { h -= 1 / 3; r = (1 - s) / 3; g = (1 + s * cos(TWOPI * h) / cos(PITHIRD - TWOPI * h)) / 3; b = 1 - (r + g); } else { h -= 2 / 3; g = (1 - s) / 3; b = (1 + s * cos(TWOPI * h) / cos(PITHIRD - TWOPI * h)) / 3; r = 1 - (g + b); } r = limit(i * r * 3); g = limit(i * g * 3); b = limit(i * b * 3); return [r * 255, g * 255, b * 255, args.length > 3 ? args[3] : 1]; }; rgb2hsi = function() { /* borrowed from here: http://hummer.stanford.edu/museinfo/doc/examples/humdrum/keyscape2/rgb2hsi.cpp */ var b, g, h, i, min, r, ref, s; ref = unpack(arguments), r = ref[0], g = ref[1], b = ref[2]; TWOPI = Math.PI * 2; r /= 255; g /= 255; b /= 255; min = Math.min(r, g, b); i = (r + g + b) / 3; s = 1 - min / i; if (s === 0) { h = 0; } else { h = ((r - g) + (r - b)) / 2; h /= Math.sqrt((r - g) * (r - g) + (r - b) * (g - b)); h = Math.acos(h); if (b > g) { h = TWOPI - h; } h /= TWOPI; } return [h * 360, s, i]; }; chroma.hsi = function() { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(Color, slice.call(arguments).concat(['hsi']), function(){}); }; _input.hsi = hsi2rgb; Color.prototype.hsi = function() { return rgb2hsi(this._rgb); }; interpolate_hsx = function(col1, col2, f, m) { var dh, hue, hue0, hue1, lbv, lbv0, lbv1, res, sat, sat0, sat1, xyz0, xyz1; if (m === 'hsl') { xyz0 = col1.hsl(); xyz1 = col2.hsl(); } else if (m === 'hsv') { xyz0 = col1.hsv(); xyz1 = col2.hsv(); } else if (m === 'hcg') { xyz0 = col1.hcg(); xyz1 = col2.hcg(); } else if (m === 'hsi') { xyz0 = col1.hsi(); xyz1 = col2.hsi(); } else if (m === 'lch' || m === 'hcl') { m = 'hcl'; xyz0 = col1.hcl(); xyz1 = col2.hcl(); } if (m.substr(0, 1) === 'h') { hue0 = xyz0[0], sat0 = xyz0[1], lbv0 = xyz0[2]; hue1 = xyz1[0], sat1 = xyz1[1], lbv1 = xyz1[2]; } if (!isNaN(hue0) && !isNaN(hue1)) { if (hue1 > hue0 && hue1 - hue0 > 180) { dh = hue1 - (hue0 + 360); } else if (hue1 < hue0 && hue0 - hue1 > 180) { dh = hue1 + 360 - hue0; } else { dh = hue1 - hue0; } hue = hue0 + f * dh; } else if (!isNaN(hue0)) { hue = hue0; if ((lbv1 === 1 || lbv1 === 0) && m !== 'hsv') { sat = sat0; } } else if (!isNaN(hue1)) { hue = hue1; if ((lbv0 === 1 || lbv0 === 0) && m !== 'hsv') { sat = sat1; } } else { hue = Number.NaN; } if (sat == null) { sat = sat0 + f * (sat1 - sat0); } lbv = lbv0 + f * (lbv1 - lbv0); return res = chroma[m](hue, sat, lbv); }; _interpolators = _interpolators.concat((function() { var len, o, ref, results; ref = ['hsv', 'hsl', 'hsi', 'hcl', 'lch', 'hcg']; results = []; for (o = 0, len = ref.length; o < len; o++) { m = ref[o]; results.push([m, interpolate_hsx]); } return results; })()); interpolate_num = function(col1, col2, f, m) { var n1, n2; n1 = col1.num(); n2 = col2.num(); return chroma.num(n1 + (n2 - n1) * f, 'num'); }; _interpolators.push(['num', interpolate_num]); interpolate_lab = function(col1, col2, f, m) { var res, xyz0, xyz1; xyz0 = col1.lab(); xyz1 = col2.lab(); return res = new Color(xyz0[0] + f * (xyz1[0] - xyz0[0]), xyz0[1] + f * (xyz1[1] - xyz0[1]), xyz0[2] + f * (xyz1[2] - xyz0[2]), m); }; _interpolators.push(['lab', interpolate_lab]); }).call(this);