Skip to content

Commit

Permalink
Merge pull request #14 from benjie/raw-lab
Browse files Browse the repository at this point in the history
Raw Lab colorspace access (for higher performance)
  • Loading branch information
markusn authored Apr 20, 2017
2 parents 835909c + 6b60fa7 commit 28174b3
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 7 deletions.
21 changes: 16 additions & 5 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ var palette = require('./palette');

var color = module.exports = {};

color.diff = diff.ciede2000;
color.rgb_to_lab = convert.rgb_to_lab;
color.rgba_to_lab = convert.rgba_to_lab;
color.map_palette = palette.map_palette;
color.palette_map_key = palette.palette_map_key;
color.diff = diff.ciede2000;
color.rgb_to_lab = convert.rgb_to_lab;
color.rgba_to_lab = convert.rgba_to_lab;
color.map_palette = palette.map_palette;
color.palette_map_key = palette.palette_map_key;
color.map_palette_lab = palette.map_palette_lab;
color.lab_palette_map_key = palette.lab_palette_map_key;
color.match_palette_lab = palette.match_palette_lab;

color.closest = function(target, relative, bc) {
var key = color.palette_map_key(target);
Expand All @@ -27,3 +30,11 @@ color.furthest = function(target, relative, bc) {

return result[key];
};

color.closest_lab = function(target, relative) {
return color.match_palette_lab(target, relative, false);
};

color.furthest_lab = function(target, relative) {
return color.match_palette_lab(target, relative, true);
};
65 changes: 63 additions & 2 deletions lib/palette.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@
/**
* EXPORTS
*/
exports.map_palette = map_palette;
exports.palette_map_key = palette_map_key;
exports.map_palette = map_palette;
exports.map_palette_lab = map_palette_lab;
exports.match_palette_lab = match_palette_lab;
exports.palette_map_key = palette_map_key;
exports.lab_palette_map_key = lab_palette_map_key;

/**
* IMPORTS
Expand All @@ -56,6 +59,16 @@ function palette_map_key(c)
return s;
}

/**
* Returns the hash key used for a {labcolor} in a {labpalettemap}
* @param {labcolor} c should have fields L,a,b
* @return {string}
*/
function lab_palette_map_key(c)
{
return "L" + c.L + "a" + c.a + "b" + c.b;
}

/**
* Returns a mapping from each color in a to the closest/farthest color in b
* @param [{rgbcolor}] a each element should have fields R,G,B
Expand Down Expand Up @@ -97,6 +110,54 @@ function map_palette(a, b, type, bc)
return c;
}

/**
* Returns the closest (or furthest) color to target_color in palette, operating in the L,a,b colorspace for performance
* @param {labcolor} target_color should have fields L,a,b
* @param [{labcolor}] palette each element should have fields L,a,b
* @param 'find_furthest' should be falsy to find the closest color
* @return {labcolor}
*/
function match_palette_lab(target_color, palette, find_furthest)
{
var color2, current_color_diff;
var best_color = palette[0];
var best_color_diff = ciede2000(target_color, best_color);
for (var idx2 = 1, l = palette.length; idx2 < l; idx2 += 1)
{
color2 = palette[idx2];
current_color_diff = ciede2000(target_color, color2);

if(
(!find_furthest && (current_color_diff < best_color_diff)) ||
(find_furthest && (current_color_diff > best_color_diff))
)
{
best_color = color2;
best_color_diff = current_color_diff;
}
}
return best_color;
}

/**
* Returns a mapping from each color in a to the closest color in b
* @param [{labcolor}] a each element should have fields L,a,b
* @param [{labcolor}] b each element should have fields L,a,b
* @param 'type' should be the string 'closest' or 'furthest'
* @return {labpalettemap}
*/
function map_palette_lab(a, b, type)
{
var c = {};
var find_furthest = type === 'furthest';
for (var idx1 = 0; idx1 < a.length; idx1 += 1)
{
var color1 = a[idx1];
c[lab_palette_map_key(color1)] = match_palette_lab(color1, b, find_furthest);
}
return c;
}

/**
* INTERNAL FUNCTIONS
*/
Expand Down
103 changes: 103 additions & 0 deletions test/palette.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
*/
var assert = require('assert');
var color_palette = require('../lib/palette');
var color_convert = require('../lib/convert');

/**
* CONSTANTS
Expand All @@ -42,9 +43,20 @@ var navy = {'R':0 , 'G':0 ,'B':128};
var blue = {'R':0 , 'G':0 ,'B':255};
var yellow = {'R':255 , 'G':255 ,'B':0};
var gold = {'R':255 , 'G':215 ,'B':0};

var white_lab = color_convert.rgb_to_lab(white);
var black_lab = color_convert.rgb_to_lab(black);
var navy_lab = color_convert.rgb_to_lab(navy);
var blue_lab = color_convert.rgb_to_lab(blue);
var yellow_lab = color_convert.rgb_to_lab(yellow);
var gold_lab = color_convert.rgb_to_lab(gold);

var colors1 = [white, black, navy, blue, yellow, gold]
var colors1_lab = [white_lab, black_lab, navy_lab, blue_lab, yellow_lab, gold_lab]
var colors2 = [white, black, blue, gold]
var colors2_lab = [white_lab, black_lab, blue_lab, gold_lab]
var colors3 = [white, black, yellow, blue]
var colors3_lab = [white_lab, black_lab, yellow_lab, blue_lab]

var white_a = {'R':255 , 'G':255 ,'B':255, 'A': 1.0};
var black_a = {'R':0 , 'G':0 ,'B':0, 'A': 1.0};
Expand All @@ -54,6 +66,14 @@ var yellow_a = {'R':255 , 'G':255 ,'B':0, 'A': 1.0};
var gold_a = {'R':255 , 'G':215 ,'B':0, 'A': 1.0};
var colors1_a = [white_a, black_a, navy_a, blue_a, yellow_a, gold_a]

var white_a_lab = color_convert.rgb_to_lab(white_a);
var black_a_lab = color_convert.rgb_to_lab(black_a);
var navy_a_lab = color_convert.rgb_to_lab(navy_a);
var blue_a_lab = color_convert.rgb_to_lab(blue_a);
var yellow_a_lab = color_convert.rgb_to_lab(yellow_a);
var gold_a_lab = color_convert.rgb_to_lab(gold_a);
var colors1_a_lab = [white_a_lab, black_a_lab, navy_a_lab, blue_a_lab, yellow_a_lab, gold_a_lab]

/**
* TESTS
*/
Expand Down Expand Up @@ -112,6 +132,89 @@ describe('palette', function(){
});

})

