feat: use back_design for back rendering in export
This commit is contained in:
@@ -66,6 +66,15 @@ def get_effective_design(project, card_key):
|
|||||||
return base
|
return base
|
||||||
|
|
||||||
|
|
||||||
|
def get_effective_back_design(project):
|
||||||
|
"""获取背面设计配置,合并 back_design 与 card_overrides['back']"""
|
||||||
|
base = dict(project.back_design or {})
|
||||||
|
overrides = (project.card_overrides or {}).get('back', {})
|
||||||
|
if overrides:
|
||||||
|
base.update(overrides)
|
||||||
|
return base
|
||||||
|
|
||||||
|
|
||||||
def load_image_safe(file_path):
|
def load_image_safe(file_path):
|
||||||
"""加载图片,找不到时返回 None"""
|
"""加载图片,找不到时返回 None"""
|
||||||
if not file_path:
|
if not file_path:
|
||||||
@@ -373,9 +382,13 @@ def draw_joker(canvas, design, which, project, card_key, asset):
|
|||||||
canvas.alpha_composite(block, (w - tw - 4 - pad, h - 2 * th - 6 - pad))
|
canvas.alpha_composite(block, (w - tw - 4 - pad, h - 2 * th - 6 - pad))
|
||||||
|
|
||||||
|
|
||||||
def draw_back(canvas, design, asset):
|
def draw_back(canvas, back_design, asset):
|
||||||
"""绘制背面:素材图 + 位置微调,无素材时退化为文字"""
|
"""绘制背面:素材图 + 位置微调 + 色调叠加,无素材时退化为文字"""
|
||||||
w, h = canvas.size
|
w, h = canvas.size
|
||||||
|
# 填充背景色
|
||||||
|
bg_color = back_design.get('background_color', '#1A237E') or '#1A237E'
|
||||||
|
canvas.paste(hex_to_rgba(bg_color, 255), (0, 0, w, h))
|
||||||
|
|
||||||
body_pad_x = int(w * 0.15)
|
body_pad_x = int(w * 0.15)
|
||||||
body_pad_y_top = int(h * 0.18)
|
body_pad_y_top = int(h * 0.18)
|
||||||
body_pad_y_bot = int(h * 0.22)
|
body_pad_y_bot = int(h * 0.22)
|
||||||
@@ -384,9 +397,9 @@ def draw_back(canvas, design, asset):
|
|||||||
|
|
||||||
if asset:
|
if asset:
|
||||||
try:
|
try:
|
||||||
image_dx = float(design.get('image_dx', 0))
|
image_dx = float(back_design.get('image_dx', 0))
|
||||||
image_dy = float(design.get('image_dy', 0))
|
image_dy = float(back_design.get('image_dy', 0))
|
||||||
image_scale = float(design.get('image_scale', 1))
|
image_scale = float(back_design.get('image_scale', 1))
|
||||||
offset_x = int(body_w * image_dx)
|
offset_x = int(body_w * image_dx)
|
||||||
offset_y = int(body_h * image_dy)
|
offset_y = int(body_h * image_dy)
|
||||||
|
|
||||||
@@ -399,13 +412,26 @@ def draw_back(canvas, design, asset):
|
|||||||
x = body_pad_x + offset_x + (body_w - img.width) // 2
|
x = body_pad_x + offset_x + (body_w - img.width) // 2
|
||||||
y = body_pad_y_top + offset_y + (body_h - img.height) // 2
|
y = body_pad_y_top + offset_y + (body_h - img.height) // 2
|
||||||
canvas.alpha_composite(img, (x, y))
|
canvas.alpha_composite(img, (x, y))
|
||||||
|
|
||||||
|
# 色调叠加
|
||||||
|
pattern_color = back_design.get('pattern_color')
|
||||||
|
if pattern_color:
|
||||||
|
tint = Image.new('RGBA', (w, h), hex_to_rgba(pattern_color, 80))
|
||||||
|
canvas.alpha_composite(tint)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
# 退化:绘制边框 + 文字
|
||||||
|
border_color = back_design.get('border_color', '#C0A050') or '#C0A050'
|
||||||
draw = ImageDraw.Draw(canvas)
|
draw = ImageDraw.Draw(canvas)
|
||||||
|
border_width = int(back_design.get('border_width', 3) or 3)
|
||||||
|
if border_width > 0:
|
||||||
|
half = max(1, border_width // 2)
|
||||||
|
draw.rectangle(((half, half), (w - half, h - half)),
|
||||||
|
outline=hex_to_rgba(border_color, 255), width=border_width)
|
||||||
fnt = make_text_font('Times New Roman', max(40, int(h * 0.08)), bold=True)
|
fnt = make_text_font('Times New Roman', max(40, int(h * 0.08)), bold=True)
|
||||||
text = 'CARD BACK'
|
text = 'CARD BACK'
|
||||||
color = hex_to_rgba(design.get('border_color', '#333333'), 255)
|
color = hex_to_rgba(border_color, 255)
|
||||||
bb = draw.textbbox((0, 0), text, font=fnt)
|
bb = draw.textbbox((0, 0), text, font=fnt)
|
||||||
tw, th = bb[2] - bb[0], bb[3] - bb[1]
|
tw, th = bb[2] - bb[0], bb[3] - bb[1]
|
||||||
draw.text(((w - tw) // 2, (h - th) // 2), text, font=fnt, fill=color)
|
draw.text(((w - tw) // 2, (h - th) // 2), text, font=fnt, fill=color)
|
||||||
@@ -439,12 +465,14 @@ def generate_card_png(project, card_key, resolution='standard'):
|
|||||||
break
|
break
|
||||||
draw_joker(canvas, design, which, project, card_key, asset)
|
draw_joker(canvas, design, which, project, card_key, asset)
|
||||||
elif card_key in ('back', 'card-back'):
|
elif card_key in ('back', 'card-back'):
|
||||||
|
back_design = get_effective_back_design(project)
|
||||||
back_asset = None
|
back_asset = None
|
||||||
for a in project.assets.filter(asset_type='back'):
|
for a in project.assets.filter(asset_type='back'):
|
||||||
p = os.path.join('media', a.file_path) if a.file_path else None
|
p = os.path.join('media', a.file_path) if a.file_path else None
|
||||||
back_asset = load_image_safe(p) if p else None
|
back_asset = load_image_safe(p) if p else None
|
||||||
break
|
break
|
||||||
draw_back(canvas, design, back_asset)
|
draw_back(canvas, back_design, back_asset)
|
||||||
|
return canvas
|
||||||
else:
|
else:
|
||||||
# 'suit-rank'
|
# 'suit-rank'
|
||||||
parts = card_key.split('-')
|
parts = card_key.split('-')
|
||||||
|
|||||||
Reference in New Issue
Block a user