codepet 1.0.9 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/polaroid_image.py +41 -32
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""拍立得相框 —
|
|
2
|
+
"""拍立得相框 — 像素风 PNG 图片版"""
|
|
3
3
|
|
|
4
4
|
import sys, os, json, platform
|
|
5
|
-
from PIL import Image, ImageDraw, ImageFont
|
|
5
|
+
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
|
6
6
|
|
|
7
7
|
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
8
8
|
SPRITE_DIR = os.path.join(SCRIPT_DIR, "..", "sprites")
|
|
@@ -15,27 +15,15 @@ SCENE_ZH = {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
def load_font(size):
|
|
18
|
-
"""跨平台加载字体"""
|
|
19
18
|
system = platform.system()
|
|
20
19
|
candidates = []
|
|
21
20
|
if system == "Darwin":
|
|
22
|
-
candidates = [
|
|
23
|
-
"/System/Library/Fonts/PingFang.ttc",
|
|
24
|
-
"/System/Library/Fonts/Hiragino Sans GB.ttc",
|
|
25
|
-
]
|
|
21
|
+
candidates = ["/System/Library/Fonts/PingFang.ttc", "/System/Library/Fonts/Hiragino Sans GB.ttc"]
|
|
26
22
|
elif system == "Windows":
|
|
27
23
|
windir = os.environ.get("WINDIR", "C:\\Windows")
|
|
28
|
-
candidates = [
|
|
29
|
-
os.path.join(windir, "Fonts", "msyh.ttc"),
|
|
30
|
-
os.path.join(windir, "Fonts", "simhei.ttf"),
|
|
31
|
-
os.path.join(windir, "Fonts", "arial.ttf"),
|
|
32
|
-
]
|
|
24
|
+
candidates = [os.path.join(windir, "Fonts", "msyh.ttc"), os.path.join(windir, "Fonts", "simhei.ttf"), os.path.join(windir, "Fonts", "arial.ttf")]
|
|
33
25
|
else:
|
|
34
|
-
candidates = [
|
|
35
|
-
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
|
|
36
|
-
"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
|
|
37
|
-
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
|
38
|
-
]
|
|
26
|
+
candidates = ["/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc", "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc", "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"]
|
|
39
27
|
for fp in candidates:
|
|
40
28
|
if os.path.exists(fp):
|
|
41
29
|
try:
|
|
@@ -44,6 +32,12 @@ def load_font(size):
|
|
|
44
32
|
continue
|
|
45
33
|
return ImageFont.load_default()
|
|
46
34
|
|
|
35
|
+
def pixelate(img, pixel_size=8):
|
|
36
|
+
"""把图片像素化 — 缩小再放大,产生像素颗粒感"""
|
|
37
|
+
w, h = img.size
|
|
38
|
+
small = img.resize((w // pixel_size, h // pixel_size), Image.NEAREST)
|
|
39
|
+
return small.resize((w, h), Image.NEAREST)
|
|
40
|
+
|
|
47
41
|
def main():
|
|
48
42
|
character = sys.argv[1] if len(sys.argv) > 1 else 'bagayalu'
|
|
49
43
|
scene = sys.argv[2] if len(sys.argv) > 2 else 'normal'
|
|
@@ -62,45 +56,60 @@ def main():
|
|
|
62
56
|
|
|
63
57
|
scene_zh = SCENE_ZH.get(scene, '一个瞬间')
|
|
64
58
|
|
|
65
|
-
#
|
|
59
|
+
# 加载并像素化角色图片
|
|
66
60
|
sprite = Image.open(img_path).convert("RGBA")
|
|
67
61
|
|
|
62
|
+
# 统一缩放到 400px 宽
|
|
63
|
+
target_w = 400
|
|
64
|
+
ratio = target_w / sprite.width
|
|
65
|
+
target_h = int(sprite.height * ratio)
|
|
66
|
+
sprite = sprite.resize((target_w, target_h), Image.LANCZOS)
|
|
67
|
+
|
|
68
|
+
# 像素化处理 — 产生复古像素风
|
|
69
|
+
sprite = pixelate(sprite, pixel_size=6)
|
|
70
|
+
|
|
68
71
|
# 拍立得尺寸
|
|
69
|
-
padding =
|
|
70
|
-
bottom_area =
|
|
72
|
+
padding = 50
|
|
73
|
+
bottom_area = 140
|
|
71
74
|
photo_w = sprite.width + padding * 2
|
|
72
75
|
photo_h = sprite.height + padding + bottom_area
|
|
73
76
|
|
|
74
|
-
#
|
|
75
|
-
card = Image.new("RGBA", (photo_w, photo_h), (
|
|
77
|
+
# 奶白色拍立得底板
|
|
78
|
+
card = Image.new("RGBA", (photo_w, photo_h), (252, 250, 245, 255))
|
|
76
79
|
|
|
77
|
-
#
|
|
80
|
+
# 贴像素化的角色图片
|
|
78
81
|
card.paste(sprite, (padding, padding), sprite)
|
|
79
82
|
|
|
80
|
-
# 画边框阴影
|
|
81
83
|
draw = ImageDraw.Draw(card)
|
|
82
|
-
|
|
84
|
+
|
|
85
|
+
# 图片区域细边框
|
|
86
|
+
draw.rectangle(
|
|
87
|
+
[padding - 2, padding - 2, padding + sprite.width + 1, padding + sprite.height + 1],
|
|
88
|
+
outline=(220, 218, 210), width=1
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# 外边框阴影
|
|
92
|
+
draw.rectangle([0, 0, photo_w - 1, photo_h - 1], outline=(210, 208, 200), width=2)
|
|
83
93
|
|
|
84
94
|
# 底部文字
|
|
85
|
-
font_caption = load_font(
|
|
86
|
-
font_studio = load_font(
|
|
95
|
+
font_caption = load_font(20)
|
|
96
|
+
font_studio = load_font(15)
|
|
87
97
|
|
|
88
98
|
caption = f"📸 刚才抓拍到了{name}{scene_zh}..."
|
|
89
99
|
studio = "🐋 Ai小蓝鲸照相馆"
|
|
90
100
|
|
|
91
|
-
caption_y = sprite.height + padding +
|
|
92
|
-
studio_y = caption_y +
|
|
101
|
+
caption_y = sprite.height + padding + 20
|
|
102
|
+
studio_y = caption_y + 45
|
|
93
103
|
|
|
94
104
|
draw.text((padding, caption_y), caption, fill=(80, 80, 80), font=font_caption)
|
|
95
|
-
draw.text((padding, studio_y), studio, fill=(
|
|
105
|
+
draw.text((padding, studio_y), studio, fill=(160, 158, 150), font=font_studio)
|
|
96
106
|
|
|
97
107
|
# 保存
|
|
98
108
|
os.makedirs(os.path.dirname(OUTPUT), exist_ok=True)
|
|
99
|
-
card_rgb = Image.new("RGB", card.size, (
|
|
109
|
+
card_rgb = Image.new("RGB", card.size, (252, 250, 245))
|
|
100
110
|
card_rgb.paste(card, mask=card.split()[3])
|
|
101
111
|
card_rgb.save(OUTPUT, "PNG", quality=95)
|
|
102
112
|
|
|
103
|
-
# 不在这里打开,让 Node.js 调用方负责打开
|
|
104
113
|
print(OUTPUT)
|
|
105
114
|
|
|
106
115
|
if __name__ == '__main__':
|