为什么GIF调色板在我的代码中被损坏? [英] Why does the GIF colour palette get corrupted in my code?

查看:47
本文介绍了为什么GIF调色板在我的代码中被损坏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了为GIF或图片加标题的函数:

I made a function that captions a GIF or image:

import textwrap
from io import BytesIO

from PIL import Image, ImageDraw, ImageFont, ImageOps, ImageSequence


def caption(fn: str, text: str):
    old_im = Image.open(fn)
    ft = old_im.format
    W = old_im.size[0]
    font = ImageFont.truetype('BebasNeue.ttf', 50) # replace with your own font

    width = 10
    while True:
        lines = textwrap.wrap(text, width=width)
        if (font.getsize(max(lines, key=len))[0]) > (0.9 * W):
            break
        width += 1

    # amount of lines * height of one line
    bar_height = len(lines) * (font.getsize(lines[0])[1])
    frames = []
    for frame in ImageSequence.Iterator(old_im):
        frame = ImageOps.expand(
            frame,
            border=(0, bar_height, 0, 0),
            fill='white'
        )
        draw = ImageDraw.Draw(frame)
        for i, line in enumerate(lines):
            w, h = draw.multiline_textsize(line, font=font)
            # Position is x: centered, y: line number * height of line
            draw.text(
                ((W - w) / 2, i * h),
                line,
                font=font,
                fill='black'
            )

        del draw
        b = BytesIO()
        frame.save(b, format=ft)
        b.seek(0)
        frames.append(Image.open(b))

    frames[0].save(
        f'out.{ft}',
        save_all=True,
        append_images=frames[1:],
        format=ft,
        loop=0,
        optimize=True
    )


caption(
    'in.gif',
    'this is a test message this is a test message this is a test message this is a test message this is a test message this is a test message'
)

这会带来一些奇怪的结果,只是不希望有什么变化.

This, with slight variations, is giving weird results, of which none are desired.

这是 in.gif :

  1. 不更改上面的代码:

  1. palette = old_im.palette 传递到 frames [0] .save():

  1. 将框架展开后立即将其转换为'RGB'( .convert('RGB'))):

  1. palette = old_im.palette 传递到 frames [0] .save(...) ,并将帧转换为'RGB展开后立即使用(( .convert('RGB'))):
  1. With palette=old_im.palette passed into frames[0].save(...) and the frame converted to 'RGB' (.convert('RGB'))) immediately after expanding it:

  1. palette = old_im.getpalette()传递到 frames [0] .save(...):

  1. palette = old_im.getpalette()传递到 frames [0] .save(...) ,并将帧转换为展开后立即使用'RGB'( .convert('RGB'))):
  1. With palette=old_im.getpalette() passed into frames[0].save(...) and the frame converted to 'RGB' (.convert('RGB'))) immediately after expanding it:

如您所见,尽管数字5似乎具有最佳效果,但没有一个选项具有理想的输出,除了白色画布上的黑色文本现在突然变成了红色画布上的暗红色文本.是什么原因造成的?如何获得正常的输出?

As you can see none of the options have the desired output, though number 5 seems to have the best results, apart from the black text on white canvas now suddenly being dark red text on a red canvas. What is causing this and how could I get a normal output?

推荐答案

在扩展 frame 之前,先转换为'RGB':

Convert to 'RGB' BEFORE expanding the frame:

# [...]
for frame in ImageSequence.Iterator(old_im):
    frame = frame.convert('RGB')                # <--
    frame = ImageOps.expand(
        frame,
        border=(0, bar_height, 0, 0),
        fill='white'
    )
    draw = ImageDraw.Draw(frame)
# [...]

这就是我得到的输出:

我认为,用 white 填充会以某种方式破坏现有的调色板.如果您在展开前转换为'RGB',则白色"表示我猜这将是正确的白色".

I assume, that filling with white somehow corrupts the existing palette. If you convert to 'RGB' before expanding, "white" will be the "correct white", I guess.

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
Pillow:        8.1.2
----------------------------------------

这篇关于为什么GIF调色板在我的代码中被损坏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