PIL Convert PNG or GIF with Transparency to JPG without

I'm prototyping an image processor in Python 2.7 using PIL1.1.7 and I would like all images to end up in JPG. Input file types will include tiff,gif,png both with transparency and without. I've been trying to combine two scripts that I found that 1. convert other file types to JPG and 2. removing transparency by creating a blank white image and pasting the original image over the white background. My searches are being spammed with people seeking to generate or preserve transparency rather than the opposite.

I'm currently working with this:

#!/usr/bin/python
import os, glob
import Image

images = glob.glob("*.png")+glob.glob("*.gif")

for infile in images:
    f, e = os.path.splitext(infile)
    outfile = f + ".jpg"
    if infile != outfile:
        #try:
        im = Image.open(infile)
        # Create a new image with a solid color
        background = Image.new('RGBA', im.size, (255, 255, 255))
        # Paste the image on top of the background
        background.paste(im, im)
        #I suspect that the problem is the line below
        im = background.convert('RGB').convert('P', palette=Image.ADAPTIVE)
        im.save(outfile)
        #except IOError:
           # print "cannot convert", infile

Both scripts work in isolation, but as I have combined them I get a ValueError: Bad Transparency Mask.

Traceback (most recent call last):
File "pilhello.py", line 17, in <module>
background.paste(im, im)
File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 1101, in paste
self.im.paste(im, box, mask.im)
ValueError: bad transparency mask

I suspect that if I were to save a PNG without transparency I could then open that new file, and re-save it as a JPG, and delete the PNG that was written to disk, but I'm hoping that there is an elegant solution that I haven't found yet.

Upvotes: 18

Views: 38804

Answers (4)

apoptosis
apoptosis

Reputation: 71

from PIL import Image


def png2jpg(file_name:str, trans_color: tuple):
    """
    convert png file to jpg file
    :param file_name: png file name
    :param trans_color: set transparent color in jpg image
    :return:
    """
    with Image.open(file_name) as im:
        image = im.convert("RGBA")
        datas = image.getdata()
        newData = []
        for item in datas:
            if item[3] == 0:  # if transparent
                newData.append(trans_color)  # set transparent color in jpg
            else:
                newData.append(tuple(item[:3]))
        image = Image.new("RGB", im.size)
        image.getdata()
        image.putdata(newData)
        image.save('{}.jpg'.format(file_name))

To convert png to jpg run png2jpg("try.png", (255,255,255))

Result:

enter image description here

Upvotes: 1

Chander
Chander

Reputation: 91

image=Image.open('file.png')
non_transparent=Image.new('RGBA',image.size,(255,255,255,255))
non_transparent.paste(image,(0,0),image)

The key is to make the mask (for the paste) the image itself.

This should work on those images that have "soft edges" (where the alpha transparency is set to not be 0 or 255)

Upvotes: 9

kindall
kindall

Reputation: 184171

Make your background RGB, not RGBA. And remove the later conversion of the background to RGB, of course, since it's already in that mode. This worked for me with a test image I created:

from PIL import Image
im = Image.open(r"C:\jk.png")
bg = Image.new("RGB", im.size, (255,255,255))
bg.paste(im,im)
bg.save(r"C:\jk2.jpg")

Upvotes: 35

uncreative
uncreative

Reputation: 1446

The following works for me on this image

f, e = os.path.splitext(infile)
print infile
outfile = f + ".jpg"
if infile != outfile:
    im = Image.open(infile)
    im.convert('RGB').save(outfile, 'JPEG')

Upvotes: 5

Related Questions