PIL 将文本添加到 gif 帧会增加图片的噪点

Has*_*ast 1 python gif animated-gif python-imaging-library

我正在使用 PIL 创建一个简单的 GIF 动画:

from PIL import Image, ImageDraw, ImageFont

images = []

for x, i in enumerate(range(10)):
    image = Image.new(mode="RGB", size=(320, 60), color="orange")

    draw = ImageDraw.Draw(image)
    fnt = ImageFont.truetype('font.ttf', size=10)
    draw.text((10, 10), ("%s" % x), fill=(0, 0, 255), font=fnt)
    images.append(image)

images[0].save("result/pil.gif", save_all=True, append_images=images[1:], duration=1000, loop=0, format="GIF")
Run Code Online (Sandbox Code Playgroud)

问题是,每当我使用 Draw.text 时,图像的背景就会出现某种白色:

在此输入图像描述

我发现一些信息,我必须使用第一帧中的 getpalette 和所有其他帧的 putpalette ,如下所示:

for x, i in enumerate(range(10)):
    image = Image.new(mode="RGB", size=(320, 60), color="orange")

    if x == 0:
        palette = image.getpalette()
    else:
        image.putpalette(palette)
Run Code Online (Sandbox Code Playgroud)

但它只是给了我:ValueError: illegal image mode

背景噪音的原因是什么?如何解决?

UPD我能够通过将图像模式更改为“P”来修复背景,但在这种情况下我的字体变得不可读。这些是 RGB 模式(字体很好)和 P 模式(字体很糟糕)的示例:

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

为什么我只能得到漂亮的背景或漂亮的字体,但不能同时得到两者?有解决方法吗?

fde*_*hin 6

这是发生的抖动,因为 gif 只能包含大小为 256 的调色板中的颜色。很可能 PIL 使用非常基本的算法从 RGB 格式转换为 gif 所需的索引格式。由于您的图像包含颜色#ff9900#ffcc00,因此调色板大概由每个字节的十六进制值组成00, 33, 66, 99, cc, ff,大小为 6x6x6 = 216,非常适合 256 个可能的值。'orange'具有 的值#ffa500并且不能用这样的调色板表示,因此背景由最接近的可用颜色填充。

您可以尝试使用颜色'#ff9900'代替'orange'。希望这种颜色可以用调色板来表示,因为它出现在嘈杂的图像中。

您还可以尝试使用自己的调色板作为quantize方法中的参数从 RGB 转换为索引格式,如本答案中所建议的。添加以下行会产生漂亮的纯色背景

image = image.quantize(method=Image.MEDIANCUT)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

或者您可以将 RGB 图像保存为 PNG 格式。在这种情况下,它将保存为 APNG 图像。

images[0].save("pil.png", save_all=True, append_images=images[0:],duration=1000, loop=0, format="PNG")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述