Skip to content

Commit

Permalink
Refactor inner logic, avoid doubly colors
Browse files Browse the repository at this point in the history
  • Loading branch information
dy committed Jul 24, 2017
1 parent dc1436d commit ba79a78
Show file tree
Hide file tree
Showing 35 changed files with 100 additions and 93 deletions.
40 changes: 26 additions & 14 deletions README.md
@@ -1,22 +1,34 @@
# Easy Javascript Colormaps

[![Build Status](https://travis-ci.org/bpostlethwaite/colormap.png)](https://travis-ci.org/bpostlethwaite/colormap)
# colormap [![Build Status](https://travis-ci.org/bpostlethwaite/colormap.png)](https://travis-ci.org/bpostlethwaite/colormap)

![all colormap output](./example/colormaps.png)

## Simple example
## Usage

```javascript
var colormap = require('colormap')
options = {
colormap: 'jet', // pick a builtin colormap or pass your own
nshades: 72, // how many divisions
format: 'hex', // "hex" or "rgb" or "rgbaString"
alpha: 1 // set an alpha value or a linear alpha mapping [start, end]
}
cg = colormap(options)
[![npm install colormap](https://nodei.co/npm/colormap.png?mini=true)](https://npmjs.org/package/colormap/)

```js
let colormap = require('colormap')

let colors = colormap({
colormap: 'jet'
nshades: 72,
format: 'hex',
alpha: 1
})
```

## API

### colormap(options)

| Property | Default | Meaning |
|---|---|---|
| `colormap` | `'jet'` | |
| `nshades` | `72` | |
| `format` | `'hex'` | |
| `alpha` | `1` | |
| `interpolate` | `'smoothstep'` | `smoothstep` or `linear` interpolation between steps. |

where leaving `options = {}` or `undefined` results in the defaults given above. There is a minimum number of `nshades` divisions you can select since the algorithms for each colormap have different requirements. `colormap` throws an error if there are too few divisions for the chosen colormap and gives the minimum number required. You should be safe with `n > 10` for all the colormaps, though some require much less (much simpler to implemenent).

## Options
Expand Down Expand Up @@ -104,4 +116,4 @@ Then just [browserify](https://github.com/substack/node-browserify) it and throw

## Credits

Color maps are inspired by [matplotlib](https://github.com/d3/d3-scale#sequential-color-scales) color scales, [cmocean](https://github.com/matplotlib/cmocean) oceanographic colormaps, [cosine gradients](https://github.com/thi-ng/color/blob/master/src/gradients.org) and others. Thanks to authors of these libs for their invaluable work.
Color maps are inspired by [matplotlib](https://github.com/d3/d3-scale#sequential-color-scales) color scales, [cmocean](https://github.com/matplotlib/cmocean) oceanographic colormaps, [cosine gradients](https://github.com/thi-ng/color/blob/master/src/gradients.org) and others. Thanks to authors of these libs for their invaluable work.
File renamed without changes.
File renamed without changes
9 changes: 6 additions & 3 deletions example/example.js → example.js
@@ -1,6 +1,6 @@
var cmap = require('./..'),
canvas = document.getElementById('canvas'),
img = document.getElementById('background'),
var cmap = require('.'),
img = document.body.appendChild(document.createElement('img')),
canvas = document.body.appendChild(document.createElement('canvas')),
c = canvas.getContext('2d'),
n = 48,
colormaps = [
Expand All @@ -15,12 +15,15 @@ var cmap = require('./..'),
'cubehelix'
];

img.width = 480;
img.onload = run;
img.src = './night.jpg'

function drawColorMaps (colormap, name, height) {
/*
* Build up the color ranges and add text
*/

for (var j = 0; j < n; j++) {
c.fillStyle = colormap[j]; // start ind at index 0
c.fillRect(j*10, height, 10, 40);
Expand Down
16 changes: 0 additions & 16 deletions example/example.html

This file was deleted.

65 changes: 34 additions & 31 deletions index.js
Expand Up @@ -7,7 +7,10 @@

var at = require('arraytools');
var clone = require('clone');
var colorScale = require('./colorScales');
var colorScale = require('./colormap');
var isPlainObject = require('is-plain-obj');
var clamp = require('clamp');
var lerp = require('lerp')

module.exports = createColormap;

Expand All @@ -23,7 +26,7 @@ function createColormap (spec) {
b = [],
a = [];

if ( !at.isPlainObject(spec) ) spec = {};
if ( !isPlainObject(spec) ) spec = {};

nshades = spec.nshades || 72;
format = spec.format || 'hex';
Expand All @@ -38,7 +41,7 @@ function createColormap (spec) {
throw Error(colormap + ' not a supported colorscale');
}

cmap = clone(colorScale[colormap]);
cmap = colorScale[colormap];

} else if (Array.isArray(colormap)) {
cmap = clone(colormap);
Expand Down Expand Up @@ -69,50 +72,50 @@ function createColormap (spec) {
alpha = clone(spec.alpha);
}

/*
* map index points from 0->1 to 0 -> n-1
*/
// 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
*/
if (alpha[0] < 0) alpha[0] = 0;
if (alpha[1] < 0) alpha[0] = 0;
if (alpha[0] > 1) alpha[0] = 1;
if (alpha[1] > 1) alpha[0] = 1;
// Add alpha channel to the map
alpha[0] = clamp(alpha[0], 0, 1);
alpha[1] = clamp(alpha[1], 0, 1);

for (i = 0; i < indicies.length; ++i) {
index = cmap[i].index;
rgba = cmap[i].rgb;
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) continue;
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 = cmap[i].rgb;
torgba = cmap[i+1].rgb;
r = r.concat(at.linspace(fromrgba[0], torgba[0], nsteps ) );
g = g.concat(at.linspace(fromrgba[1], torgba[1], nsteps ) );
b = b.concat(at.linspace(fromrgba[2], torgba[2], nsteps ) );
a = a.concat(at.linspace(fromrgba[3], torgba[3], nsteps ) );
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)
])
}
}

r = r.map( Math.round );
g = g.map( Math.round );
b = b.map( Math.round );

colors = at.zip(r, g, b, a);

if (format === 'hex') colors = colors.map( rgb2hex );
if (format === 'rgbaString') colors = colors.map( rgbaStr );

Expand Down
File renamed without changes.
File renamed without changes
5 changes: 4 additions & 1 deletion package.json
Expand Up @@ -5,7 +5,10 @@
"author": "bpostlethwaite",
"dependencies": {
"arraytools": "^1.1.2",
"clone": "^1.0.2"
"clamp": "^1.0.1",
"clone": "^1.0.2",
"is-plain-obj": "^1.1.0",
"lerp": "^1.0.3"
},
"devDependencies": {
"color-space": "^1.14.3",
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
37 changes: 30 additions & 7 deletions test/rgba-colorscale-test.js → test.js
@@ -1,6 +1,25 @@
var colormap = require('../.'),
test = require('tape').test;


test('is object - object', function(t) {
t.plan(1);
var n = 15,
cg,
check = true;

// Display all the colormaps
var cms = ['jet', 'hsv' ,'hot', 'cool', 'spring', 'summer', 'autumn',
'winter', 'greys', 'bone', 'copper'];

for (var i = 0; i < cms.length; i++) {
cg = cmap({'colormap': cms[i], 'nshades': n });
check = check & (cg.length == n);
}

t.ok(check);
});

test('alpha config creates rgba arrays with correct alpha', function (t) {

var alpha = 0.5;
Expand Down Expand Up @@ -45,21 +64,25 @@ test('user colormap alpha values override alpha config', function (t) {
t.end();
});

test('alphamap values are computed independently between runs', function(t) {
var blueRed = colormap({
colormap: "bluered",
format: "rgba",
alpha: [0, 1]
});
test.only('alphamap values are computed independently between runs', function(t) {
// var blueRed = colormap({
// colormap: "bluered",
// format: "rgba",
// alpha: [0, 1]
// });

var blueRed2 = colormap({
colormap: "bluered",
format: "rgba",
alpha: [0, 0.5]
});

t.same(blueRed[blueRed.length - 1], [ 255, 0, 0, 1 ]);
// t.same(blueRed[blueRed.length - 1], [ 255, 0, 0, 1 ]);
t.same(blueRed2[blueRed2.length - 1], [ 255, 0, 0, 0.5 ]);

t.end();
});

test('repeating values', function(t) {
t.end()
});
21 changes: 0 additions & 21 deletions test/output-length-test.js

This file was deleted.

0 comments on commit ba79a78

Please sign in to comment.