包含三个子项目: - avatar-h5-renderer: Live2D Cubism 4 H5 渲染器 (Vite + TS) - avatar_flutter_app: Flutter 容器 App (打包 H5 进 WebView) - gif-export: puppeteer 导出 32 个动作的透明 GIF (供 ESP32 圆屏播放) 模型资源: Haru, Natori (含贴图、moc3、motions, expressions) 设计文档: AI驱动虚拟形象渲染方案_v5.1.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
60 lines
2.0 KiB
Python
60 lines
2.0 KiB
Python
import os
|
|
import shutil
|
|
from PIL import Image
|
|
import colorsys
|
|
|
|
def shift_hue(img_path, hue_shift_amount):
|
|
# Backup original
|
|
orig_path = img_path.replace('.png', '_orig.png')
|
|
if not os.path.exists(orig_path):
|
|
shutil.copy2(img_path, orig_path)
|
|
|
|
# Open image
|
|
img = Image.open(orig_path)
|
|
if img.mode != 'RGBA':
|
|
img = img.convert('RGBA')
|
|
|
|
# Split into channels
|
|
r, g, b, a = img.split()
|
|
|
|
# Convert RGB to HSV, shift hue, convert back
|
|
out_r, out_g, out_b = [], [], []
|
|
|
|
r_data = r.getdata()
|
|
g_data = g.getdata()
|
|
b_data = b.getdata()
|
|
|
|
# We want a blue/cyan theme.
|
|
# Instead of relative shift, let's just map most hues to a blueish hue.
|
|
# Actually, a simple hue shift (e.g. + 0.4 in 0-1 range) might be safer to keep variation.
|
|
|
|
for rp, gp, bp in zip(r_data, g_data, b_data):
|
|
h, s, v = colorsys.rgb_to_hsv(rp/255.0, gp/255.0, bp/255.0)
|
|
|
|
# Shift hue towards blue (around 0.55 - 0.65 in HSV)
|
|
# Let's do a relative shift. If original is reddish (0-0.1), shifting by 0.5 makes it cyan/blue.
|
|
h = (h + hue_shift_amount) % 1.0
|
|
|
|
# Let's also desaturate slightly to make it more "ethereal" like the uploaded pic
|
|
s = min(s * 0.8, 1.0)
|
|
|
|
rn, gn, bn = colorsys.hsv_to_rgb(h, s, v)
|
|
out_r.append(int(rn * 255))
|
|
out_g.append(int(gn * 255))
|
|
out_b.append(int(bn * 255))
|
|
|
|
new_r = Image.new('L', img.size)
|
|
new_r.putdata(out_r)
|
|
new_g = Image.new('L', img.size)
|
|
new_g.putdata(out_g)
|
|
new_b = Image.new('L', img.size)
|
|
new_b.putdata(out_b)
|
|
|
|
new_img = Image.merge('RGBA', (new_r, new_g, new_b, a))
|
|
new_img.save(img_path)
|
|
print(f"Tinted and saved: {img_path}")
|
|
|
|
base_dir = "/Users/maidong/Desktop/AR测试/avatar-h5-renderer/public/Resources/Haru/Haru.2048/"
|
|
shift_hue(os.path.join(base_dir, "texture_00.png"), 0.5) # Shift to cyan/blue
|
|
shift_hue(os.path.join(base_dir, "texture_01.png"), 0.5)
|