I am using Pillow to do some image operations and want to count how many unique colors are there in a PNG or JPG image file. I can do it easily with mode "P" images that have a small number of colors, but it won't work for RGB or RGBA images. Reading through the docs of Pillow, it seems that Image.getcolors()
returns None
if there are more than 256 colors.
What is the best way to do it? Can we do it using Pillow? I am targeting pure Python + Pillow, but I can optionally include numpy on my list of dependencies, it if it helps.
One possible solution (I encoded the PNG image in Base64):
from PIL import Image
from io import BytesIO
import base64
data = '''iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB+ACCAAXMEa+fpcAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAx9JREFUeNrt3MtNA1EMQFGMpqWIgpAiakJKA6mBBrJOL2wfBYQVDrI9c85+8pnPlWfxXrxQbSWPD6eQv3p1CkAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAurKWPC+1nv/z/S315efLzT2ICQAQAEAAAAEABAAQAEAAAAEABAAEABAAQAAAAQAEABAAYH+sxc4r3Q8g6+vju/T7r6e7e9gEAAgAIACAAAACAAgAIACAAAACAAgAIACAAAACAAgAIADAo236H1jJ45+wmDz1EefLbfR+ApgAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAD4F5tTcGzX0736J4SrYAIABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAOBB+X4AK3l85D+C2bdAtdH7GZgAwCsAIACAAAACAAgAIACAAAACAAgAIACAAAACAAgAIABAWx3WMq+yg12A2Rd/H9ev9BYwAYBXAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAgLaesRb50Ov5ofgBTH2ECQC8AgACAAgAIACAAAACAAgAIACAAAACAAgAIACAAAACALS1OQWMtop3lIgYffpMAOAVABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAoC37ATBbdj1+9X4CJgBAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAH5nPwCOLbufgAkAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAKBKNPgNq+xgqH+ASp9BEwB4BQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEAGgrdvAf7CdA5QMw+hkyAYBXAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAgLbCKbAlgGfABAAIACAAgAAAAgAIACAAgAAAAgAIACAAgAAAAgAIACAAQDs/+5skuT18qwIAAAAASUVORK5CYII='''
img = Image.open(BytesIO(base64.b64decode(data)))
unique_colors = set()
for i in range(img.size[0]):
for j in range(img.size[1]):
pixel = img.getpixel((i, j))
unique_colors.add(pixel)
print('Image info = ', img)
print('Unique color count = ', len(unique_colors))
Prints:
Image info = <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=256x256 at 0x7FFFF670A400>
Unique color count = 7