App Android: tambah ikon launcher (hijau zamrud, grafik putih, badge Rp)
This commit is contained in:
86
scripts/gen_icon.py
Normal file
86
scripts/gen_icon.py
Normal file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate app icon for Saat Invest (1024x1024, anti-aliased 4x supersample).
|
||||
Desain: bg hijau zamrud gradient, garis grafik naik putih tebal, titik akhir,
|
||||
badge 'Rp' kecil. Simpan ke flutter/assets/icon/app_icon.png."""
|
||||
import math
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
SS = 4 # supersample factor
|
||||
SIZE = 1024
|
||||
W = H = SIZE * SS
|
||||
|
||||
# --- background gradient (emerald) ---
|
||||
top = (0x16, 0x8a, 0x63) # lebih terang
|
||||
bot = (0x07, 0x53, 0x3a) # lebih gelap
|
||||
img = Image.new('RGB', (W, H))
|
||||
px = img.load()
|
||||
for y in range(H):
|
||||
t = y / (H - 1)
|
||||
r = int(top[0] + (bot[0] - top[0]) * t)
|
||||
g = int(top[1] + (bot[1] - top[1]) * t)
|
||||
b = int(top[2] + (bot[2] - top[2]) * t)
|
||||
for x in range(W):
|
||||
px[x, y] = (r, g, b)
|
||||
|
||||
d = ImageDraw.Draw(img)
|
||||
WHITE = (255, 255, 255, 255)
|
||||
SOFT = (255, 255, 255, 128)
|
||||
|
||||
def pt(x, y):
|
||||
"""convert normalized (0..1) to supersampled px coords."""
|
||||
return (x * W, y * H)
|
||||
|
||||
# --- line chart (naik) ---
|
||||
# area chart di tengah (safe zone); baseline 0.78 -> puncak 0.34
|
||||
line_pts = [
|
||||
(0.18, 0.72),
|
||||
(0.36, 0.58),
|
||||
(0.52, 0.62),
|
||||
(0.68, 0.46),
|
||||
(0.82, 0.34),
|
||||
]
|
||||
pts_px = [pt(x, y) for x, y in line_pts]
|
||||
|
||||
# stroke tebal dengan join bulat
|
||||
lw = int(0.078 * W)
|
||||
d.line(pts_px, fill=WHITE, width=lw, joint='curve')
|
||||
|
||||
# titik pada tiap vertex (bulatan kecil)
|
||||
r = int(0.042 * W)
|
||||
for (x, y) in pts_px:
|
||||
d.ellipse([x - r, y - r, x + r, y + r], fill=WHITE)
|
||||
|
||||
# area di bawah garis (fill lembut)
|
||||
base_y = 0.80 * H
|
||||
poly = [(pts_px[0][0], base_y)] + list(pts_px) + [(pts_px[-1][0], base_y)]
|
||||
overlay = Image.new('RGBA', (W, H), (0, 0, 0, 0))
|
||||
od = ImageDraw.Draw(overlay)
|
||||
od.polygon(poly, fill=(255, 255, 255, 45))
|
||||
img = Image.alpha_composite(img.convert('RGBA'), overlay)
|
||||
d = ImageDraw.Draw(img)
|
||||
|
||||
# --- badge 'Rp' ---
|
||||
# posisikan di kiri-atas dari ujung grafik, tetap dalam safe zone
|
||||
font_path = '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf'
|
||||
fsize = int(0.105 * W)
|
||||
f = ImageFont.truetype(font_path, fsize)
|
||||
text = 'Rp'
|
||||
bbox = d.textbbox((0, 0), text, font=f)
|
||||
tw = bbox[2] - bbox[0]
|
||||
th = bbox[3] - bbox[1]
|
||||
# badge bulat: di atas segmen terakhir, kiri dari titik ujung
|
||||
bcx = pts_px[-2][0] * 0.92 + pts_px[-1][0] * 0.08 - 0.10 * W
|
||||
bcy = pts_px[-2][1] * 0.5 + pts_px[-1][1] * 0.5 - 0.20 * H
|
||||
br = int(0.105 * W)
|
||||
d.ellipse([bcx - br, bcy - br, bcx + br, bcy + br], fill=(255, 255, 255, 240))
|
||||
# teks Rp hijau tua di badge
|
||||
d.text((bcx - tw / 2 - bbox[0], bcy - th / 2 - bbox[1]), text,
|
||||
font=f, fill=(0x07, 0x53, 0x3a, 255))
|
||||
|
||||
# --- downscale to 1024 (Lanczos) ---
|
||||
out = img.resize((SIZE, SIZE), Image.Resampling.LANCZOS).convert('RGB')
|
||||
|
||||
import os
|
||||
os.makedirs('flutter/assets/icon', exist_ok=True)
|
||||
out.save('flutter/assets/icon/app_icon.png')
|
||||
print('saved flutter/assets/icon/app_icon.png', out.size)
|
||||
Reference in New Issue
Block a user