mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-09-05 23:57:19 +08:00
Initial commit
This commit is contained in:
@@ -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()
|
||||
Reference in New Issue
Block a user