如何使用python在图像上绘制具有不同笔划和填充颜色的文本?

如何使用python在图像上绘制具有不同笔划和填充颜色的文本?,python,image,python-imaging-library,Python,Image,Python Imaging Library,如何使用python在图像上绘制具有不同笔划和填充颜色的文本 这是一些带有红色笔划和灰色填充的文本 我曾尝试使用PIL进行此操作,但没有设置笔划颜色的选项。使用: PIL不支持这一点,但您可以伪造它:使用一个像素偏移量使用轮廓颜色渲染文本四到八次: x+1,y x-1,y x ,y+1 x ,y-1 (四倍版本) (八倍版本) 然后用填充颜色在x,y处填充一次。使用(从中提取大量代码): 您可以使用Inkscape: import subprocess subprocess.call(

如何使用python在图像上绘制具有不同笔划和填充颜色的文本

这是一些带有红色笔划和灰色填充的文本

我曾尝试使用PIL进行此操作,但没有设置笔划颜色的选项。

使用:


PIL不支持这一点,但您可以伪造它:使用一个像素偏移量使用轮廓颜色渲染文本四到八次:

x+1,y
x-1,y
x  ,y+1
x  ,y-1 
(四倍版本)

(八倍版本)

然后用填充颜色在
x,y
处填充一次。

使用(从中提取大量代码):

您可以使用Inkscape:

import subprocess
subprocess.call("inkscape in.svg --export-text-to-path --export-plain-svg out.svg", shell = True)

注意:您必须下载Inkscape才能使用此功能,因此永久使用不实用

补充@Aaron Digulla的答案,这就是在PIL中伪造轮廓颜色的方法:

from PIL import Image, ImageDraw, ImageFont

def main():
    text_color = (255, 0, 0)
    outline_color = (0, 0, 255)
    size = (512, 256)
    img = Image.new(mode='RGB', size=size, color=(255, 255, 255))
    font = ImageFont.truetype(font="C:/WINDOWS/Fonts/STKAITI.TTF", size=100)
    drawer = ImageDraw.Draw(img)

    x = 10
    y = 10
    bd_w = 1
    drawer.text((x-bd_w, y), "测试文字", font=font, fill=outline_color)
    drawer.text((x, y-bd_w), "测试文字", font=font, fill=outline_color)
    drawer.text((x+bd_w, y), "测试文字", font=font, fill=outline_color)
    drawer.text((x, y+bd_w), "测试文字", font=font, fill=outline_color)

    drawer.text((x+bd_w, y-bd_w), "测试文字", font=font, fill=outline_color)
    drawer.text((x-bd_w, y-bd_w), "测试文字", font=font, fill=outline_color)
    drawer.text((x-bd_w, y+bd_w), "测试文字", font=font, fill=outline_color)
    drawer.text((x+bd_w, y+bd_w), "测试文字", font=font, fill=outline_color)

    drawer.text((x, y), "测试文字", font=font, fill=text_color)

    img.show()


if __name__ == "__main__":
    main()
但请注意,如果将
bd_w
(边框宽度)设置得稍高,此方法将生成不符合要求的文本。参见下图了解
bd_w
的效果:

边框宽度=1

边框宽度=4

边框宽度=7


对于大文本,将边框宽度保持在4以下似乎是可以接受的。

他们从6.2.0开始在枕头中添加了本机解决方案:


现在,您可以指定
stroke\u fill
这是轮廓的颜色,而
stroke\u width
这是轮廓的厚度。

我需要知道文本的尺寸才能使用它吗?我可以通过上下文获得所需的信息。text\u extends(“示例”)但是之后,我需要创建一个新的具有正确宽度和高度的表面。是的,不幸的是,我不知道一个更好的方法。@ unutu,我成功地将您的代码移植到C++中,但是有一个问题Reg透明度。谢谢,你能检查一下吗?在我创建输出文本之前,我需要知道输出文本的尺寸吗?你可以使用任何你想要的
几何图形--imagemagick会创建一个精确的几何图形,只要你使用感叹号--但是如果字体
大小
太大,部分文字可能会被剪掉。我想得到一张与文字大小完全一致的图片。没有剪切的文本,某些方面没有多余的空间。您可以使用
-trim
选项剪切到文本的大小。最好将命令及其选项放入列表中,然后替换每个元素中的变量。这将解决参数中空格和/或引号字符的问题。8x版本基本上相当于仅在对角线上渲染4次。@HassanBaig您不会注意到它。它仅在边框较薄(例如,1像素)时有效。如果使用较宽的边框,生成的文本就不太令人满意。要更新pillow,请使用pip install-U pillow
。这适用于枕头7.2。
import cairo

def text_extent(font, font_size, text, *args, **kwargs):
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 0, 0)
    ctx = cairo.Context(surface)
    ctx.select_font_face(font, *args, **kwargs)
    ctx.set_font_size(font_size)
    return ctx.text_extents(text)

text='Example'
font="Sans"
font_size=55.0
font_args=[cairo.FONT_SLANT_NORMAL]
(x_bearing, y_bearing, text_width, text_height,
 x_advance, y_advance) = text_extent(font, font_size, text, *font_args)
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(text_width), int(text_height))
ctx = cairo.Context(surface)
ctx.select_font_face(font, *font_args)
ctx.set_font_size(font_size)
ctx.move_to(-x_bearing, -y_bearing)
ctx.text_path(text)
ctx.set_source_rgb(0.47, 0.47, 0.47)
ctx.fill_preserve()
ctx.set_source_rgb(1, 0, 0)
ctx.set_line_width(1.5)
ctx.stroke()

surface.write_to_png("/tmp/out.png")
import subprocess
subprocess.call("inkscape in.svg --export-text-to-path --export-plain-svg out.svg", shell = True)
from PIL import Image, ImageDraw, ImageFont

def main():
    text_color = (255, 0, 0)
    outline_color = (0, 0, 255)
    size = (512, 256)
    img = Image.new(mode='RGB', size=size, color=(255, 255, 255))
    font = ImageFont.truetype(font="C:/WINDOWS/Fonts/STKAITI.TTF", size=100)
    drawer = ImageDraw.Draw(img)

    x = 10
    y = 10
    bd_w = 1
    drawer.text((x-bd_w, y), "测试文字", font=font, fill=outline_color)
    drawer.text((x, y-bd_w), "测试文字", font=font, fill=outline_color)
    drawer.text((x+bd_w, y), "测试文字", font=font, fill=outline_color)
    drawer.text((x, y+bd_w), "测试文字", font=font, fill=outline_color)

    drawer.text((x+bd_w, y-bd_w), "测试文字", font=font, fill=outline_color)
    drawer.text((x-bd_w, y-bd_w), "测试文字", font=font, fill=outline_color)
    drawer.text((x-bd_w, y+bd_w), "测试文字", font=font, fill=outline_color)
    drawer.text((x+bd_w, y+bd_w), "测试文字", font=font, fill=outline_color)

    drawer.text((x, y), "测试文字", font=font, fill=text_color)

    img.show()


if __name__ == "__main__":
    main()