Initial commit

This commit is contained in:
shiyu
2025-08-24 18:49:00 +08:00
parent 99866befe1
commit 6b0f2bd4fa
129 changed files with 11587 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
from .base import BaseProcessor
from typing import Dict, Any
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
from fastapi.responses import Response
from services.logging import LogService
class ImageWatermarkProcessor:
name = "图片水印"
supported_exts = ["jpg", "jpeg", "png", "bmp"]
config_schema = [
{"key": "text", "label": "水印文字", "type": "string", "required": True},
{
"key": "position",
"label": "位置",
"type": "select",
"required": False,
"default": "bottom-right",
"options": [
{"value": "top-left", "label": "左上"},
{"value": "center", "label": "居中"},
{"value": "bottom-right", "label": "右下"},
],
},
{"key": "font_size", "label": "字体大小", "type": "number", "required": False, "default": 24},
]
produces_file = True
async def process(self, input_bytes: bytes,path: str, config: Dict[str, Any]) -> Response:
text = config.get("text", "")
position = config.get("position", "bottom-right")
font_size = int(config.get("font_size", 24))
img = Image.open(BytesIO(input_bytes)).convert("RGBA")
watermark = Image.new("RGBA", img.size)
draw = ImageDraw.Draw(watermark)
try:
font = ImageFont.truetype("arial.ttf", font_size)
except Exception:
font = ImageFont.load_default()
w, h = img.size
try:
text_w, text_h = font.getsize(text)
except AttributeError:
bbox = draw.textbbox((0, 0), text, font=font)
text_w, text_h = bbox[2] - bbox[0], bbox[3] - bbox[1]
if position == "bottom-right":
xy = (w - text_w - 10, h - text_h - 10)
elif position == "top-left":
xy = (10, 10)
else:
xy = (w // 2 - text_w // 2, h // 2 - text_h // 2)
draw.text(xy, text, font=font, fill=(255, 255, 255, 128))
out = Image.alpha_composite(img, watermark)
buf = BytesIO()
out.convert("RGB").save(buf, format="JPEG")
await LogService.info(
"processor:image_watermark",
f"Watermarked image {path}",
details={"path": path, "config": config},
)
return Response(content=buf.getvalue(), media_type="image/jpeg")
PROCESSOR_TYPE = "image_watermark"
PROCESSOR_NAME = ImageWatermarkProcessor.name
SUPPORTED_EXTS = ImageWatermarkProcessor.supported_exts
CONFIG_SCHEMA = ImageWatermarkProcessor.config_schema
PROCESSOR_FACTORY = lambda: ImageWatermarkProcessor()