Tick_Forge/tools/make_icon.py
97 라인
3.7 KiB
Python
"""Tick Forge logos in the house style (dark field, faint price lines in an accent colour, bold white wordmark).
Writes market/hero_1024.png (name + tagline) and market/logo_200.png, logo_140.png, logo_60.png (name only, large,
so it stays readable at 60 px). The background lines are ONE price series repeated shifted in time and rescaled,
which is what the tool does. Needs Pillow; uses DejaVu Sans if matplotlib is installed, else Arial.
"""
import random
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
OUT = Path(__file__).resolve().parent.parent / "market"
OUT.mkdir(exist_ok=True)
BG = (13, 17, 23)
ACCENT = (232, 166, 54) # amber
GREY = (150, 160, 178)
def font(size, bold=True):
try:
import matplotlib
d = Path(matplotlib.__file__).parent / "mpl-data" / "fonts" / "ttf"
return ImageFont.truetype(str(d / ("DejaVuSans-Bold.ttf" if bold else "DejaVuSans.ttf")), size)
except Exception:
return ImageFont.truetype("arialbd.ttf" if bold else "arial.ttf", size)
def walk(n, seed):
r = random.Random(seed)
v, out = 0.0, []
for _ in range(n):
v += r.gauss(0.0, 1.0) + 0.05
out.append(v)
lo, hi = min(out), max(out)
return [(x - lo) / (hi - lo) for x in out]
def background(size, seed=7):
"""Faint copies of one series: grey = original, amber = shifted and rescaled copies."""
S = size * 2 # supersample
img = Image.new("RGBA", (S, S), BG + (255,))
base = walk(260, seed)
n = len(base)
layers = [(GREY, 0.0, 1.00, 0.18, 0.18), (ACCENT, 0.06, 0.80, 0.50, 0.26), (ACCENT, 0.13, 1.25, 0.28, 0.20),
(ACCENT, 0.20, 0.55, 0.78, 0.17), (GREY, 0.27, 0.95, 0.66, 0.12), (ACCENT, 0.34, 1.10, 0.90, 0.12)]
for col, shift, scale, ymid, alpha in layers:
lay = Image.new("RGBA", (S, S), (0, 0, 0, 0))
d = ImageDraw.Draw(lay)
pts = []
for i, v in enumerate(base):
x = (i / (n - 1) + shift) * S * 1.1 - S * 0.05
y = (ymid - (v - 0.5) * 0.5 * scale) * S
pts.append((x, y))
d.line(pts, fill=col + (int(255 * alpha * 1.6),), width=max(2, S // 230), joint="curve")
img = Image.alpha_composite(img, lay)
return img.resize((size, size), Image.LANCZOS)
def centered(d, text, f, y, fill, W):
w = d.textlength(text, font=f)
d.text(((W - w) / 2, y), text, font=f, fill=fill)
def hero(size=1024):
im = background(size).convert("RGB")
d = ImageDraw.Draw(im)
centered(d, "Tick Forge", font(int(size * 0.115)), size * 0.415, (255, 255, 255), size)
centered(d, "custom symbols for the Strategy Tester", font(int(size * 0.036), bold=False), size * 0.565, ACCENT, size)
return im
def banner(w=1200, h=628):
"""Landscape card (article / social preview): the square background stretched wide, wordmark + tagline."""
big = background(w, seed=7)
top = (w - h) // 2
im = big.crop((0, top, w, top + h)).convert("RGB")
d = ImageDraw.Draw(im)
centered(d, "Tick Forge", font(int(h * 0.20)), h * 0.30, (255, 255, 255), w)
centered(d, "custom symbols for the Strategy Tester", font(int(h * 0.062), bold=False), h * 0.58, ACCENT, w)
return im
def logo(size):
im = background(size, seed=7).convert("RGB")
d = ImageDraw.Draw(im)
f = font(int(size * 0.27))
centered(d, "Tick", f, size * 0.20, (255, 255, 255), size)
centered(d, "Forge", f, size * 0.50, ACCENT, size)
return im
if __name__ == "__main__":
hero().save(OUT / "hero_1024.png")
banner().save(OUT / "banner_1200x628.png")
big = logo(800)
for s in (200, 140, 60):
big.resize((s, s), Image.LANCZOS).save(OUT / ("logo_%d.png" % s))
print("wrote", OUT)