// copyright (c) 2013 pieroxy // this work is free. you can redistribute it and/or modify it // under the terms of the wtfpl, version 2 // for more information see license.txt or http://www.wtfpl.net/ // // for more information, the home page: // http://pieroxy.net/blog/pages/color-finder/index.html // // detection of the most prominent color in an image // version 1.1.1 function colorfinder(colorfactorcallback) { this.callback = colorfactorcallback; this.getmostprominentcolor = function(imgel) { var rgb = null; if (!this.callback) this.callback = function() { return 1; }; var data = this.getimagedata(imgel); rgb = this.getmostprominentrgbimpl(data, 6, rgb, this.callback); rgb = this.getmostprominentrgbimpl(data, 4, rgb, this.callback); rgb = this.getmostprominentrgbimpl(data, 2, rgb, this.callback); rgb = this.getmostprominentrgbimpl(data, 0, rgb, this.callback); return rgb; }; this.getimagedata = function(imgel, degrade, rgbmatch, colorfactorcallback) { var rgb, canvas = document.createelement('canvas'), context = canvas.getcontext && canvas.getcontext('2d'), data, width, height, key, i = -4, db={}, length,r,g,b, count = 0; if (!context) { return defaultrgb; } height = canvas.height = imgel.naturalheight || imgel.offsetheight || imgel.height; width = canvas.width = imgel.naturalwidth || imgel.offsetwidth || imgel.width; context.drawimage(imgel, 0, 0); try { data = context.getimagedata(0, 0, width, height); } catch(e) { /* security error, img on diff domain */ return null; } length = data.data.length; var factor = math.max(1,math.round(length/5000)); var result = {}; while ( (i += 4*factor) < length ) { if (data.data[i+3]>32) { key = (data.data[i]>>degrade) + "," + (data.data[i+1]>>degrade) + "," + (data.data[i+2]>>degrade); if (!result.hasownproperty(key)) { rgb = {r:data.data[i], g:data.data[i+1], b:data.data[i+2],count:1}; rgb.weight = this.callback(rgb.r, rgb.g, rgb.b); if (rgb.weight<=0) rgb.weight = 1e-10; result[key]=rgb; } else { rgb=result[key]; rgb.count++; } } } return result; }; this.getmostprominentrgbimpl = function(pixels, degrade, rgbmatch, colorfactorcallback) { var rgb = {r:0,g:0,b:0,count:0,d:degrade}, db={}, pixel,pixelkey,pixelgroupkey, length,r,g,b, count = 0; for (pixelkey in pixels) { pixel = pixels[pixelkey]; totalweight = pixel.weight * pixel.count; ++count; if (this.doesrgbmatch(rgbmatch, pixel.r, pixel.g, pixel.b)) { pixelgroupkey = (pixel.r>>degrade) + "," + (pixel.g>>degrade) + "," + (pixel.b>>degrade); if (db.hasownproperty(pixelgroupkey)) db[pixelgroupkey]+=totalweight; else db[pixelgroupkey]=totalweight; } } for (i in db) { data = i.split(","); r = data[0]; g = data[1]; b = data[2]; count = db[i]; if (count>rgb.count) { rgb.count = count; data = i.split(","); rgb.r = r; rgb.g = g; rgb.b = b; } } return rgb; }; this.doesrgbmatch = function(rgb,r,g,b) { if (rgb==null) return true; r = r >> rgb.d; g = g >> rgb.d; b = b >> rgb.d; return rgb.r == r && rgb.g == g && rgb.b == b; } }