0

我有一个函数,它使用 Pillow 生成给定文本的图像表示,用作输入textfontfont_sizecolor。该函数通过生成一个空的 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
4

1 回答 1

1

您可以使用该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")
于 2021-08-04T09:35:33.647 回答