如何使用python在图像上绘制具有不同笔触和填充颜色的文本?
这是一些红色笔触和灰色填充的文字。
我尝试使用PIL执行此操作,但没有设置笔触颜色的选项。
答案 0 :(得分:10)
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")
答案 1 :(得分:7)
PIL不支持此功能但您可以伪造它:使用一个像素偏移使用轮廓颜色渲染文本四到八次:
x+1,y
x-1,y
x ,y+1
x ,y-1
(四次版)
x+1,y+1
x ,y+1
x-1,y+1
x+1,y
x-1,y
x+1,y-1
x ,y-1
x-1,y-1
(八次版)
然后在x,y
处填充颜色一次。
答案 2 :(得分:6)
使用imagemagick:
import subprocess
args = {
'bgColor': 'transparent',
'fgColor': 'light slate grey',
'fgOutlineColor': 'red',
'text': 'Example',
'size': 72,
'geometry': '350x100!',
'output': '/tmp/out.png',
'font': 'helvetica'
}
cmd = ['convert', 'xc:{bgColor}', '-resize', '{geometry}', '-gravity', 'Center',
'-font', '{font}', '-pointsize', '{size}', '-fill', '{fgColor}',
'-stroke', '{fgOutlineColor}', '-draw', "text 0,0 '{text}'", '-trim', '{output}']
cmd = [item.format(**args) for item in cmd]
proc = subprocess.Popen(cmd)
proc.communicate()
答案 3 :(得分:3)
他们从6.2.0版本开始在Pillow中添加了本机解决方案:https://pillow.readthedocs.io/en/stable/reference/ImageDraw.html#PIL.ImageDraw.PIL.ImageDraw.ImageDraw.text
您现在指定stroke_fill
(轮廓的颜色)和stroke_width
(轮廓的厚度)。
答案 4 :(得分:2)
您可以使用Inkscape:
import subprocess
subprocess.call("inkscape in.svg --export-text-to-path --export-plain-svg out.svg", shell = True)
注意:您必须下载Inkscape才能使用它,因此不适合永久使用
答案 5 :(得分:1)
补充@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以下似乎是可以接受的。