mirror of
https://github.com/janishutz/color-thief.git
synced 2025-11-25 22:04:25 +00:00
updates before renaming to color-thief
This commit is contained in:
196
js/color-thief.js
Normal file
196
js/color-thief.js
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Image Palette v0.1
|
||||
* by Lokesh Dhakar - http://www.lokeshdhakar.com
|
||||
*
|
||||
* Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
|
||||
*
|
||||
* The median cut palette function uses quantize.js which is written by Nick Rabinowitz
|
||||
* and licensed under the MIT license. Big props to Nick as this is where the magic happens.
|
||||
*
|
||||
* == Functions
|
||||
* getDominantColor()
|
||||
* createPalette()
|
||||
* getAverageRGB()
|
||||
* createAreaBasedPalette()
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* getDominantColor(sourceImage)
|
||||
* returns {r: num, g: num, b: num}
|
||||
*
|
||||
* Use the median cut algorithm provided by quantize.js to cluster similar
|
||||
* colors and return the base color from the largest cluster.
|
||||
*/
|
||||
function getDominantColor(sourceImage){
|
||||
|
||||
var palette = [];
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
// Store the RGB values in an array format suitable for quantize function
|
||||
var pixelArray = [];
|
||||
for (var i = 0; i < pixelCount; i++) {
|
||||
// If pixel is mostly opaque
|
||||
if(pixels[i*4+3] >= 125){
|
||||
pixelArray.push( [pixels[i*4], pixels[i*4+1], pixels[i*4+2]]);
|
||||
}
|
||||
};
|
||||
|
||||
// Send array to quantize function which clusters values
|
||||
// using median cut algorithm
|
||||
var cmap = MMCQ.quantize(pixelArray, 5);
|
||||
var newPalette = cmap.palette();
|
||||
|
||||
return {r: newPalette[0][0], g: newPalette[0][1], b: newPalette[0][2]};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* createPalette(sourceImage)
|
||||
* returns array[ {r: num, g: num, b: num}, {r: num, g: num, b: num}, ...]
|
||||
*
|
||||
* Use the median cut algorithm provided by quantize.js to cluster similar
|
||||
* colors.
|
||||
*
|
||||
* BUGGY: Function does not always return the requested amount of colors. It can be +/- 2.
|
||||
*/
|
||||
function createPalette(sourceImage, colorCount){
|
||||
|
||||
var palette = [];
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
// Store the RGB values in an array format suitable for quantize function
|
||||
var pixelArray = [];
|
||||
for (var i = 0; i < pixelCount; i++) {
|
||||
// If pixel is mostly opaque
|
||||
if(pixels[i*4+3] >= 125){
|
||||
pixelArray.push( [pixels[i*4], pixels[i*4+1], pixels[i*4+2]]);
|
||||
}
|
||||
};
|
||||
|
||||
// Send array to quantize function which clusters values
|
||||
// using median cut algorithm
|
||||
var cmap = MMCQ.quantize(pixelArray, colorCount);
|
||||
var newPalette = cmap.palette();
|
||||
|
||||
return newPalette;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* getAverageRGB(sourceImage)
|
||||
* returns {r: num, g: num, b: num}
|
||||
*
|
||||
* Add up all pixels RGB values and return average.
|
||||
* Tends to return muddy gray/brown color. Most likely, you'll be better
|
||||
* off using getDominantColor() instead.
|
||||
*/
|
||||
function getAverageRGB(sourceImage) {
|
||||
// Config
|
||||
var sampleSize = 10;
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
// Reset vars
|
||||
var i = 0,
|
||||
count = 0,
|
||||
rgb = {r:0,g:0,b:0};
|
||||
|
||||
// Loop through every # pixels. (# is set in Config above via the blockSize var)
|
||||
// Add all the red values together, repeat for blue and green.
|
||||
// Last step, divide by the number of pixels checked to get average.
|
||||
while ( (i += sampleSize * 4) < pixelCount ) {
|
||||
// if pixel is mostly opaque
|
||||
if(pixels[i+3] > 125){
|
||||
++count;
|
||||
rgb.r += pixels[i];
|
||||
rgb.g += pixels[i+1];
|
||||
rgb.b += pixels[i+2];
|
||||
}
|
||||
}
|
||||
|
||||
rgb.r = Math.floor(rgb.r/count);
|
||||
rgb.g = Math.floor(rgb.g/count);
|
||||
rgb.b = Math.floor(rgb.b/count);
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* createAreaBasedPalette(sourceImage, colorCount)
|
||||
* returns array[ {r: num, g: num, b: num}, {r: num, g: num, b: num}, ...]
|
||||
*
|
||||
* Break the image into sections. Loops through pixel RGBS in the section and average color.
|
||||
* Tends to return muddy gray/brown color. You're most likely better off using createPalette().
|
||||
*
|
||||
* BUGGY: Function does not always return the requested amount of colors. It can be +/- 2.
|
||||
*
|
||||
*/
|
||||
function createAreaBasedPalette(sourceImage, colorCount){
|
||||
|
||||
var palette = [];
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
|
||||
// How big a pixel area does each palette color get
|
||||
var rowCount = colCount = Math.round(Math.sqrt(colorCount)),
|
||||
colWidth = Math.round(image.width / colCount),
|
||||
rowHeight = Math.round(image.height / rowCount);
|
||||
|
||||
var count = offset = rowOffset = vertOffset = horizOffset = 0,
|
||||
rgb = {r:0,g:0,b:0};
|
||||
|
||||
// Loop through pixels section by section.
|
||||
// At the end of each section, push the average rgb color to palette array.
|
||||
for(var i=0; i<rowCount; i++){
|
||||
vertOffset = i * rowHeight * image.width * 4;
|
||||
|
||||
for(var j=0; j<colCount; j++){
|
||||
horizOffset = j * colWidth * 4;
|
||||
|
||||
for( var k = 0; k < rowHeight; k++){
|
||||
rowOffset = k * image.width * 4;
|
||||
|
||||
for( var l = 0; l < colWidth; l++){
|
||||
offset = vertOffset + horizOffset + rowOffset + (l * 4);
|
||||
rgb.r += pixels[offset];
|
||||
rgb.g += pixels[offset+1];
|
||||
rgb.b += pixels[offset+2];
|
||||
count++;
|
||||
}
|
||||
|
||||
}
|
||||
rgb.r = Math.floor(rgb.r/count);
|
||||
rgb.g = Math.floor(rgb.g/count);
|
||||
rgb.b = Math.floor(rgb.b/count);
|
||||
palette.push(rgb);
|
||||
|
||||
// reset before next section
|
||||
rgb = {r:0,g:0,b:0};
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return palette;
|
||||
}
|
||||
Reference in New Issue
Block a user