| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- from PIL import Image
- import os
- def draw_icon(size):
- img = Image.new("RGBA", (size, size), (0, 0, 0, 0))
- BG = (255, 107, 53)
- CIRC = (30, 58, 138)
- WHITE = (255, 255, 255)
- PAD = int(round(24 * size / 512.0))
- RX = int(round(104 * size / 512.0))
- ccx = size // 2
- ccy = size // 2
- ccr = int(round(112 * size / 512.0))
- # 1. Orange rounded square
- x1, y1 = PAD, PAD
- x2, y2 = size - PAD, size - PAD
- for y in range(y1, y2 + 1):
- for x in range(x1, x2 + 1):
- if _in_rrect(x, y, x1, y1, x2, y2, RX):
- img.putpixel((x, y), BG + (255,))
- # 2. Deep blue circle
- for y in range(ccy - ccr, ccy + ccr + 1):
- for x in range(ccx - ccr, ccx + ccr + 1):
- if (x - ccx) ** 2 + (y - ccy) ** 2 <= ccr ** 2:
- img.putpixel((x, y), CIRC + (255,))
- # 3. White play triangle — right-pointing isosceles, apex at circle's right edge
- # Width-to-height ratio ~2:1 for a balanced play button look
- # bh=ccr*0.35 ensures the left vertex stays inside the circle
- # At y=ccy: triangle base spans ~67% of circle diameter (visually balanced)
- bh = int(round(ccr * 0.35))
- w_tri = bh * 2 # width from left vertex to right vertex = 0.7*ccr
- rx2 = ccx + ccr # right vertex at circle's right edge
- lx = rx2 - w_tri # left vertex
- ty_ = ccy - bh
- by_ = ccy + bh
- for y in range(ty_, by_ + 1):
- frac = float(y - ty_) / float(by_ - ty_) if by_ > ty_ else 0.0
- xl = lx
- xr = lx + int(round(w_tri * 2 * frac))
- xl, xr = min(xl, xr), max(xl, xr)
- for x in range(xl, xr + 1):
- if 0 <= x < size and 0 <= y < size:
- img.putpixel((x, y), WHITE + (255,))
- return img
- def _in_rrect(px, py, x1, y1, x2, y2, r):
- if px < x1 or px > x2 or py < y1 or py > y2:
- return False
- if px < x1 + r and py < y1 + r:
- return (px - x1 - r) ** 2 + (py - y1 - r) ** 2 <= r ** 2
- if px > x2 - r and py < y1 + r:
- return (px - x2 + r) ** 2 + (py - y1 - r) ** 2 <= r ** 2
- if px < x1 + r and py > y2 - r:
- return (px - x1 - r) ** 2 + (py - y2 + r) ** 2 <= r ** 2
- if px > x2 - r and py > y2 - r:
- return (px - x2 + r) ** 2 + (py - y2 + r) ** 2 <= r ** 2
- return True
- src_size = 1024
- img = draw_icon(src_size)
- vp = img.load()
- ccr = int(round(112 * src_size / 512.0))
- bh_draw = int(round(ccr * 0.35))
- w_tri_draw = bh_draw * 2
- rx2_draw = src_size // 2 + ccr
- lx_draw = rx2_draw - w_tri_draw
- ty__draw = src_size // 2 - bh_draw
- by__draw = src_size // 2 + bh_draw
- print("ccr=%d, w_tri=%d, bh=%d, lx=%d, rx2=%d, ty_=%d, by_=%d" % (ccr, w_tri_draw, bh_draw, lx_draw, rx2_draw, ty__draw, by__draw))
- print("Midpoint at y=ccy: %d [expect %d]" % ((lx_draw+rx2_draw)//2, src_size//2))
- print("Center(512,512): %s" % str(vp[512, 512]))
- print("Corner(5,5): %s" % str(vp[5, 5]))
- # Verify triangle left vertex is inside circle
- # Left vertex distance from center must be < ccr
- left_dist = abs(lx_draw - src_size//2)
- # Also check top-left corner (most likely to be outside)
- top_lx = lx_draw
- top_ly = ty__draw
- tl_dist_sq = (top_lx - src_size//2)**2 + (top_ly - src_size//2)**2
- print("Left vertex dist from center: %.1f < ccr=%d: %s" % (left_dist, ccr, left_dist < ccr))
- print("Top-left corner dist: %.1f < ccr=%d: %s" % (tl_dist_sq**0.5, ccr, tl_dist_sq**0.5 < ccr))
- out_dir = "minimax-output/vector"
- icons_dir = "client/public/icons"
- os.makedirs(out_dir, exist_ok=True)
- img.save(os.path.join(out_dir, "icon-orange-1024.png"), "PNG")
- for sz in [16, 24, 32, 48, 64, 128, 256, 512]:
- img.resize((sz, sz), Image.NEAREST).save(os.path.join(icons_dir, "icon-%d.png" % sz), "PNG")
- img.resize((512, 512), Image.NEAREST).save(os.path.join(icons_dir, "logo.png"), "PNG")
- img.resize((16, 16), Image.NEAREST).save(os.path.join(icons_dir, "tray-icon.png"), "PNG")
- img.resize((32, 32), Image.NEAREST).save(os.path.join(icons_dir, "tray-icon@2x.png"), "PNG")
- print("Done!")
|