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/<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 是個代碼片段工具,最近剛剛用起來,感覺還蠻不錯的

有時候用來記錄和分享一些代碼片段很方便,不需要專門創建一個倉庫

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/c7rDPgExAJACvWO5ZAUgPA