16

我尝试使用 Python 图像库将 gif 转换为单个图像,但它会导致奇怪的帧

输入 gif 是:

源图片 http://longcat.de/gif_example.gif

在我的第一次尝试中,我尝试将带有 Image.new 的图像转换为 RGB 图像,以 255,255,255 作为白色背景 - 就像我在互联网上找到的任何其他示例一样:

def processImage( infile ):

    try:
        im = Image.open( infile )
    except IOError:
        print "Cant load", infile
        sys.exit(1)

    i = 0

    try:
        while 1:

            background = Image.new("RGB", im.size, (255, 255, 255))
            background.paste(im)
            background.save('foo'+str(i)+'.jpg', 'JPEG', quality=80)

            i += 1
            im.seek( im.tell() + 1 )

    except EOFError:
        pass # end of sequence

但它会导致奇怪的输出文件:

示例 #1 http://longcat.de/gif_example1.jpg

我的第二次尝试是,首先将 gif 转换为 RGBA,然后使用它的透明度蒙版,使透明部分变为白色:

def processImage( infile ):

    try:
        im = Image.open( infile )
    except IOError:
        print "Cant load", infile
        sys.exit(1)

    i = 0

    try:
        while 1:

            im2 = im.convert('RGBA')
            im2.load()

            background = Image.new("RGB", im2.size, (255, 255, 255))
            background.paste(im2, mask = im2.split()[3] )
            background.save('foo'+str(i)+'.jpg', 'JPEG', quality=80)

            i += 1
            im.seek( im.tell() + 1 )

    except EOFError:
        pass # end of sequence

这导致这样的输出:

示例 #2 http://longcat.de/gif_example2.jpg

与第一次尝试相比的优势是,第一帧看起来不错但是正如你所看到的,其余的都坏了

接下来我应该尝试什么?

编辑:

我想我离解决方案更近了

示例 #3 http://longcat.de/gif_example3.png

我必须将第一张图像的调色板用于其他图像,并将其与前一帧合并(对于使用差异图像的 gif 动画)

def processImage( infile ):

    try:
        im = Image.open( infile )
    except IOError:
        print "Cant load", infile
        sys.exit(1)

    i = 0

    size        = im.size
    lastframe   = im.convert('RGBA')
    mypalette   = im.getpalette()

    try:
        while 1:

            im2 = im.copy()
            im2.putpalette( mypalette )

            background = Image.new("RGB", size, (255,255,255))

            background.paste( lastframe )
            background.paste( im2 )
            background.save('foo'+str(i)+'.png', 'PNG', quality=80)

            lastframe = background

            i += 1
            im.seek( im.tell() + 1 )

    except EOFError:
        pass # end of sequence

但我其实不知道,为什么我的透明度是黑色,而不是白色即使我修改调色板(将透明度通道更改为白色)或使用透明度蒙版,背景仍然是黑色

4

4 回答 4

22

首先,JPEG不支持透明!但这不是唯一的问题..当您移动到下一帧时,GIF信息palette丢失了(PIL 的问题?) - 因此PIL无法正确转换为RGBA框架(因此第一帧是好的,但所有其他帧都是拧巴)。因此,解决方法是palette为每一帧添加背面,(这是您在上一个代码示例中所做的,但您的问题是您保存为RGB没有RGBA,因此您没有 alpha/透明度通道。而且您是做一些不必要的事情..)。无论如何,这是具有透明度的.png和更正的代码,希望它有一些用处:)

在此处输入图像描述在此处输入图像描述在此处输入图像描述在此处输入图像描述在此处输入图像描述在此处输入图像描述在此处输入图像描述在此处输入图像描述在此处输入图像描述在此处输入图像描述

import Image
import sys

def processImage(infile):
    try:
        im = Image.open(infile)
    except IOError:
        print "Cant load", infile
        sys.exit(1)
    i = 0
    mypalette = im.getpalette()

    try:
        while 1:
            im.putpalette(mypalette)
            new_im = Image.new("RGBA", im.size)
            new_im.paste(im)
            new_im.save('foo'+str(i)+'.png')

            i += 1
            im.seek(im.tell() + 1)

    except EOFError:
        pass # end of sequence

processImage('gif_example.gif')
于 2012-04-26T14:44:38.603 回答
4

在图像查看器上查看图像时,即使透明度设置为零,它也倾向于将图像显示为黑色。确保您的图像真正透明的一种方法是将其合并到另一个上。应该看到“表情”,同时不妨碍其他图像。尝试:

background = Image.open('someimage.jpg') #an existing image
foreground = Image.open('foo.jpg') #one of the above images
background.paste(foreground, (0,0), foreground)
background.save('trial.jpg') #the composite image

从理论上讲,如果您在图像查看器中打开“trial.jpg”并保留初始图像的内容,并且在其顶部是 foo 图像,那么您将确定它是否只是图像查看器并且您的图像很好...

于 2012-04-22T19:44:25.030 回答
3

来源在这里

Image.open('image.gif').convert('RGB').save('image.jpg')
于 2019-08-02T11:34:54.540 回答
0

在此处输入图像描述

这对我有用。以下示例显示了将 image.gif 转换为 8 幅具有白色背景的 jpg 格式图像。

from PIL import Image
from PIL import GifImagePlugin


def gif2jpg(file_name: str, num_key_frames: int, trans_color: tuple):
    """
    convert gif to `num_key_frames` images with jpg format
    :param file_name: gif file name
    :param num_key_frames: result images number
    :param trans_color: set converted transparent color in jpg image
    :return:
    """
    with Image.open(file_name) as im:
        for i in range(num_key_frames):
            im.seek(im.n_frames // num_key_frames * i)
            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(i))


gif2jpg("image.gif", 8, (255, 255, 255))  # convert image.gif to 8 jpg images with white background

于 2022-02-17T16:23:00.800 回答