diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 5ae892b..c33a965 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp index aa305be..e53b2bf 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp and b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png index 5ae892b..b6bfc63 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d86d237..9a7a785 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp index d6c6e92..e17a79e 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png index d86d237..b6bef97 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index b6c7f42..e59fa65 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp index ca54f89..abf5bd3 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index b6c7f42..9dbfe24 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/scripts/resize_duck_icon.py b/scripts/resize_duck_icon.py new file mode 100644 index 0000000..ad46de8 --- /dev/null +++ b/scripts/resize_duck_icon.py @@ -0,0 +1,92 @@ +#!/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()