Python实现给图片加水印功能
前言 最近忙得连轴转,很久没更新博客了,代码倒是没啥写,积累了好些东西,接下来一有时间就来更新吧~ 本文记录使用Python实现给图片添加水印的功能实现过程 先看效果 把公众号的封面作为素材 原图是这样的 codelab 加个水印的效果 temp 实现代码 主要实现是参考GitHub上一个项目的:https://github.com/2Dou/watermarker 用到了Pillow库,使用前请
目录8 个章节
前言
最近忙得连轴转,很久没更新博客了,代码倒是没啥写,积累了好些东西,接下来一有时间就来更新吧~
本文记录使用Python实现给图片添加水印的功能实现过程
先看效果
把公众号的封面作为素材
原图是这样的

加个水印的效果

实现代码
主要实现是参考GitHub上一个项目的:https://github.com/2Dou/watermarker
用到了Pillow库,使用前请先安装,一般要在Django中保存图片也需要安装这个库的。所以这个依赖可以说是比较友好的。
这个项目是命令行工具,而我是在Django项目中用,所以我做了魔改
核心代码如下(这段代码是在我封装的一个类里面)
origin_image = Image.open(self.image_path)
origin_image = ImageOps.exif_transpose(origin_image)
# 计算字体的宽度、高度
width = len(self.text) * self.size
height = round(self.size * self.font_height_crop)
# 创建水印图片
watermark_image = Image.new(mode='RGBA', size=(width, height))
# 生成文字
draw_table = ImageDraw.Draw(im=watermark_image)
draw_table.text(
xy=(0, 0),
text=self.text,
fill=self.color,
font=ImageFont.truetype(self.font_file, size=self.size)
)
del draw_table
# 裁剪空白
watermark_image = Watermarker.crop_image_edge(watermark_image)
# 设置透明度
Watermarker.set_image_opacity(watermark_image, self.opacity)
# 计算斜边长度
c = int(math.sqrt(origin_image.size[0] * origin_image.size[0] + origin_image.size[1] * origin_image.size[1]))
# 以斜边长度为宽高创建大图(旋转后大图才足以覆盖原图)用于覆盖在原图之上
watermark_mask = Image.new(mode='RGBA', size=(c, c))
# 在大图上生成水印文字
y, idx = 0, 0
while y < c:
# 制造x坐标错位
x = -int((watermark_image.size[0] + self.space) * 0.5 * idx)
idx = (idx + 1) % 2
while x < c:
# 在该位置粘贴mark水印图片
watermark_mask.paste(watermark_image, (x, y))
x = x + watermark_image.size[0] + self.space
y = y + watermark_image.size[1] + self.space
# 将大图旋转一定角度
watermark_mask = watermark_mask.rotate(self.angle)
# 在原图上添加大图水印
if origin_image.mode != 'RGBA':
origin_image = origin_image.convert('RGBA')
origin_image.paste(
watermark_mask, # 大图
(int((origin_image.size[0] - c) / 2), int((origin_image.size[1] - c) / 2)), # 坐标
mask=watermark_mask.split()[3]
)
del watermark_mask
我把这个加水印的功能封装成了一个类
class Watermarker(object):
"""图片水印工具"""
django_support = False
def __init__(
self, image_path: str, text: str,
angle=30,
color='#8B8B1B',
font_file='青鸟华光简琥珀.ttf',
font_height_crop=1.2,
opacity=0.15,
quality=80,
size=50,
space=75,
):
...
@staticmethod
def set_image_opacity(image: Image, opacity: float):
...
@staticmethod
def crop_image_edge(image: Image):
...
@property
def image(self):
...
def save(self, file_path: str, image_format: str = 'png'):
...
def show(self):
...
使用方法
简单使用
w = Watermarker('codelab.png', '程序设计实验室', size=200)
# 显示加了水印的图片
w.show()
# 保存
w.save('save.png')
在Django中使用
以我封装的 DjangoStarter 框架为例,直接把Image对象写入Http响应里
from io import BytesIO
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponse
from django_starter.contrib.watermark import Watermarker
def add_watermark(request, pk):
text = request.GET.get('text', timezone.now().strftime('%Y-%m-%d %H:%M:%S'))
photo = get_object_or_404(Photo, pk=pk)
image = Watermarker(photo.photo.path, text).image
# 将图片保存到内存中
with BytesIO() as f:
image.save(f, 'png')
# 返回图片数据流
return HttpResponse(f.getvalue(), content_type='image/png')
路由配置
from django.urls import path
from . import views
app_name = 'photo'
urlpatterns = [
path('photo/<int:pk>/add_watermark/', views.add_watermark, name='add_watermark'),
]
这样配置之后,访问链接:http://[host]:[port]/photo/1/add_watermark/
就可以看到加了水印的图片了
效果如下

搞定~
命令行使用
本项目参考的那个项目
完整代码
GitHub gist地址:https://gist.github.com/Deali-Axy/e22ea79bfbe785f9017b2e3cd7fdb3eb
PS:Github gist是个代码片段工具,最近刚刚用起来,感觉还蛮不错的
有时候用来记录和分享一些代码片段很方便,不需要专门创建一个仓库
_EOF_
Python实现给图片加水印功能
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
Python踩坑:类与类对象类型参数传递与使用
前言 对初学者来说,Python确实简单好用,毕竟动态类型语言,不用定义就可以拿来用,类型之间随意转换简直不要太方便,因此Python用来写写小脚本,爬虫程序什么的,没什么问题。 不过,一旦用来开发稍微大型一点的项目,例如搭建一个Web应用,就会遇到一些问题,一般缺乏经验的人都会陷入某些坑中。= =... 坑 先说坑,函数参数类型是一坑,类与类的对象这又是一坑。 虽然之前用其他静态类型语言(例如C
2022-05-27 · Python · 约 1 分钟
现代 Python 程序优雅处理日期时间的避坑指南
Python 时间处理还是得踩坑?`datetime`、`time`、`calendar` 搞得人头大,Naive vs Aware 时区陷阱更是坑爹。2026 年了还用 `pytz`?标准库 `ZoneInfo` 加上 `Pendulum`、`Arrow` 才叫现代化,至少不用再写反人类的时间字符串解析。数据库存 UTC,前端传 ISO 8601,简单点行不行?
2026-03-25 · Python · 约 1 分钟
Python中的双端队列:collections-deque
关于deque 起因是我想做一个「手气不错」的功能,为了提高性能,打算用队列实现,偶然在Stack Overflow看到一个讨论「Efficiency of using a Python list as a queue」 python的list有pop方法,可以实现队列的取出功能,不过据说性能一般般,高赞回答说的 You won't run out of memory using the list
2021-12-18 · Python · 约 1 分钟
Python-本地时间和UTC时间转换
代码 import time import datetime def utc2local(utc_st): UTC时间转本地时间(+8: 00) now_stamp = time.time() local_time = datetime.datetime.fromtimestamp(now_stamp) utc_time = datetime.datetime.ut
2021-12-18 · Python · 约 1 分钟
讨论
共 0 条加载评论中…