Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List unique colors in an HTML Canvas

Tags:

html

canvas

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

like image 318
lostsource Avatar asked Nov 06 '12 00:11

lostsource


1 Answers

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.

like image 143
Juan Cortés Avatar answered Sep 22 '22 03:09

Juan Cortés