前言

最近这个在Django后台上传图片时自动加水印的需求,各种google和百度一个能用的都没有,最终在胡阳大神的书《Django企业开发实战:高效Python Web框架 指南》中找到了答案,在此特地感谢,不过大神的代码好像用的是默认字体,最终呈现的效果不太好看,而且水印是在图片的最下方居中显示,也不太符合我们的一般放在右下角的习惯,我优化了一下代码。

实战

以本站的后端Django项目为例,假设你的你用Django框架的脚手架命令新建的项目叫DjangoBlog4Life,那么在你的这个目录../DjangoBlog4Life/DjangoBlog4Life下面新建一个叫storage.py的文件放入下面代码:

from io import BytesIO
import os

from django.core.files.storage import FileSystemStorage
from django.core.files.uploadedfile import InMemoryUploadedFile

from PIL import Image, ImageDraw, ImageFont


class WatermarkStorage(FileSystemStorage):
    def save(self, name, content, max_length=None):
        # 处理逻辑
        if 'image' in content.content_type:
            # 加水印
            image = self.watermark_with_text(content, 'https://www.sharpgan.com/', "192,192,192")
            content = self.convert_image_to_file(image, name)

        return super().save(name, content, max_length=max_length)

    def convert_image_to_file(self, image, name):
        temp = BytesIO()
        image.save(temp, format='PNG')
        file_size = temp.tell()
        return InMemoryUploadedFile(temp, None, name, 'image/png', file_size, None)

    def watermark_with_text(self, file_obj, text, color):
        img = Image.open(file_obj)
        size = img.size
        x, y = size[0], size[1]
        #print(x,y)
        draw = ImageDraw.Draw(img)
        font_path = os.path.dirname(os.path.abspath(__file__))
        ttfront = ImageFont.truetype(os.path.join(font_path, 'arial.ttf'), 35)
        text_w, text_h = draw.textsize(text, ttfront)
        xy_coordinate = x-(text_w+10), y-text_h
        rgb_color_str = color.split(',')
        rgb_color = int(rgb_color_str[0]), int(rgb_color_str[1]),int(rgb_color_str[2])
        draw.text(xy_coordinate, text, fill=rgb_color, font=ttfront)
        return img

上述代码已经在Django 3.2.16 LTS中亲测可用,需要注意的是需要你自己把代码中的save()方法中的水印文字也就是本站的网址https://www.sharpgan.com/自行修改为你想要的,然后就是你自己去google或百度搜一个叫arial.ttf的字体文件,放到和storage.py这个文件同一级目录里面。

最后,在你的settings.py中加入下面一行配置即可:

DEFAULT_FILE_STORAGE='DjangoBlog4Life.storage.WatermarkStorage'

下面展示一下成果:

2022年10月最新基于Django3.2.16实现对上传图片加水印

如果上述代码有帮助到你的话,不要忘记第一时间评论告诉我哦,我收到邮件通知后会立刻回复你的。