describe('#map_palette_lab()', function (){
it('should map all colors to themselves when possible #1',
function(){
var expected1_1 = {};
expected1_1[color_palette.lab_palette_map_key(white_lab)] = white_lab;
expected1_1[color_palette.lab_palette_map_key(black_lab)] = black_lab;
expected1_1[color_palette.lab_palette_map_key(navy_lab)] = navy_lab;
expected1_1[color_palette.lab_palette_map_key(blue_lab)] = blue_lab;
expected1_1[color_palette.lab_palette_map_key(yellow_lab)] = yellow_lab;
expected1_1[color_palette.lab_palette_map_key(gold_lab)] = gold_lab;
assert.deepEqual(expected1_1,
color_palette.map_palette_lab(colors1_lab, colors1_lab));
});
it('should map all colors to themselves when possible #2',
function(){
var expected1_2 = {};
expected1_2[color_palette.lab_palette_map_key(white_a_lab)] = white_a_lab;
expected1_2[color_palette.lab_palette_map_key(black_a_lab)] = black_a_lab;
expected1_2[color_palette.lab_palette_map_key(navy_a_lab)] = navy_a_lab;
expected1_2[color_palette.lab_palette_map_key(blue_a_lab)] = blue_a_lab;
expected1_2[color_palette.lab_palette_map_key(yellow_a_lab)] = yellow_a_lab;
expected1_2[color_palette.lab_palette_map_key(gold_a_lab)] = gold_a_lab;
assert.deepEqual(expected1_2,
color_palette.map_palette_lab(colors1_a_lab, colors1_a_lab));
});
it('should map navy->blue and yellow->gold when navy and yellow are missing',
function(){
var expected2 = {};
expected2[color_palette.lab_palette_map_key(white_lab)] = white_lab;
expected2[color_palette.lab_palette_map_key(black_lab)] = black_lab;
expected2[color_palette.lab_palette_map_key(navy_lab)] = blue_lab;
expected2[color_palette.lab_palette_map_key(blue_lab)] = blue_lab;
expected2[color_palette.lab_palette_map_key(yellow_lab)] = gold_lab;
expected2[color_palette.lab_palette_map_key(gold_lab)] = gold_lab;
assert.deepEqual(expected2,
color_palette.map_palette_lab(colors1_lab, colors2_lab));
});
it('should map white->black & black,navy,blue->yellow & yellow,gold->blue',
function(){
var expected3 = {};
expected3[color_palette.lab_palette_map_key(white_lab)] = black_lab;
expected3[color_palette.lab_palette_map_key(black_lab)] = yellow_lab;
expected3[color_palette.lab_palette_map_key(navy_lab)] = yellow_lab;
expected3[color_palette.lab_palette_map_key(blue_lab)] = yellow_lab;
expected3[color_palette.lab_palette_map_key(yellow_lab)] = blue_lab;
expected3[color_palette.lab_palette_map_key(gold_lab)] = blue_lab;
assert.deepEqual(expected3,
color_palette.map_palette_lab(colors1_lab,
colors3_lab,
'furthest'));
});

})

