【PIL处理图片】小技巧之画虚线、加粗字体、长文本自动分行(符号处理)

【PIL处理图片】系列文章目录

小技巧之图片透明渐变处理
小技巧之画虚线、加粗字体、长文本自动分行(符号处理)
小技巧之圆角边框处理


上一篇介绍了图片渐变蒙版处理,还有一些其他的小技巧,一起在这里介绍一下。可以直接看目录标题,几个方法相互独立。


加粗字体

先加载PIL库。

from PIL import Image, ImageDraw, ImageFont

这个没什么说的,主要用到ImageDraw.text()

img = Image.open('这里填图像路径.png')
draw = ImageDraw.Draw(img)
# 这里的字体需要注意,如果想写上中文,必须下载支持中文的字体
# 下面的字体就不支持中文,仅做例子
font = ImageFont.truetype('Chalkduster.ttf', size=50)
color = (255, 255, 255)
x, y = (30, 30)
txt = 'Add text here'
draw = ImageDraw.Draw(img)
draw.text((x-1, y), txt, font=font, fill=color)
draw.text((x+1, y), txt, font=font, fill=color)

在这里插入图片描述

可以根据自己的需求修改重复的次数和移动的坐标


画虚线

这里以一条竖虚线为例,可以根据自己需求修改坐标和虚线的形式

# 竖线
def draw_grid_vertical_line(draw, pos_list, fill, width, gap):
    x_begin, y_begin = pos_list[0]
    x_end, y_end = pos_list[1]
    for y in range(y_begin, y_end, gap):
        draw.line([(x_begin, y), (x_begin, y+gap/2)], fill=fill, width=width)

# 横线
def draw_grid_transverse_line(draw, pos_list, fill, width, gap):
    x_begin, y_begin = pos_list[0]
    x_end, y_end = pos_list[1]
    for x in range(x_begin, x_end, gap):
        draw.line([(x, y_begin), (x+gap/2, y_begin)], fill=fill, width=width)

img = Image.open('这里填图像路径.png')
draw = ImageDraw.Draw(img)
y_pos_list = [(30, 0), (30, img.size[1])]
x_pos_list = [(0, 30), (img.size[0], 30)]
width = 2
gap = 30
draw_grid_vertical_line(draw, y_pos_list, fill='white', width=width, gap=gap)
draw_grid_transverse_line(draw, x_pos_list, fill='red', width=width, gap=gap)

line


长文本自动分行(符号处理)

当我们输入长文本的时候,文字不会自动分行,只会超出图片大小限制,所以我们需要自己写分行函数。
文字选自《桃花源记》。

在这里插入图片描述

这里介绍一个包:textwrap,可以进行自动分行。

import textwrap
import re
from PIL import Image, ImageDraw, ImageFont

用法如下:

txt = 《桃花源记》
img = Image.open('这里填图像路径.png')
draw = ImageDraw.Draw(img)
pos = (30, 30)
text_width = 39  # 自己调整一行的文字宽度
# mac支持的中文字体
font = ImageFont.truetype('Hiragino Sans GB', size=20)
para = textwrap.wrap(txt, width=text_width)
leading = 50  # 文字段落间隔
for i, line in enumerate(para):
    draw.text((pos[0], leading * i + pos[1]), line, 'white', font)

textwrap
可以看到中文标点符号有可能处于句子开头,但正常语法中我们不会以这样,所以需要写个函数处理一下。

punc_pattern = "[,.,。》、—”]+"
def add_long_text(text, text_width):
    para = textwrap.wrap(text, width=text_width)
    write_text = []
    for i, line in enumerate(para):
        write_text.append(line)
        punc = re.search(punc_pattern, line)
        if punc:
            # 如果有标点符号开头
            if punc.start() == 0:
                line = write_text.pop(-1)
                former = write_text.pop(-1)
                former += punc.group()
                write_text.append(former)
                line = line[punc.end():]
                if len(line) > 0:
                    write_text.append(line)
    return write_text

para = add_long_text(txt, text_width)
for i, line in enumerate(para):
    draw.text((pos[0], leading * i + pos[1]), line, 'white', font)

add_long_text
对比一下前图,这个标点开头问题已经解决!