- 新增 PosterSmartEngine,AI 生成文案 + 海报渲染 - 5 种布局支持文本换行和自适应字体 - 修复按钮/标签颜色显示问题 - 优化渐变遮罩和内容区域计算 - Prompt 优化:标题格式为产品名+描述
134 lines
3.9 KiB
Python
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)
|