aurel
aurel

Reputation: 3122

Is there a js library can can generate a color palette from an image?

Something that might do something like

<img  class="image" ... />

$(".image").get_colors()

I know there are few websites where you can upload your image and it would generate the color for you but I want something to put on my website

Something like this where you see the colors generated from the screenshot and can search by colors. I tried to check the source code but I could not see any reference to a js library.

I need this feature to work with js if possible.

EDIT: The image would be on the page already; I just need to generate its color, so I don't want the uploading features.

Thanks.

Upvotes: 6

Views: 5295

Answers (3)

wle8300
wle8300

Reputation: 2749

Have you seen this project on Github?

http://lokeshdhakar.com/projects/color-thief/

It's a javascript solution. (It depends on two additional libraries: jquery, quantize.js).

var colorThief = new ColorThief();
colorThief.getPalette(sourceImage, 8);
getPalette(sourceImage[, colorCount, quality])

Which will return an array, like so: [ [num, num, num], [num, num, num], ... ]

Upvotes: 2

Prusse
Prusse

Reputation: 4315

I did write just for fun. It is a jquery plugin, if you don't use it you can read it for some pointers. If there is some error during the call to get_colors a array is set in the return value to hold the errors, it returns an array of objects, these objects are a histogram of a image(one item in the array for every selected element).

(function($, window, document, undefined){
    var canvas = document.createElement('canvas');
    if (canvas && canvas.getContext){
        $.fn.get_colors = function(){
            var rv = [];
            this.each(function(){
                var tagname = this.tagName.toLowerCase();
                if ((tagname === 'img') || (tagname === 'canvas') || (tagname === 'video')){
                    //something bad can happend when drawing the image
                    try{
                        var w = this.getAttribute('width');
                        var h = this.getAttribute('height');
                        canvas.setAttribute('width', w);  
                        canvas.setAttribute('height', h); 
                        var ctxt = canvas.getContext('2d');
                        if (ctxt){
                            ctxt.drawImage(this, 0, 0);
                            var imagedata = ctxt.getImageData(0, 0, w, h);
                            var data = imagedata.data;
                            //log('imagedata.width:'+imagedata.width+' imagedata.height:'+imagedata.height+' w:'+w+' h:'+h);
                            var obj = {};
                            var color = '';
                            var r = 0, g = 0, b = 0, a = 0;
                            var pix = data.length;
                            for (pix--; pix > 2; pix-=4){
                                //a = data[pix - 0];
                                b = data[pix - 1];
                                g = data[pix - 2];
                                r = data[pix - 3];
                                if (r < 16) r = '0' + r.toString(16);
                                else r = r.toString(16);
                                if (g < 16) g = '0' + g.toString(16);
                                else g = g.toString(16);
                                if (b < 16) b = '0' + b.toString(16);
                                else b = b.toString(16);
                                //if (a < 16) a = '0' + r.toString(16);
                                //else a = a.toString(16);
                                //color = r + g + b + a;
                                color = r + g + b;
                                if (obj[color] > 0) ++obj[color];
                                else obj[color] = 1;
                            }
                            rv.push(obj);
                            imagedata = data = obj = null;
                        }
                        ctxt = null;
                    } catch(error){
                        if (!rv.errors){
                            rv.errors = [];
                        }
                        rv.errors.push(error);
                    }
                }
            });
            return rv;
        };
    } else{
        $.fn.get_colors = function(){
            throw new Error('canvas element support required!');
        };
    }
})(jQuery, this, this.document);

If a document with only one image with 4 pixels(2x2) "#ff0000, #00ff00, #0000ff, #ff0000", if you do $('img').get_colors(); it returns [{"ff0000": 2, "0000ff": 1, "00ff00":1}].

To learn how to use the canvas element you could look at MDN and at the specs in development for details about pixel manipulation.

Edit: commented out a line I was using when debugging.

Upvotes: 2

nrabinowitz
nrabinowitz

Reputation: 55688

You might be interested in this related question and my answer to another one.

Getting all the colors from an image is simple, at least in a browser that supports the canvas element - the technique is described here. You end up with a CanvasPixelArray (described here), which is essentially an array like [r,g,b,a,r,g,b,a, ...] where r,g,b,a are bytes indicating the red, green, blue, and alpha values of each pixel.

The hard part is identifying or creating a small selection of representative colors, rather than the 10,000 colors that might be in a 100x100 image. This is a pretty complicated problem, with many solutions (overview here). You can see Javascript implementations of two possible algorithms in the clusterfck library and my port of the Leptonica Modified Median Cut algorithm.

Upvotes: 7

Related Questions