Question

The project in question: https://github.com/matutter/Pixel2 is a personal project to replace some out of date software at work. What it should do is, the user adds an image and it generates a color palette of the image. The color palette should have no duplicate colors. (thats the only important stuff)

My question is: why do larger or hi-res or complex images not work as well? (loss of color data)

Using dropzone.js I have the user put a picture on the page. The picture is a thumbnail. Next I use jquery to find the src out of a <img src="...">. I pass that src to a function that does this

function generate(imgdata) {
  var imageObj = new Image();
  imageObj.src = imgdata;
  convert(imageObj); //the function that traverses the image data pulling out RGB
}

the "convert" function pulls out the data fairly simply by

for(var i=0, n=data.length; i<n; i+=4, pixel++ ) {
    r = data[i];
    g = data[i+1];
    b = data[i+2];
    color = r + g + b; // format is a string of **r, g, b**
}

finally, the last part of the main algorithme filters out duplicate colors, I only want just 1 occurrence of each... here's the last part

color   = monoFilter(color); // the call

function monoFilter(s) {
    var unique = [];
    $.each(s, function(i, el){
        if($.inArray(el, unique) === -1) unique.push(el);
    });
    unique.splice(0,1); //remove undefine
    unique.unshift("0, 0, 0");    //make sure i have black
    unique.push("255, 255, 255"); //and white
    return unique;
}

I'm hoping someone can help me identify why there is such a loss of color data in big files.

If anyone is actually interesting enough to look at the github, the relivent files are js/pixel2.js, js/dropzone.js, and ../index.html

Was it helpful?

Solution 2

"The problem was that I wasn't accounting for alpha. So a palette from an image that uses alpha would have accidental duplicate records."

I figured this out after finding this Convert RGBA color to RGB

OTHER TIPS

This is probably the cause of the problem:

color = r + g + b; // format is a string of **r, g, b**

This simply adds the numbers together and the more pixels you have the higher risk you run to get the same number. For example, these colors generate the same result:

        R    G   B
color = 90 + 0 + 0 = 90;
color = 0 + 90 + 0 = 90;
color = 0 + 0 + 90 = 90;

even though they are completely different colors.

To avoid this you can do it like this if you want a string:

color = [r,g,b].join();

or you can create an integer value of them (which is faster to compare with than a string):

color = (b << 16) + (g << 8) + r;   /// LSB byte-order

Even an Euclidean vector would be better:

color = r*r + g*g + b*b;

but with the latter you risk eventually the same scenario as the initial one (but useful for nearest color scenarios).

Anyways, hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top