0

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

Aage Torleif
  • 1,907
  • 1
  • 20
  • 37
  • Maybe I'm misunderstanding but why not store the colors in an associative array in the first pass? `allColors[r + g + b]=1` – WiredPrairie Jan 19 '14 at 13:28
  • The question is about why this procedure won't find every color if the image is large. However that's not a bad idea, would almost skip the need for removing duplicates. – Aage Torleif Jan 19 '14 at 17:55
  • It should entirely skip the need for removing duplicates, as it would be done by the nature of the storage. – WiredPrairie Jan 19 '14 at 18:04
  • yes, totally! but im also using that array to not only generate a palette i also would use the unsorted version of the array with all the pixel and color info to generate a special binary-like image format. – Aage Torleif Jan 19 '14 at 18:07
  • You could build a real array from the associate array as well. – WiredPrairie Jan 19 '14 at 20:30

2 Answers2

0

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.

  • They are handled as strings properly. My question is if I have a image with 30000 unique colors, I might only capture 300. – Aage Torleif Jan 19 '14 at 23:44
0

"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

Community
  • 1
  • 1
Aage Torleif
  • 1,907
  • 1
  • 20
  • 37