yayacal/scripts/resize_duck_icon.py

93 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""缩小小黄鸭在图标中的占比,并重新生成所有 mipmap 资源。"""
from pathlib import Path
from PIL import Image, ImageDraw
# 项目路径
APP_RES = Path(__file__).parent.parent / "app" / "src" / "main" / "res"
# Android 标准密度对应比例
DENSITIES = {
"mipmap-xhdpi": 2, # 108 dp * 2 = 216 px
"mipmap-xxhdpi": 3, # 108 dp * 3 = 324 px
"mipmap-xxxhdpi": 4, # 108 dp * 4 = 432 px
}
# 小黄鸭缩放比例0.75 = 占原来 75%
DUCK_SCALE = 0.75
# 背景色取自 ic_launcher_background.xml
BG_COLOR = (0x83, 0xD0, 0xF1, 0xFF)
def make_rounded_mask(size: int, radius_ratio: float = 0.22) -> Image.Image:
"""生成圆角矩形 mask用于圆角方形图标"""
mask = Image.new("L", (size, size), 0)
draw = ImageDraw.Draw(mask)
radius = int(size * radius_ratio)
draw.rounded_rectangle((0, 0, size, size), radius=radius, fill=255)
return mask
def make_circle_mask(size: int) -> Image.Image:
"""生成圆形 mask用于圆形图标"""
mask = Image.new("L", (size, size), 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0, size, size), fill=255)
return mask
def compose_icon(foreground: Image.Image, size: int, mask: Image.Image) -> Image.Image:
"""将前景合成到纯色背景上,并应用形状 mask。"""
bg = Image.new("RGBA", (size, size), BG_COLOR)
# 将前景缩放到当前密度尺寸
fg = foreground.resize((size, size), Image.Resampling.LANCZOS)
bg.alpha_composite(fg)
# 应用形状 mask
result = Image.new("RGBA", (size, size), (0, 0, 0, 0))
result.paste(bg, (0, 0), mask)
return result.convert("RGB")
def main():
# 读取最高分辨率前景图
src_fg = Image.open(APP_RES / "mipmap-xxxhdpi" / "ic_launcher_foreground.webp").convert("RGBA")
src_size = src_fg.size[0]
# 缩放鸭子内容,增加透明边距
new_size = int(src_size * DUCK_SCALE)
fg_resized = src_fg.resize((new_size, new_size), Image.Resampling.LANCZOS)
# 放置到原始尺寸透明画布中央
foreground_scaled = Image.new("RGBA", (src_size, src_size), (0, 0, 0, 0))
offset = (src_size - new_size) // 2
foreground_scaled.paste(fg_resized, (offset, offset), fg_resized)
for folder, scale in DENSITIES.items():
px = 108 * scale # 自适应图标前景标准尺寸
folder_path = APP_RES / folder
folder_path.mkdir(parents=True, exist_ok=True)
# 生成新的前景 webp
fg = foreground_scaled.resize((px, px), Image.Resampling.LANCZOS)
fg.save(folder_path / "ic_launcher_foreground.webp", "WEBP", quality=95)
# 生成合成后的圆角方形和圆形 PNG
icon_size = 48 * scale # 启动图标标准尺寸
rounded_mask = make_rounded_mask(icon_size)
circle_mask = make_circle_mask(icon_size)
compose_icon(fg, icon_size, rounded_mask).save(
folder_path / "ic_launcher.png", "PNG"
)
compose_icon(fg, icon_size, circle_mask).save(
folder_path / "ic_launcher_round.png", "PNG"
)
print(f"Generated {folder}: {px}x{px} foreground, {icon_size}x{icon_size} icons")
if __name__ == "__main__":
main()