Last active
March 18, 2016 21:33
-
-
Save hapticdata/ffd6624af98db361025b to your computer and use it in GitHub Desktop.
extract the unique colors out of an image
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = uniqueColors; | |
var _canvas; | |
/** | |
* Collect all of the unique colors within an image, | |
* all pixel values are returned as [ red, green, blue, alpha ] between 0 - 255 | |
* @param {Image|HTMLCanvasElement} image | |
* @param {Number} [x] to start sampling | |
* @param {Number} [y] to start sampling | |
* @param {Number} [width] to crop sampling | |
* @param {Number} [height] to crop sampling | |
* @param {Boolean} [ignoreAlphaZero] dismiss color values that are completely transparent | |
* @param {Number} [tolerance] dismiss a color if its difference to an existing color is under this tolerance | |
* @param {Array} [arr] provide an array to continue filling | |
* @return {Array<Array[4]>} | |
*/ | |
function uniqueColors(image, x, y, width, height, ignoreAlphaZero, tolerance, arr){ | |
x = x || 0; | |
y = y || 0; | |
width = width || image.naturalWidth; | |
height = height || image.naturalHeight; | |
ignoreAlphaZero = !!ignoreAlphaZero; | |
var checkTolerance = typeof tolerance === 'number'; | |
arr = arr || []; | |
var canvas, | |
ctx, | |
colorKey, | |
colorMap = {}; | |
if(image.getContext){ | |
canvas = image; | |
ctx = canvas.getContext('2d'); | |
} else { | |
//we can reuse the same canvas always | |
canvas = _canvas || (_canvas = document.createElement('canvas')); | |
canvas.width = image.width; | |
canvas.height = image.height; | |
ctx = canvas.getContext('2d'); | |
ctx.drawImage(image, 0, 0, image.naturalWidth, image.naturalHeight); | |
} | |
//now we have a canvas with the image painted on it | |
var imgData, | |
data, | |
i = 0, | |
r, | |
g, | |
b, | |
a; | |
try { | |
imgData = ctx.getImageData(x, y, width, height); | |
data = imgData.data; | |
} catch(e){ | |
//if an error occurs, such as from trying to illegally use a | |
//cross-domain resource, dispose of the canvas to avoid future issues | |
_canvas = null; | |
throw e; | |
} | |
for(i=0; i<data.length; i+=4){ | |
a = data[i+3]; | |
if(a === 0 && ignoreAlphaZero){ | |
continue; | |
} | |
r = data[i]; | |
g = data[i+1]; | |
b = data[i+2]; | |
colorKey = r+'|'+g+'|'+b+'|'+a; | |
var px = [ r, g, b, a ]; | |
if(!colorMap[colorKey]){ | |
colorMap[colorKey] = px; | |
if(!checkTolerance || diffAll(arr, px, tolerance)){ | |
arr.push(px); | |
} | |
} | |
} | |
return arr; | |
} | |
function difference(a, b) { | |
var diff = 0; | |
for(var i=0; i<a.length; i++){ | |
diff += Math.abs(a[i] - b[i]); | |
} | |
return diff; | |
} | |
function diffAll(arr, a, tolerance){ | |
for(var i=0; i<arr.length; i++){ | |
if(difference(a, arr[i]) < tolerance){ | |
return false; | |
} | |
} | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment