Files
saat-app/scripts/gen_icon.py

87 lines
2.7 KiB
Python

#!/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)