jinye_huang dcfd820ca4 feat(poster_v2): 智能海报生成引擎 v1.0
- 新增 PosterSmartEngine,AI 生成文案 + 海报渲染
- 5 种布局支持文本换行和自适应字体
- 修复按钮/标签颜色显示问题
- 优化渐变遮罩和内容区域计算
- Prompt 优化:标题格式为产品名+描述
2025-12-10 15:04:59 +08:00

134 lines
3.9 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
效果渲染器
"""
from typing import Tuple, List
from PIL import Image, ImageDraw, ImageFilter
class EffectRenderer:
"""效果渲染器"""
@staticmethod
def create_gradient(
size: Tuple[int, int],
start_color: Tuple,
end_color: Tuple,
direction: str = "vertical"
) -> Image.Image:
"""
创建渐变图像
Args:
size: (width, height)
start_color: 起始颜色 RGB 或 RGBA
end_color: 结束颜色 RGB 或 RGBA
direction: "vertical""horizontal"
"""
width, height = size
gradient = Image.new("RGBA", size)
draw = ImageDraw.Draw(gradient)
# 支持 RGB 和 RGBA
r1, g1, b1 = start_color[:3]
a1 = start_color[3] if len(start_color) > 3 else 255
r2, g2, b2 = end_color[:3]
a2 = end_color[3] if len(end_color) > 3 else 255
if direction == "vertical":
for i in range(height):
ratio = i / height
r = int(r1 * (1 - ratio) + r2 * ratio)
g = int(g1 * (1 - ratio) + g2 * ratio)
b = int(b1 * (1 - ratio) + b2 * ratio)
a = int(a1 * (1 - ratio) + a2 * ratio)
draw.line([(0, i), (width, i)], fill=(r, g, b, a))
else:
for i in range(width):
ratio = i / width
r = int(r1 * (1 - ratio) + r2 * ratio)
g = int(g1 * (1 - ratio) + g2 * ratio)
b = int(b1 * (1 - ratio) + b2 * ratio)
a = int(a1 * (1 - ratio) + a2 * ratio)
draw.line([(i, 0), (i, height)], fill=(r, g, b, a))
return gradient
@staticmethod
def create_frosted_glass(
image: Image.Image,
region: Tuple[int, int, int, int],
blur_radius: int = 25,
overlay_alpha: int = 230
) -> Image.Image:
"""
创建毛玻璃效果
Args:
image: 原始图像
region: 毛玻璃区域 (x1, y1, x2, y2)
blur_radius: 模糊半径
overlay_alpha: 白色遮罩透明度
"""
x1, y1, x2, y2 = region
# 裁剪区域
cropped = image.crop(region)
# 模糊
blurred = cropped.filter(ImageFilter.GaussianBlur(blur_radius))
# 白色遮罩
overlay = Image.new("RGBA", (x2 - x1, y2 - y1), (255, 255, 255, overlay_alpha))
# 合成
result = Image.alpha_composite(blurred.convert("RGBA"), overlay)
return result
@staticmethod
def create_shadow(
size: Tuple[int, int],
radius: int = 28,
blur: int = 15,
alpha: int = 20,
offset: Tuple[int, int] = (0, 8)
) -> Image.Image:
"""
创建阴影图层
Args:
size: 阴影尺寸
radius: 圆角半径
blur: 模糊半径
alpha: 阴影透明度
offset: 偏移量
"""
width, height = size
padding = blur * 2
shadow = Image.new("RGBA", (width + padding * 2, height + padding * 2), (0, 0, 0, 0))
draw = ImageDraw.Draw(shadow)
draw.rounded_rectangle(
[padding + offset[0], padding + offset[1],
width + padding + offset[0], height + padding + offset[1]],
radius=radius,
fill=(0, 0, 0, alpha)
)
shadow = shadow.filter(ImageFilter.GaussianBlur(blur))
return shadow
@staticmethod
def darken_overlay(
image: Image.Image,
alpha: int = 60
) -> Image.Image:
"""添加暗化遮罩层"""
overlay = Image.new("RGBA", image.size, (0, 0, 0, alpha))
return Image.alpha_composite(image.convert("RGBA"), overlay)