describe('#match_palette_lab()', function (){
it('should match map_palette results for closest',
function() {
assert.deepEqual(color_palette.match_palette_lab(white_lab, colors1_lab), white_lab);
assert.deepEqual(color_palette.match_palette_lab(black_lab, colors1_lab), black_lab);
assert.deepEqual(color_palette.match_palette_lab(navy_lab, colors1_lab), navy_lab);
assert.deepEqual(color_palette.match_palette_lab(blue_lab, colors1_lab), blue_lab);
assert.deepEqual(color_palette.match_palette_lab(yellow_lab, colors1_lab), yellow_lab);
assert.deepEqual(color_palette.match_palette_lab(gold_lab, colors1_lab), gold_lab);

assert.deepEqual(color_palette.match_palette_lab(white_lab, colors2_lab), white_lab);
assert.deepEqual(color_palette.match_palette_lab(black_lab, colors2_lab), black_lab);
assert.deepEqual(color_palette.match_palette_lab(navy_lab, colors2_lab), blue_lab);
assert.deepEqual(color_palette.match_palette_lab(blue_lab, colors2_lab), blue_lab);
assert.deepEqual(color_palette.match_palette_lab(yellow_lab, colors2_lab), gold_lab);
assert.deepEqual(color_palette.match_palette_lab(gold_lab, colors2_lab), gold_lab);
});

it('should match map_palette results for furthest',
function() {
assert.deepEqual(color_palette.match_palette_lab(white_lab, colors3_lab, true), black_lab);
assert.deepEqual(color_palette.match_palette_lab(black_lab, colors3_lab, true), yellow_lab);
assert.deepEqual(color_palette.match_palette_lab(navy_lab, colors3_lab, true), yellow_lab);
assert.deepEqual(color_palette.match_palette_lab(blue_lab, colors3_lab, true), yellow_lab);
assert.deepEqual(color_palette.match_palette_lab(yellow_lab, colors3_lab, true), blue_lab);
assert.deepEqual(color_palette.match_palette_lab(gold_lab, colors3_lab, true), blue_lab);
});
})
});

// Local Variables:
Expand Down

0 comments on commit 28174b3

Please sign in to comment.