144 lines
3.3 KiB
JavaScript
Executable File
144 lines
3.3 KiB
JavaScript
Executable File
/*
|
|
* Ben Postlethwaite
|
|
* January 2013
|
|
* License MIT
|
|
*/
|
|
'use strict';
|
|
|
|
var colorScale = require('./colorScale');
|
|
var lerp = require('lerp')
|
|
|
|
module.exports = createColormap;
|
|
|
|
function createColormap (spec) {
|
|
/*
|
|
* Default Options
|
|
*/
|
|
var indicies, fromrgba, torgba,
|
|
nsteps, cmap, colormap, format,
|
|
nshades, colors, alpha, i;
|
|
|
|
if ( !spec ) spec = {};
|
|
|
|
nshades = (spec.nshades || 72) - 1;
|
|
format = spec.format || 'hex';
|
|
|
|
colormap = spec.colormap;
|
|
if (!colormap) colormap = 'jet';
|
|
|
|
if (typeof colormap === 'string') {
|
|
colormap = colormap.toLowerCase();
|
|
|
|
if (!colorScale[colormap]) {
|
|
throw Error(colormap + ' not a supported colorscale');
|
|
}
|
|
|
|
cmap = colorScale[colormap];
|
|
|
|
} else if (Array.isArray(colormap)) {
|
|
cmap = colormap.slice();
|
|
|
|
} else {
|
|
throw Error('unsupported colormap option', colormap);
|
|
}
|
|
|
|
if (cmap.length > nshades + 1) {
|
|
throw new Error(
|
|
colormap+' map requires nshades to be at least size '+cmap.length
|
|
);
|
|
}
|
|
|
|
if (!Array.isArray(spec.alpha)) {
|
|
|
|
if (typeof spec.alpha === 'number') {
|
|
alpha = [spec.alpha, spec.alpha];
|
|
|
|
} else {
|
|
alpha = [1, 1];
|
|
}
|
|
|
|
} else if (spec.alpha.length !== 2) {
|
|
alpha = [1, 1];
|
|
|
|
} else {
|
|
alpha = spec.alpha.slice();
|
|
}
|
|
|
|
// map index points from 0..1 to 0..n-1
|
|
indicies = cmap.map(function(c) {
|
|
return Math.round(c.index * nshades);
|
|
});
|
|
|
|
// Add alpha channel to the map
|
|
alpha[0] = Math.min(Math.max(alpha[0], 0), 1);
|
|
alpha[1] = Math.min(Math.max(alpha[1], 0), 1);
|
|
|
|
var steps = cmap.map(function(c, i) {
|
|
var index = cmap[i].index
|
|
|
|
var rgba = cmap[i].rgb.slice();
|
|
|
|
// if user supplies their own map use it
|
|
if (rgba.length === 4 && rgba[3] >= 0 && rgba[3] <= 1) {
|
|
return rgba
|
|
}
|
|
rgba[3] = alpha[0] + (alpha[1] - alpha[0])*index;
|
|
|
|
return rgba
|
|
})
|
|
|
|
|
|
/*
|
|
* map increasing linear values between indicies to
|
|
* linear steps in colorvalues
|
|
*/
|
|
var colors = []
|
|
for (i = 0; i < indicies.length-1; ++i) {
|
|
nsteps = indicies[i+1] - indicies[i];
|
|
fromrgba = steps[i];
|
|
torgba = steps[i+1];
|
|
|
|
for (var j = 0; j < nsteps; j++) {
|
|
var amt = j / nsteps
|
|
colors.push([
|
|
Math.round(lerp(fromrgba[0], torgba[0], amt)),
|
|
Math.round(lerp(fromrgba[1], torgba[1], amt)),
|
|
Math.round(lerp(fromrgba[2], torgba[2], amt)),
|
|
lerp(fromrgba[3], torgba[3], amt)
|
|
])
|
|
}
|
|
}
|
|
|
|
//add 1 step as last value
|
|
colors.push(cmap[cmap.length - 1].rgb.concat(alpha[1]))
|
|
|
|
if (format === 'hex') colors = colors.map( rgb2hex );
|
|
else if (format === 'rgbaString') colors = colors.map( rgbaStr );
|
|
else if (format === 'float') colors = colors.map( rgb2float );
|
|
|
|
return colors;
|
|
};
|
|
|
|
function rgb2float (rgba) {
|
|
return [
|
|
rgba[0] / 255,
|
|
rgba[1] / 255,
|
|
rgba[2] / 255,
|
|
rgba[3]
|
|
]
|
|
}
|
|
|
|
function rgb2hex (rgba) {
|
|
var dig, hex = '#';
|
|
for (var i = 0; i < 3; ++i) {
|
|
dig = rgba[i];
|
|
dig = dig.toString(16);
|
|
hex += ('00' + dig).substr( dig.length );
|
|
}
|
|
return hex;
|
|
}
|
|
|
|
function rgbaStr (rgba) {
|
|
return 'rgba(' + rgba.join(',') + ')';
|
|
}
|