Reputation: 1407
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
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:
Upvotes: 1
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
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
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