Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python PIL: Create indexed color image with transparent background

I wonder how I could create a image with a transparent background and only 2 indexed colours (red and blue) to minimise the file size?

More specifically I have two black and white images that I want to convert, one to transparent and blue and the other to transparent and red. Then I want to merge those 2 images. I could do that with a regular RGBA image, but I really want the colour to be indexed to minimise the file size.

Ideally with PIL, but other Python library could also work.

like image 480
Tickon Avatar asked Oct 11 '11 22:10

Tickon


2 Answers

So I managed to do it, using "palette" image type, but the resulting file is not as small as I expected... Here's my code in case its useful for someone else, or if someone can improve on it.

from PIL import Image

im = Image.open("image1.png")
imP = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=3)
imP.putpalette([
    0, 0, 0, # index 0 is black background
    0, 0, 255, # index 1 is blue
    255, 0, 0, # index 2 is red ])

im2 = Image.open("image2.png")
imP2L = im2.convert('L') # need a greyscale image to create a mask
mask = Image.eval(imP2L, lambda a: 255 if a == 0 else 0)
imP.paste(2, mask) # Paste the color of index 2 using image2 as a mask
imP.save('out3.png', transparency = 0, optimize = 1) # Save and set index 0 as transparent
like image 173
Tickon Avatar answered Nov 17 '22 21:11

Tickon


Once you merge the two images, you won't have two colors any more - the colors will combine based on the transparency of each one at every pixel location. Worst case, you will have 256*256=65536 colors, which can't be indexed and wouldn't compress well if you did.

I would suggest saving as a PNG and let the lossless compression do its best.

like image 29
Mark Ransom Avatar answered Nov 17 '22 21:11

Mark Ransom