Is there an efficient way to get a list of colors of what is currently drawn in an HTML Canvas?
I guess the correct term would be a Color Palette of the current composite
Assume you have an html document like the following:
<canvas id="example" width="500" height="300"></canvas>
<ul id="list">
<h3>Click the canvas to extract colors</h3>
</ul>
I have created a fiddle in which you have a ready made canvas with some shapes and colors that we will be processing when we click on it. I'm not creating a color picker for you, just listing as that was the original answer and should serve as the means to achieve the second part of it.
Here's the fiddle
The function that extracts the colors an lists them is the following, I'm avoiding copying all the canvas drawing stuff since it just serves as the example and isn't generic enough.
var colorList = []; //This will hold all our colors
function getColors(){
var canvas = document.getElementById('example');
var context = canvas.getContext('2d');
var imageWidth = canvas.width;
var imageHeight = canvas.height;
var imageData = context.getImageData(0, 0, imageWidth, imageHeight);
var data = imageData.data;
// quickly iterate over all pixels
for(var i = 0, n = data.length; i < n; i += 4) {
var r = data[i];
var g = data[i + 1];
var b = data[i + 2];
//If you need the alpha value it's data[i + 3]
var hex = rgb2hex("rgb("+r+","+g+","+b+")");
if ($.inArray(hex, colorList) == -1){
$('#list').append("<li>"+hex+"</li>");
colorList.push(hex);
}
}
}
This will produce a result containing a seemingly unordered list of hex values that represent the order in which they appear in your image (hence the 'seemingly'), if you want a color picker however you may want to consider the use of colorList.sort();
which will order the array into a black-to-white fashion.
Note that I'm using the rgb2hex
function to convert the values returned to the hex format I'm assuming your wanting, if you're ok with rgb feel free to not use it, the function is the following:
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
And the source is this, as I stated as a comment in the code, you could easily extract the alpha channel too if you needed to but I went for the most generic scenario (and simplest) that I could think of.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With