pillow相关实战操作
一. pillow
Python图像处理库。
1. 文档
2. 安装
pip install pillow
二. 实战操作
1. 图片中实现文字书写超过宽度自动换行
from PIL import Image, ImageDraw, ImageFont
class ImgText:
font = ImageFont.truetype("宋体.ttf", 24)
def __init__(self, text):
# 预设宽度 可以修改成你需要的图片宽度
self.width = 100
# 文本
self.text = text
# 段落 , 行数, 行高
self.duanluo, self.note_height, self.line_height = self.split_text()
def get_duanluo(self, text):
txt = Image.new('RGBA', (100, 100), (255, 255, 255, 0))
draw = ImageDraw.Draw(txt)
# 所有文字的段落
duanluo = ""
# 宽度总和
sum_width = 0
# 几行
line_count = 1
# 行高
line_height = 0
for char in text:
width, height = draw.textsize(char, ImgText.font)
sum_width += width
if sum_width > self.width: # 超过预设宽度就修改段落 以及当前行数
line_count += 1
sum_width = 0
duanluo += '\n'
duanluo += char
line_height = max(height, line_height)
if not duanluo.endswith('\n'):
duanluo += '\n'
return duanluo, line_height, line_count
def split_text(self):
# 按规定宽度分组
max_line_height, total_lines = 0, 0
allText = []
for text in self.text.split('\n'):
duanluo, line_height, line_count = self.get_duanluo(text)
max_line_height = max(line_height, max_line_height)
total_lines += line_count
allText.append((duanluo, line_count))
line_height = max_line_height
total_height = total_lines * line_height
return allText, total_height, line_height
def draw_text(self):
"""
绘图以及文字
:return:
"""
note_img = Image.open("demo.png").convert("RGBA")
draw = ImageDraw.Draw(note_img)
# 左上角开始
x, y = 0, 0
for duanluo, line_count in self.duanluo:
draw.text((x, y), duanluo, fill=(255, 0, 0), font=ImgText.font)
y += self.line_height * line_count
note_img.save("result.png")
if __name__ == '__main__':
n = ImgText(
"一切皆往事经过这里" * 5)
n.draw_text()
测试用的图片:

注意事项:
- 有一些字体文件是不能够书写中文的。
2. 图片上写文字并旋转文字
from PIL import Image, ImageDraw, ImageFont
def draw_rotated_text(image, font, text, angle, x, y):
txt = Image.new(image.mode, font.getsize(text))
d = ImageDraw.Draw(txt)
d.text((0, 0), text, font=font, fill=(255, 0, 0))
txt = txt.rotate(angle, expand=1)
image.paste(txt, (int(x - txt.width/2), int(y - txt.height/2)), txt)
def image_text():
image = Image.open('bg.png').convert("RGBA")
font = ImageFont.truetype('demo.ttf', 50)
draw_rotated_text(image, font, "zero", 0, image.width/2, image.height/2)
draw_rotated_text(image, font, "ninety", 90, image.width/2, image.height/2)
draw_rotated_text(image, font, "onetwenty", 120, image.width/2, image.height/2)
image.show()
if __name__ == '__main__':
image_text()
3. 实现图片中某个区域的高斯模糊
from PIL import Image, ImageFilter
class MyGaussianBlur(ImageFilter.Filter):
name = "GaussianBlur"
def __init__(self, radius=2, bounds=None):
"""
bounds裁剪的矩形,作为一个(left,up,right,below)的元组。
left:与左边界的距离
up:与上边界的距离
right:还是与左边界的距离
below:还是与上边界的距离
:param radius:
:param bounds:
"""
self.radius = radius
self.bounds = bounds
def filter(self, image):
if self.bounds:
clips = image.crop(self.bounds).gaussian_blur(self.radius)
image.paste(clips, self.bounds)
return image
else:
return image.gaussian_blur(self.radius)
def main():
image = Image.open('demo.jpg')
print(image.size) # (1024, 1024)
bounds = (16, 945, 415, 1000) # 高斯模糊的区域
radius = 10 # 高斯模糊的值
image = image.filter(MyGaussianBlur(radius=radius, bounds=bounds))
# image.show() # 查看生成的图片效果
image.save("demo2.png") # 保存为demo2.png
if __name__ == '__main__':
main()
4. 透明水印放置在背景图上方
import numpy as np
from PIL import Image
import uuid
def blend_image(fore_image, background):
"""
:param fore_image: 水印图片
:param background: 背景图片
:return:
"""
# 读入图片
background = Image.open(background).convert('RGB')
h = Image.new('RGBA', background.size, color=(0, 0, 0, 0))
# 加载图片水印
mark = Image.open(fore_image)
box = (223, 956, 259, 980) # 水印放置的位置
region = mark.resize((box[2] - box[0], box[3] - box[1]))
h.paste(region, box)
fore_image = h.resize(background.size)
# 图片加权合成
scope_map = np.array(fore_image)[:, :, -1] / 255
scope_map = scope_map[:, :, np.newaxis]
scope_map = np.repeat(scope_map, repeats=3, axis=2)
res_image = np.multiply(scope_map, np.array(fore_image)[:, :, :3]) + np.multiply((1 - scope_map),
np.array(background))
# output_path = str(uuid.uuid1()) + '.png'
# 保存图片
res_image = Image.fromarray(np.uint8(res_image))
res_image.show()
# res_image.save(output_path)
# return output_path
if __name__ == '__main__':
blend_image('mark2.png', 'demo2.png')
注意事项
- 如果遇到背景图片是白色的话,水印位置会变成黑色的。
5. 给图片添加图片水印
from PIL import Image
def main():
# 加载背景图
background = Image.open('demo1.jpg').convert('RGBA')
# 加载图片水印
mark = Image.open('mark.png')
box = (16, 945, 415, 1000)
region = mark.resize((box[2] - box[0], box[3] - box[1]))
background.paste(region, box)
background.show()
if __name__ == '__main__':
main()
解释box = (16, 945, 415, 1000)中的值:这里是使用了两个坐标点。长方形的形状。第一个点是左上角的坐标(16, 945)。第二个点是右下角的坐标(415, 1000)。这两个点确定之后就可以构成一个矩形了。上面的程序我是把整张图片水印放贴在背景图上的。我采用的demo1.png的尺寸是:1024*1024。mark.png是:282*40。
实现后的效果如下所示:


浙公网安备 33010602011771号