曦远 (DealiAxy)一份私人的文字刊物

StarBlog
返回文章列表折页手记阅读全文
Python

Implementing Image Watermarking with Python

Preface I've been so busy lately that I haven't updated the blog in a long time. I haven't written much code, but I've accumulated quite a few things. I'll start updating whenever I have some time~ This article records the process of implementing image watermarking with Python Let's see the results first Using the WeChat official account cover as material The original image looks like this codelab The effect after adding a watermark temp Implementation code The main implementation is based on a GitHub project: https://github.com/2Dou/watermarker It uses the Pillow library. Please

曦远 (DealiAxy)约 13 分钟
目录8 个章节

Preface

I've been so busy lately that I haven't updated the blog in a long time. I haven't written much code, but I've accumulated quite a few things. I'll start updating whenever I have some time~

This article records the process of implementing image watermarking with Python

Let's See the Results First

Using the WeChat official account cover as material

The original image looks like this

codelab

The effect after adding a watermark

temp

Implementation Code

The main implementation is based on a GitHub project: https://github.com/2Dou/watermarker

It uses the Pillow library. Please install it before use. Generally, you also need this library to save images in Django, so this dependency can be considered fairly friendly.

This project is a command-line tool, but I use it in a Django project, so I customized it

The core code is as follows (this code is inside a class I encapsulated)

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

I encapsulated this watermarking functionality into a class

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):
        ...

Usage

Simple Usage

w = Watermarker('codelab.png', '程序设计实验室', size=200)
# 显示加了水印的图片
w.show()
# 保存
w.save('save.png')

Using in Django

Taking my encapsulated DjangoStarter framework as an example, write the Image object directly into the HTTP response

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')

URL configuration

from django.urls import path
from . import views

app_name = 'photo'
urlpatterns = [
    path('photo/<int:pk>/add_watermark/', views.add_watermark, name='add_watermark'),
]

After this configuration, visit the URL: http://[host]:[port]/photo/1/add_watermark/

and you can see the watermarked image

The effect is as follows

image-20220929172532412

Done~

Command-Line Usage

The project this one is based on

Complete Code

GitHub gist address: https://gist.github.com/Deali-Axy/e22ea79bfbe785f9017b2e3cd7fdb3eb

PS: GitHub gist is a code snippet tool. I just started using it recently, and it feels pretty nice

Sometimes it's convenient for recording and sharing code snippets, without needing to create a dedicated repository

_EOF_

Implementing Image Watermarking with Python

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…