views:

255

answers:

4

Question:

  • Given an image in PNG format, what is the simplest way to programmatically obtain the number of colors used in the image?

Constraints:

  • The solution will be integreted into a shell script running under Linux, so any solution that fits in such an environment will do.
  • Please note that the "color capacity of the image file" does not necessarily correspond to "colors used". Example: In an image file with a theoretical color capacity of 256 colors only say 7 colors might be in actual use. I want to obtain the number of colors actually used.
+2  A: 

Fun. There doesn't appear to be any guaranteed method of doing this; in the worst case you'll need to scan the image and interpret every pixel, in the best possible case the PNG will be using a palette and you can just check there.

Even in the palette case, though, you're not guaranteed that every entry is used -- so you're (at best) getting an upper bound.

http://www.libpng.org/pub/png/spec/1.1/PNG-Contents.html

.. and the chunk info here:

http://www.libpng.org/pub/png/spec/1.1/PNG-Chunks.html

Maas
Beat me to it by seconds.
he specifically wants the **actual** number of colours used, so an upper bound based on the colour depth or palette isn't good enough
Alnitak
Hey, nice. I answer correctly, then expand a bit on my answer to give a potentially useful back-of-the-envelope addition, and you rate me down for it? Remind me never to add color or context to my statements.. I should have stopped after the semi-colon.
Maas
actually you should have stopped after "interpret every pixel"
Alnitak
+4  A: 

The Image.getcolors method in Python Imaging Library seems to do exactly what you want.

jleedev
+5  A: 

Why write your own program?

If you're doing this with a shell script, you can use the netpbm utilities:

count = `pngtoppm png_file | ppmhist -noheader | wc -l`
Alnitak
+1  A: 

Alnitak's solution is nice :) I really should get to know netpbm and imagemagick etc. better some time.

Just FYI, as a simple and very general solution: loop through each pixel in the image, getting the r,g,b color values as a single integer. Look for that integer in a list. If it's not there, add it. When finished with all the pixels, print the number of colors in the list.

If you want to count occurences, use a hashmap/dictionary instead of a simple list, incrementing the key's value (a counter) if found in the dictionary already. If not found, add it with a starting counter value of 1.

Lee B
"Loop through each pixel in the image [...]" isn't that just a more detailed re-statement of the problem?
knorv
Arguably, any program is a more detailed restatement of the problem :) The question is whether the asker knew that, and whether it helps to tell him. I made a call based on how the question was written, and decided that he might not have known it.
Lee B