我有一个函数,它使用枕头生成给定文本的图像表示,使用输入text
、font
、font_size
和color
。该函数的工作方式是生成一个空的RGBA映像,然后在其上绘制文本,最后对结果进行裁剪,以便只保留文本。
现在,在99%的情况下,这个函数工作得很好,但是字体越大,我就需要一个更大的画布来开始,否则文本就会被剪短。因此,我将初始画布设置为具有非常高的值,例如(10k, 10k)
像素。这个初始图像大小减慢了整个过程,我想知道是否有一种方法可以获得相同的结果,而不必求助于初始的空图像,或者生成初始图像大小尽可能小,以避免浪费资源
我的职责是:
def text_to_image(
text: str,
font_filepath: str,
font_size: int,
color: Tuple[int, int, int, int],
) -> ImageType:
# ?: very big canvas size as to not to clip the text when rendered with bigger font sizes
canvas_size = (
10000,
10000,
)
img = Image.new("RGBA", canvas_size)
draw = ImageDraw.Draw(img)
draw_point = (0, 0)
font = ImageFont.truetype(font_filepath, size=font_size)
draw.multiline_text(draw_point, text, font=font, fill=color)
text_window = img.getbbox()
img = img.crop(text_window)
return img
抽样结果:
编辑:
感谢@AKX的超级快速反应,它解决了我的问题。对任何感兴趣的人来说,这个函数变成
def text_to_image(
text: str,
font_filepath: str,
font_size: int,
color: Tuple[int, int, int, int],
) -> ImageType:
font = ImageFont.truetype(font_filepath, size=font_size)
img = Image.new("RGBA", font.getmask(text).size)
draw = ImageDraw.Draw(img)
draw_point = (0, 0)
draw.multiline_text(draw_point, text, font=font, fill=color)
text_window = img.getbbox()
img = img.crop(text_window)
return img
发布于 2021-08-04 09:35:33
您可以使用getmask()
函数获得与给定文本大小完全相同的灰度位图。
然后,您可以创建一个空图像,一个所需的背景色。
然后使用带有纯色和掩码的im.paste()
在文本中绘制:
from PIL import Image, ImageFont
text = "Hello world!"
font_size = 36
font_filepath = "/Library/Fonts/Artegra_Sans-600-SemiBold-Italic.otf"
color = (67, 33, 116, 155)
font = ImageFont.truetype(font_filepath, size=font_size)
mask_image = font.getmask(text, "L")
img = Image.new("RGBA", mask_image.size)
img.im.paste(color, (0, 0) + mask_image.size, mask_image) # need to use the inner `img.im.paste` due to `getmask` returning a core
img.save("yes.png")
发布于 2022-06-14 10:11:38
谢谢@HitLuca和@AKX上面的代码示例。我发现get掩码函数正在剪切我的一些文本。我发现使用getsize_multiline函数使文本维度作为一个替代方案运行得很好。下面是我的密码。
from PIL import Image, ImageFont, ImageDraw, ImageColor
def text_to_image(
text: str,
font_filepath: str,
font_size: int,
color: (int, int, int), #color is in RGB
font_align="center"):
font = ImageFont.truetype(font_filepath, size=font_size)
box = font.getsize_multiline(text)
img = Image.new("RGBA", (box[0], box[1]))
draw = ImageDraw.Draw(img)
draw_point = (0, 0)
draw.multiline_text(draw_point, text, font=font, fill=color, align=font_align)
return img
https://stackoverflow.com/questions/68648801
复制相似问题