feat: 更新鸿蒙应用配置与功能优化
- 添加鸿蒙分层图标配置和生成脚本 - 修复数据导出JSON解析问题 - 优化关于页面和团队信息展示 - 更新应用版本至1.4.1 - 清理代码警告和冗余文件 - 添加字体和二维码测试脚本 - 完善鸿蒙适配文档和指南
This commit is contained in:
139
scripts/gen_hmos_icons.py
Normal file
139
scripts/gen_hmos_icons.py
Normal file
@@ -0,0 +1,139 @@
|
||||
"""
|
||||
鸿蒙(HarmonyOS) 分层图标生成脚本
|
||||
从源图标提取 foreground + background,符合华为审核规范 1024x1024
|
||||
"""
|
||||
import os
|
||||
import json
|
||||
import math
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
ASSETS_ICONS = os.path.join(SCRIPT_DIR, "..", "assets", "icons")
|
||||
OHOS_MEDIA = os.path.join(SCRIPT_DIR, "..", "ohos", "AppScope", "resources", "base", "media")
|
||||
OHOS_ENTRY_MEDIA = os.path.join(SCRIPT_DIR, "..", "ohos", "entry", "src", "main", "resources", "base", "media")
|
||||
|
||||
SOURCE_ICON = os.path.join(ASSETS_ICONS, "icon_1024x1024.png")
|
||||
OUTPUT_SIZE = 1024
|
||||
|
||||
|
||||
def get_dominant_bg_color(img):
|
||||
samples = [
|
||||
(80, 80), (img.width - 81, 80),
|
||||
(80, img.height - 81), (img.width - 81, img.height - 81),
|
||||
(img.width // 2, 60), (img.width // 2, img.height - 61),
|
||||
(60, img.height // 2), (img.width - 61, img.height // 2),
|
||||
(150, 150), (img.width - 151, img.height - 151),
|
||||
]
|
||||
colors = []
|
||||
for pos in samples:
|
||||
px = img.getpixel(pos)
|
||||
if len(px) >= 3:
|
||||
colors.append((px[0], px[1], px[2]))
|
||||
r_sum = sum(c[0] for c in colors)
|
||||
g_sum = sum(c[1] for c in colors)
|
||||
b_sum = sum(c[2] for c in colors)
|
||||
n = len(colors)
|
||||
return (r_sum // n, g_sum // n, b_sum // n)
|
||||
|
||||
|
||||
def color_distance(c1, c2):
|
||||
return math.sqrt(
|
||||
(c1[0] - c2[0]) ** 2 +
|
||||
(c1[1] - c2[1]) ** 2 +
|
||||
(c1[2] - c2[2]) ** 2
|
||||
)
|
||||
|
||||
|
||||
def create_rounded_mask(size, radius):
|
||||
mask = Image.new("L", (size, size), 0)
|
||||
draw = ImageDraw.Draw(mask)
|
||||
draw.rounded_rectangle([0, 0, size - 1, size - 1], radius=radius, fill=255)
|
||||
return mask
|
||||
|
||||
|
||||
def generate_background(img, output_path, bg_color):
|
||||
bg = Image.new("RGB", (OUTPUT_SIZE, OUTPUT_SIZE), bg_color)
|
||||
bg.save(output_path, "PNG")
|
||||
print(f" background: {output_path} ({os.path.getsize(output_path) / 1024:.1f}KB)")
|
||||
print(f" 颜色: RGB{bg_color}")
|
||||
|
||||
|
||||
def generate_foreground(img, output_path, bg_color, tolerance=50):
|
||||
from PIL import ImageChops
|
||||
|
||||
fg = img.convert("RGBA").resize((OUTPUT_SIZE, OUTPUT_SIZE), Image.LANCZOS)
|
||||
|
||||
pixels = fg.load()
|
||||
width, height = fg.size
|
||||
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
r, g, b, a = pixels[x, y]
|
||||
dist = color_distance((r, g, b), bg_color)
|
||||
if dist < tolerance and a > 200:
|
||||
alpha = int(255 * (dist / tolerance))
|
||||
pixels[x, y] = (r, g, b, alpha)
|
||||
elif dist < tolerance * 0.5:
|
||||
pixels[x, y] = (r, g, b, 0)
|
||||
|
||||
mask = create_rounded_mask(OUTPUT_SIZE, int(OUTPUT_SIZE * 0.22))
|
||||
|
||||
fg.putalpha(ImageChops.multiply(fg.split()[3], mask))
|
||||
|
||||
fg.save(output_path, "PNG")
|
||||
print(f" foreground: {output_path} ({os.path.getsize(output_path) / 1024:.1f}KB)")
|
||||
|
||||
|
||||
def generate_layered_json(output_dir, fg_name="foreground_icon.png", bg_name="background_icon.png"):
|
||||
config = {
|
||||
"layered-image": {
|
||||
"foreground": f"$media:{fg_name.replace('.png', '')}",
|
||||
"background": f"$media:{bg_name.replace('.png', '')}"
|
||||
}
|
||||
}
|
||||
json_path = os.path.join(output_dir, "layered_image.json")
|
||||
with open(json_path, "w", encoding="utf-8") as f:
|
||||
json.dump(config, f, indent=2, ensure_ascii=False)
|
||||
print(f" layered_image.json: {json_path}")
|
||||
return json_path
|
||||
|
||||
|
||||
def main():
|
||||
if not os.path.exists(SOURCE_ICON):
|
||||
print(f"错误: 源文件不存在 {SOURCE_ICON}")
|
||||
return
|
||||
|
||||
print(f"源图标: {SOURCE_ICON}")
|
||||
img = Image.open(SOURCE_ICON).convert("RGBA")
|
||||
print(f" 尺寸: {img.size}")
|
||||
|
||||
bg_color = get_dominant_bg_color(img)
|
||||
print(f" 背景色采样: RGB{bg_color}")
|
||||
|
||||
os.makedirs(OHOS_MEDIA, exist_ok=True)
|
||||
os.makedirs(OHOS_ENTRY_MEDIA, exist_ok=True)
|
||||
|
||||
print("\n--- AppScope/resources/base/media ---")
|
||||
|
||||
bg_path = os.path.join(OHOS_MEDIA, "background_icon.png")
|
||||
fg_path = os.path.join(OHOS_MEDIA, "foreground_icon.png")
|
||||
|
||||
generate_background(img, bg_path, bg_color)
|
||||
generate_foreground(img, fg_path, bg_color)
|
||||
generate_layered_json(OHOS_MEDIA)
|
||||
|
||||
print("\n--- entry/src/main/resources/base/media ---")
|
||||
|
||||
bg_entry = os.path.join(OHOS_ENTRY_MEDIA, "background_icon.png")
|
||||
fg_entry = os.path.join(OHOS_ENTRY_MEDIA, "foreground_icon.png")
|
||||
|
||||
generate_background(img, bg_entry, bg_color)
|
||||
generate_foreground(img, fg_entry, bg_color)
|
||||
generate_layered_json(OHOS_ENTRY_MEDIA)
|
||||
|
||||
print("\n完成!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user