PIL如何将带有透明度的PNG或GIF转换为不带透明度的JPG?

17

我正在使用PIL1.1.7在Python 2.7中原型化一个图像处理器,并希望所有图像最终都是JPG格式。输入文件类型将包括带透明度和不带透明度的tiff、gif、png。我一直在尝试组合两个脚本:1.将其他文件类型转换为JPG;2.通过创建空白白色图像并将原始图像粘贴到白色背景上来去除透明度。我的搜索结果被那些寻求生成或保留透明度的人所淹没,而不是相反的情况。

我目前正在使用以下代码:

#!/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

这两个脚本在单独运行时都能正常工作,但是当我将它们合并时就会出现“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

我怀疑如果我保存一个没有透明度的PNG,然后打开这个新文件,重新保存成JPG,并删除写入磁盘的PNG,但我希望有一种优雅的解决方案,我还没有找到。


当代码在.paste()上出错甚至没有到达那一行时,为什么您会认为问题是“下面的那一行”? - kindall
这个问题稍晚提出,但已经有了所有的答案:https://dev59.com/nmox5IYBdhLWcg3wf0bl#33507138 - Vinícius M
4个回答

34

将您的背景设置为RGB,而不是RGBA。当然,删除后面将背景转换为RGB的步骤,因为它已经处于该模式下。这对我使用测试图像起作用:

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")

4
它在http://img293.imageshack.us/img293/1434/teslahv5.png上失效了,我该怎么修复它? - Eugene Nagorny
我认为这行代码 bg.paste(im,im) 需要改成 bg.paste(im,mask=im)。 - Ramast
2
收到 '*** ValueError: bad transparency mask' 的错误,其遮罩为im。 - Sandeep
使用上述解决方案仍然会出现“*** ValueError: bad transparency mask”错误。不确定原因。 - Sandeep
也许有点晚了,但是尝试一下 bg.paste(im, mask=im.split()[3]) - Jens
在这里,各位:https://dev59.com/nmox5IYBdhLWcg3wf0bl#33507138 - Vinícius M

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

关键是使蒙版(用于粘贴的)成为图像本身。
这应该适用于那些具有“柔和边缘”的图像(其中Alpha透明度设置为不为 0 或 255)。

5
以下内容适用于我在这张图片上的操作。
f, e = os.path.splitext(infile)
print infile
outfile = f + ".jpg"
if infile != outfile:
    im = Image.open(infile)
    im.convert('RGB').save(outfile, 'JPEG')

我最初尝试了这种方法。直接转换为RGB模式可以处理硬边缘掩模,但是在软边缘掩模下可能会出现非常严重的问题。 - kindall
你能提供一个图片链接,让我看看它为什么无法工作吗?我会尝试解决这个问题。 - uncreative
这是我用来测试的一个链接:http://mac.jerrykindall.com:81/pil/jk.png。如果只是去掉 alpha 通道,这是结果链接:http://mac.jerrykindall.com:81/pil/jk_bad.png。 - kindall

1
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))

要将png转换为jpg,请运行png2jpg("try.png", (255,255,255))

结果:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接