Files
sspai-100-hours-series-python/projects/click-cli/watermark/markers.py

76 lines
1.7 KiB
Python

from __future__ import annotations
import logging
from PIL import Image, ImageDraw, ImageFont
from watermark.helper import adjust_marker_layer, set_opacity
logger = logging.getLogger("watermark.markers")
def text_marker(
font_or_path,
content,
size=20,
color="black",
rotation=0,
alpha: int | float = 1,
**kwargs,
):
# set font and get the font size which determined by content.
font = ImageFont.truetype(font_or_path, size=size)
CONTENT_SIZE = font.getsize(text=content)
layer = Image.new("RGBA", CONTENT_SIZE)
plot = ImageDraw.Draw(layer)
plot.text(
xy=(0, 0), # x=0, y=0
text=content,
fill=color,
font=font,
align="center",
)
if rotation:
layer = layer.rotate(rotation, expand=True)
if alpha:
layer = set_opacity(layer, alpha)
return layer
def image_marker(fpath, zoom=0.8, rotation=0, alpha: int | float = 1, **kwargs):
# convert image watermarker to RGBA mode.
layer = Image.open(fpath).convert("RGBA")
width, height = layer.size
if 0 <= zoom <= 1:
layer = layer.resize((int(width * zoom), int(height * zoom)))
if rotation:
layer = layer.rotate(rotation, expand=True)
if alpha:
layer = set_opacity(layer, alpha)
return layer
def make(path, *, text=None, image=None, **kwargs):
pic = Image.open(path).convert("RGBA")
if text and not image:
marker = text_marker(text, **kwargs)
elif not text and image:
marker = image_marker(image, **kwargs)
else:
raise ValueError("use text or image")
layer = adjust_marker_layer(pic, marker, **kwargs)
marked = Image.alpha_composite(pic, layer)
return marked