场景
是这样的一个需求,为所有的图片增加一个水印,在图片底部增加联系电话。
思路
- 从图片服务器下载图片到本地
- open本地图片
- 根据手机号生成文本,返回文本的宽高
- 根据文本宽高和图片宽高,确定手机号背景色的起始位置
- 描绘文字和背景
- 保存到本地
- 将新保存图片上传图片服务器
代码
# -*- coding=utf-8 -*-
from PIL import Image, ImageDraw, ImageFont
import requests
def add_text_to_image(image, text):
rgba_image = image.convert('RGBA')
img_width, img_height = rgba_image.size
text_overlay = Image.new('RGBA', rgba_image.size, (255, 255, 255, 0))
image_draw = ImageDraw.Draw(text_overlay)
font = ImageFont.truetype(font_path, int(img_width / 11 * 1.5),
index=0)
text_size_x, text_size_y = image_draw.textsize(text, font=font)
text_x = (img_width - text_size_x) / 2
text_y = img_height - text_size_y - 20
# min_x, min_y, max_x, max_y
image_draw.rectangle(xy=(0, img_height, img_width, text_y), fill="red", outline="#ccc", width=0)
text_xy = (text_x, text_y)
image_draw.text(text_xy, text, font=font, fill=(255, 255, 255, 225))
image_with_text = Image.alpha_composite(rgba_image, text_overlay)
return image_with_text
def download_img(url):
r = requests.request("GET", url)
local_path = "tmp.jpg"
with open(local_path, "wb") as code:
code.write(r.content)
return local_path
def start():
i = 1
max_num = 1000
while i < max_num:
img_url = 'http://test-oss.beijing.aliyun.com/abc.jpg'
loca_url = download_img(img_url)
im_before = Image.open(loca_url)
im_after = add_text_to_image(im_before, phone_num)
im_after.show()
tmp_img_path = 'tmp.png'
im_after.save(tmp_img_path)
# upload_img(tmp_img_path, i)
# i += 1
break
font_path = 'wqyzht.ttf'
phone_num = "15771264412"
if __name__ == '__main__':
start()
总结
遇到了这样的几个问题
1.OSError: cannot write mode RGBA as JPEG
这个问题就是打开图片和保存图片的方式不同,打开的时候是使用的RGBA,保存成jpg就会报错,以为rgba多了一个透明度,所以保存jpg会报错。
两种解决方案
a.打开方式改变rgb
b.保存成png即可
2.如何实现纯颜色背景块
在很多加水印的时候都要加个底色,可以使用 image_draw.rectangle 来解决这个问题,并且还支持边框
# min_x, min_y, max_x, max_y
image_draw.rectangle(xy=(0, img_height, img_width, text_y), fill="red", outline="#ccc", width=0)