diff --git a/README.md b/README.md index bf560b3..3382fa1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +

JJ_MKVMaker

+ # JJ_MKVMaker 동영상에 자막을 넣어 **MKV** 로 만들고, 자막을 **편집 · AI 로 생성 · 번역**하고, diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4..8ce9a65 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b7..c1ce60e 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 09d4391..b02f16d 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d..550d1e9 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372e..9db70c1 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/assets/icon/app_icon_1024.png b/assets/icon/app_icon_1024.png new file mode 100644 index 0000000..6f6ea0c Binary files /dev/null and b/assets/icon/app_icon_1024.png differ diff --git a/assets/icon/app_icon_256.png b/assets/icon/app_icon_256.png new file mode 100644 index 0000000..9ff1b45 Binary files /dev/null and b/assets/icon/app_icon_256.png differ diff --git a/assets/icon/app_icon_small_256.png b/assets/icon/app_icon_small_256.png new file mode 100644 index 0000000..d19c659 Binary files /dev/null and b/assets/icon/app_icon_small_256.png differ diff --git a/assets/tray_icon.ico b/assets/tray_icon.ico index c04e20c..c76ba64 100644 Binary files a/assets/tray_icon.ico and b/assets/tray_icon.ico differ diff --git a/lib/ui/home_page.dart b/lib/ui/home_page.dart index 020b9c3..aa8f12d 100644 --- a/lib/ui/home_page.dart +++ b/lib/ui/home_page.dart @@ -109,7 +109,8 @@ class _TopBar extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 16), child: Row( children: [ - const Icon(Icons.movie_filter, color: JjColors.accent), + // 프로그램 아이콘 (tool/make_icon.py 로 생성) + Image.asset('assets/icon/app_icon_256.png', width: 28, height: 28, filterQuality: FilterQuality.medium), const SizedBox(width: 8), const Text('JJ_MKVMaker', style: TextStyle(fontSize: 17, fontWeight: FontWeight.w700)), diff --git a/pubspec.yaml b/pubspec.yaml index 999dbed..270d87f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.1+2 +version: 1.0.2+3 environment: sdk: ^3.13.4 @@ -79,6 +79,7 @@ flutter: uses-material-design: true assets: - assets/tray_icon.ico + - assets/icon/app_icon_256.png # To add assets to your application, add an assets section, like this: # assets: diff --git a/tool/make_icon.py b/tool/make_icon.py new file mode 100644 index 0000000..46d9dc1 --- /dev/null +++ b/tool/make_icon.py @@ -0,0 +1,103 @@ +"""JJ_MKVMaker 아이콘 만들기 (1024px 원본 → .ico / .png) + +사용법: python tool/make_icon.py +결과: assets/icon/app_icon_1024.png, windows/runner/resources/app_icon.ico, + assets/tray_icon.ico, android/app/src/main/res/mipmap-*/ic_launcher.png +""" +from pathlib import Path + +from PIL import Image, ImageDraw, ImageFilter, ImageFont + +ROOT = Path(__file__).resolve().parent.parent +S = 1024 # 원본 크기 +FONT = 'C:/Windows/Fonts/seguibl.ttf' # Segoe UI Black + +TEAL = (0, 196, 204) +VIOLET = (108, 92, 255) + + +def lerp(a, b, t): + return tuple(round(a[i] + (b[i] - a[i]) * t) for i in range(3)) + + +def rounded_mask(size, radius): + m = Image.new('L', (size, size), 0) + ImageDraw.Draw(m).rounded_rectangle((0, 0, size - 1, size - 1), radius=radius, fill=255) + return m + + +def make_master(small=False): + """small=True: 16~32px 용 단순 버전 (재생 표시 없이 JJ 를 크게)""" + # 대각선 그라데이션 (왼쪽 위 청록 → 오른쪽 아래 보라) + grad = Image.new('RGB', (S, S)) + px = grad.load() + for y in range(S): + for x in range(S): + px[x, y] = lerp(TEAL, VIOLET, (x + y) / (2 * (S - 1))) + + # 왼쪽 위에 아주 은은한 빛 (경계가 보이지 않게 크게 흐림) + glow = Image.new('L', (S, S), 0) + ImageDraw.Draw(glow).ellipse((-S * 0.5, -S * 0.6, S * 0.9, S * 0.5), fill=38) + glow = glow.filter(ImageFilter.GaussianBlur(S * 0.16)) + grad = Image.composite(Image.new('RGB', (S, S), (255, 255, 255)), grad, glow) + + icon = Image.new('RGBA', (S, S), (0, 0, 0, 0)) + icon.paste(grad, (0, 0), rounded_mask(S, int(S * 0.23))) + + # "JJ" (그림자 + 흰 글자) + font = ImageFont.truetype(FONT, int(S * (0.66 if small else 0.56))) + text = 'JJ' + d = ImageDraw.Draw(icon) + l, t, r, b = d.textbbox((0, 0), text, font=font) + x = (S - (r - l)) / 2 - l - (0 if small else S * 0.035) + y = (S - (b - t)) / 2 - t - (0 if small else S * 0.02) + + shadow = Image.new('RGBA', (S, S), (0, 0, 0, 0)) + ImageDraw.Draw(shadow).text((x + S * 0.012, y + S * 0.022), text, font=font, fill=(20, 10, 60, 120)) + shadow = shadow.filter(ImageFilter.GaussianBlur(S * 0.018)) + icon = Image.alpha_composite(icon, shadow) + ImageDraw.Draw(icon).text((x, y), text, font=font, fill=(255, 255, 255, 255)) + if small: + return icon + + # 오른쪽 아래 재생(▶) 표시: 흰 원 + 보라 삼각형 + cx, cy, rad = S * 0.765, S * 0.765, S * 0.135 + badge = Image.new('RGBA', (S, S), (0, 0, 0, 0)) + bd = ImageDraw.Draw(badge) + bd.ellipse((cx - rad * 1.12, cy - rad * 1.12, cx + rad * 1.12, cy + rad * 1.12), fill=(40, 20, 110, 90)) + badge = badge.filter(ImageFilter.GaussianBlur(S * 0.012)) + bd = ImageDraw.Draw(badge) + bd.ellipse((cx - rad, cy - rad, cx + rad, cy + rad), fill=(255, 255, 255, 255)) + tri = rad * 0.52 + bd.polygon([(cx - tri * 0.62, cy - tri), (cx - tri * 0.62, cy + tri), (cx + tri * 0.95, cy)], fill=VIOLET + (255,)) + return Image.alpha_composite(icon, badge) + + +def main(): + master = make_master() + out = ROOT / 'assets' / 'icon' + out.mkdir(parents=True, exist_ok=True) + master.save(out / 'app_icon_1024.png') + master.resize((256, 256), Image.LANCZOS).save(out / 'app_icon_256.png') + + # 작은 크기 (16~32px) 는 단순 버전, 큰 크기는 재생 표시 포함 버전 + simple = make_master(small=True) + simple.resize((256, 256), Image.LANCZOS).save(out / 'app_icon_small_256.png') + + def ico(path, sizes): + imgs = [(simple if s <= 32 else master).resize((s, s), Image.LANCZOS) for s in sizes] + imgs[-1].save(path, format='ICO', sizes=[(s, s) for s in sizes], append_images=imgs[:-1]) + + ico(ROOT / 'windows' / 'runner' / 'resources' / 'app_icon.ico', [16, 20, 24, 32, 40, 48, 64, 128, 256]) + ico(ROOT / 'assets' / 'tray_icon.ico', [16, 20, 24, 32, 48]) + + # Android 앱 아이콘 (이식 대비) + for name, px in {'mdpi': 48, 'hdpi': 72, 'xhdpi': 96, 'xxhdpi': 144, 'xxxhdpi': 192}.items(): + d = ROOT / 'android' / 'app' / 'src' / 'main' / 'res' / f'mipmap-{name}' + if d.exists(): + master.resize((px, px), Image.LANCZOS).save(d / 'ic_launcher.png') + print('아이콘 생성 완료:', out / 'app_icon_1024.png') + + +if __name__ == '__main__': + main() diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico index c04e20c..f3a404e 100644 Binary files a/windows/runner/resources/app_icon.ico and b/windows/runner/resources/app_icon.ico differ