【发布时间】:2021-07-09 16:36:37
【问题描述】:
我制作了一个为 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():
- 在展开后立即将帧转换为“RGB”(
.convert('RGB'))):
- 将
palette=old_im.palette传递到frames[0].save(...)并且帧在展开后立即转换为“RGB”(.convert('RGB'))):
- 将
palette=old_im.getpalette()传递到frames[0].save(...):
- 将
palette=old_im.getpalette()传递到frames[0].save(...)并且帧在展开后立即转换为“RGB”(.convert('RGB'))):
正如您所见,没有一个选项具有所需的输出,尽管数字 5 似乎有最好的结果,除了白色画布上的黑色文本现在突然变成红色画布上的深红色文本。这是什么原因造成的,我怎样才能得到正常的输出?
【问题讨论】:
标签: python python-3.x python-imaging-library gif