feat: 背面图案支持 + 大小王素材位置微调 + 10号牌pip修复
This commit is contained in:
@@ -32,7 +32,7 @@ LAYOUT_POSITIONS = {
|
||||
7: [(0.30, 0.15), (0.70, 0.15), (0.50, 0.35), (0.30, 0.55), (0.70, 0.55), (0.30, 0.85), (0.70, 0.85)],
|
||||
8: [(0.30, 0.15), (0.70, 0.15), (0.50, 0.32), (0.30, 0.50), (0.70, 0.50), (0.50, 0.68), (0.30, 0.85), (0.70, 0.85)],
|
||||
9: [(0.30, 0.15), (0.70, 0.15), (0.50, 0.30), (0.22, 0.50), (0.50, 0.50), (0.78, 0.50), (0.50, 0.70), (0.30, 0.85), (0.70, 0.85)],
|
||||
10: [(0.30, 0.15), (0.70, 0.15), (0.30, 0.35), (0.70, 0.35), (0.50, 0.50), (0.30, 0.65), (0.70, 0.65), (0.30, 0.85), (0.70, 0.85)],
|
||||
10: [(0.30, 0.15), (0.70, 0.15), (0.30, 0.35), (0.70, 0.35), (0.50, 0.45), (0.50, 0.55), (0.30, 0.65), (0.70, 0.65), (0.30, 0.85), (0.70, 0.85)],
|
||||
}
|
||||
|
||||
|
||||
@@ -300,10 +300,25 @@ def draw_joker(canvas, design, which, project, card_key, asset):
|
||||
body_h = h - body_pad_y_top - body_pad_y_bot
|
||||
if asset:
|
||||
try:
|
||||
img = asset.copy()
|
||||
img.thumbnail((body_w, body_h), Image.LANCZOS)
|
||||
canvas.alpha_composite(img, (body_pad_x + (body_w - img.width) // 2,
|
||||
body_pad_y_top + (body_h - img.height) // 2))
|
||||
half_h = body_h // 2
|
||||
image_dx = float(design.get('image_dx', 0))
|
||||
image_dy = float(design.get('image_dy', 0))
|
||||
image_scale = float(design.get('image_scale', 1))
|
||||
offset_x = int(body_w * image_dx)
|
||||
offset_y = int(body_h * image_dy)
|
||||
|
||||
img_copy = asset.copy()
|
||||
if image_scale != 1:
|
||||
sw = max(1, int(img_copy.width * image_scale))
|
||||
sh = max(1, int(img_copy.height * image_scale))
|
||||
img_copy = img_copy.resize((sw, sh), Image.LANCZOS)
|
||||
img_copy.thumbnail((body_w, half_h), Image.LANCZOS)
|
||||
x = body_pad_x + offset_x + (body_w - img_copy.width) // 2
|
||||
y_top = body_pad_y_top + offset_y + (half_h - img_copy.height) // 2
|
||||
canvas.alpha_composite(img_copy, (x, y_top))
|
||||
img_flipped = img_copy.transpose(Image.FLIP_TOP_BOTTOM)
|
||||
y_bot = body_pad_y_top + half_h + offset_y + (half_h - img_flipped.height) // 2
|
||||
canvas.alpha_composite(img_flipped, (x, y_bot))
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
@@ -339,6 +354,44 @@ def draw_joker(canvas, design, which, project, card_key, asset):
|
||||
canvas.alpha_composite(block, (w - tw - 4 - pad, h - 2 * th - 6 - pad))
|
||||
|
||||
|
||||
def draw_back(canvas, design, asset):
|
||||
"""绘制背面:素材图 + 位置微调,无素材时退化为文字"""
|
||||
w, h = canvas.size
|
||||
body_pad_x = int(w * 0.15)
|
||||
body_pad_y_top = int(h * 0.18)
|
||||
body_pad_y_bot = int(h * 0.22)
|
||||
body_w = w - 2 * body_pad_x
|
||||
body_h = h - body_pad_y_top - body_pad_y_bot
|
||||
|
||||
image_dx = float(design.get('image_dx', 0))
|
||||
image_dy = float(design.get('image_dy', 0))
|
||||
image_scale = float(design.get('image_scale', 1))
|
||||
offset_x = int(body_w * image_dx)
|
||||
offset_y = int(body_h * image_dy)
|
||||
|
||||
if asset:
|
||||
try:
|
||||
img = asset.copy()
|
||||
if image_scale != 1:
|
||||
sw = max(1, int(img.width * image_scale))
|
||||
sh = max(1, int(img.height * image_scale))
|
||||
img = img.resize((sw, sh), Image.LANCZOS)
|
||||
img.thumbnail((body_w, body_h), Image.LANCZOS)
|
||||
x = body_pad_x + offset_x + (body_w - img.width) // 2
|
||||
y = body_pad_y_top + offset_y + (body_h - img.height) // 2
|
||||
canvas.alpha_composite(img, (x, y))
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
draw = ImageDraw.Draw(canvas)
|
||||
fnt = make_text_font('Times New Roman', max(40, int(h * 0.08)), bold=True)
|
||||
text = 'CARD BACK'
|
||||
color = hex_to_rgba(design.get('border_color', '#333333'), 255)
|
||||
bb = draw.textbbox((0, 0), text, font=fnt)
|
||||
tw, th = bb[2] - bb[0], bb[3] - bb[1]
|
||||
draw.text(((w - tw) // 2, (h - th) // 2), text, font=fnt, fill=color)
|
||||
|
||||
|
||||
def generate_card_png(project, card_key, resolution='standard'):
|
||||
"""根据项目配置生成单张牌 PNG"""
|
||||
scale_map = {'standard': 1, 'hd': 2, 'ultra-hd': 4}
|
||||
@@ -366,14 +419,12 @@ def generate_card_png(project, card_key, resolution='standard'):
|
||||
break
|
||||
draw_joker(canvas, design, which, project, card_key, asset)
|
||||
elif card_key in ('back', 'card-back'):
|
||||
# 简化:背面同整体背景 + 一行文字
|
||||
draw = ImageDraw.Draw(canvas)
|
||||
fnt = make_text_font('Times New Roman', max(40, int(h * 0.08)), bold=True)
|
||||
text = 'CARD BACK'
|
||||
color = hex_to_rgba(design.get('border_color', '#333333'), 255)
|
||||
bb = draw.textbbox((0, 0), text, font=fnt)
|
||||
tw, th = bb[2] - bb[0], bb[3] - bb[1]
|
||||
draw.text(((w - tw) // 2, (h - th) // 2), text, font=fnt, fill=color)
|
||||
back_asset = None
|
||||
for a in project.assets.filter(asset_type='back'):
|
||||
p = os.path.join('media', a.file_path) if a.file_path else None
|
||||
back_asset = load_image_safe(p) if p else None
|
||||
break
|
||||
draw_back(canvas, design, back_asset)
|
||||
else:
|
||||
# 'suit-rank'
|
||||
parts = card_key.split('-')
|
||||
|
||||
Reference in New Issue
Block a user