python - 为什么我的代码中的 GIF 调色板损坏了?
问题描述
我制作了一个为 GIF 或图像添加字幕的函数:
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'
)
这有轻微的变化,会产生奇怪的结果,这是不需要的。
这是in.gif
:
- 不更改上面的代码:
palette=old_im.palette
传入frames[0].save()
:_
.convert('RGB'))
将帧在展开后立即转换为“RGB”( ):
palette=old_im.palette
传入frames[0].save(...)
并在.convert('RGB'))
扩展后立即将帧转换为“RGB”( ):
palette=old_im.getpalette()
传入frames[0].save(...)
:_
palette=old_im.getpalette()
传入frames[0].save(...)
并在.convert('RGB'))
扩展后立即将帧转换为“RGB”( ):
正如您所看到的,没有一个选项具有所需的输出,尽管数字 5 似乎有最好的结果,除了白色画布上的黑色文本现在突然变成红色画布上的深红色文本。是什么原因造成的,我怎样才能得到正常的输出?
解决方案
'RGB'
在扩展之前转换为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'
,我猜“白色”将是“正确的白色”。
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.9.1
Pillow: 8.1.2
----------------------------------------
推荐阅读
- javascript - 正则表达式可以找到这样的模式吗?
- bash - 通过 Jenkins 管道访问运行 Matlab 的 Docker Slave 的命令行
- swift - changeRootViewController时出现unknow error:EXC_BAD_ACCESS (code=1, address=0x20)
- graphql - 使用第一个查询结果作为第二个查询的条件
- c# - 循环加载用户配置文件
- regex - Oracle SQL Regex 美元符号不能确定字符串的结尾
- file - TYPO3 如何生成文件的索引,如其 XML 网站导出数据所示?
- r - 为什么 print() 会改变我的函数的输出?
- javafx - 是否可以在我键入时自动格式化 JavaFX HTMLEditor 内容?
- python - Pandas 数据框分配引发 SettingWithCopyWarning