• Python实现给图片加水印功能


    前言#

    最近忙得连轴转,很久没更新博客了,代码倒是没啥写,积累了好些东西,接下来一有时间就来更新吧~

    本文记录使用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//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是个代码片段工具,最近刚刚用起来,感觉还蛮不错的

    有时候用来记录和分享一些代码片段很方便,不需要专门创建一个仓库

  • 相关阅读:
    【被误用的feof与文件操作读取结束的正确判定】
    Hive基础(DML 数据操作)
    再获5G RedCap能力认证!宏电5G RedCap工业智能网关通过中国联通5G物联网OPENLAB开放实验室测试验证
    基本网络知识的介绍
    使用LlamaIndex构建自己的PandasAI
    全网监控 nginx 部署 zabbix6.0
    ECCV 2022 | STDANet:基于可变形注意力的视频去模糊
    UnityPlayerActivity详解
    超简单!!!搭建阿克曼ROS小车
    RabbitMQ入门 -- 阿里云服务器安装RabbitMQ
  • 原文地址:https://www.cnblogs.com/deali/p/16742548.html