diff --git a/docs/icona/proposte/a-casa-onda-172.png b/docs/icona/proposte/a-casa-onda-172.png new file mode 100644 index 0000000..858e192 Binary files /dev/null and b/docs/icona/proposte/a-casa-onda-172.png differ diff --git a/docs/icona/proposte/a-casa-onda-86.png b/docs/icona/proposte/a-casa-onda-86.png new file mode 100644 index 0000000..591a37e Binary files /dev/null and b/docs/icona/proposte/a-casa-onda-86.png differ diff --git a/docs/icona/proposte/b-manopola-172.png b/docs/icona/proposte/b-manopola-172.png new file mode 100644 index 0000000..02b4676 Binary files /dev/null and b/docs/icona/proposte/b-manopola-172.png differ diff --git a/docs/icona/proposte/b-manopola-86.png b/docs/icona/proposte/b-manopola-86.png new file mode 100644 index 0000000..c22f513 Binary files /dev/null and b/docs/icona/proposte/b-manopola-86.png differ diff --git a/docs/icona/proposte/c-goccia-fiamma-172.png b/docs/icona/proposte/c-goccia-fiamma-172.png new file mode 100644 index 0000000..d92f142 Binary files /dev/null and b/docs/icona/proposte/c-goccia-fiamma-172.png differ diff --git a/docs/icona/proposte/c-goccia-fiamma-86.png b/docs/icona/proposte/c-goccia-fiamma-86.png new file mode 100644 index 0000000..29c7241 Binary files /dev/null and b/docs/icona/proposte/c-goccia-fiamma-86.png differ diff --git a/docs/icona/proposte/contatto.png b/docs/icona/proposte/contatto.png new file mode 100644 index 0000000..5b54a6d Binary files /dev/null and b/docs/icona/proposte/contatto.png differ diff --git a/docs/icona/proposte/d-casa-goccia-172.png b/docs/icona/proposte/d-casa-goccia-172.png new file mode 100644 index 0000000..264cb6a Binary files /dev/null and b/docs/icona/proposte/d-casa-goccia-172.png differ diff --git a/docs/icona/proposte/d-casa-goccia-86.png b/docs/icona/proposte/d-casa-goccia-86.png new file mode 100644 index 0000000..8f53f4f Binary files /dev/null and b/docs/icona/proposte/d-casa-goccia-86.png differ diff --git a/scripts/icon_proposals.py b/scripts/icon_proposals.py new file mode 100644 index 0000000..96d1895 --- /dev/null +++ b/scripts/icon_proposals.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +"""Quattro proposte di icona per harbour-aira, alla misura vera (172 e 86 px). + +Si disegna a 344 px e si ridimensiona: bordi puliti a ogni taglia, come fa +scripts/make_icons.py. Nessun logo di terzi (il permesso per nome e logo Aira +non e' ancora arrivato), nessuna lettera generata. + +Uso: python3 scripts/icon_proposals.py +Esito: docs/icona/proposte/*.png (172 e 86 px) + contatto.png con tutte e quattro +""" +import math +import pathlib + +from PIL import Image, ImageDraw, ImageFont + +BASE = 344 # si disegna grande, si ridimensiona dopo +OUT = pathlib.Path("docs/icona/proposte") + +TOP = (12, 62, 130) # blu profondo (identita' attuale) +BOTTOM = (24, 148, 190) # azzurro +WARM = (255, 138, 46) # arancione +WHITE = (255, 255, 255, 240) +BLUE = (14, 78, 148) # blu del fondo, per i ritagli (negative space) + + +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 gradient(size): + img = Image.new("RGB", (1, size)) + d = ImageDraw.Draw(img) + for y in range(size): + t = y / max(1, size - 1) + d.point((0, y), tuple(int(TOP[i] + (BOTTOM[i] - TOP[i]) * t) for i in range(3))) + return img.resize((size, size)) + + +def onda(d, x0, x1, y, ampiezza, spessore, fill, creste=2): + """Una linea ondulata: la stessa forma in tutti i disegni che la usano.""" + punti = [] + passi = 120 + for i in range(passi + 1): + t = i / passi + x = x0 + (x1 - x0) * t + yy = y + ampiezza * math.sin(2 * math.pi * creste * t) + punti.append((x, yy)) + d.line(punti, fill=fill, width=int(spessore), joint="curve") + + +def base_icon(): + img = gradient(BASE).convert("RGBA") + return img, ImageDraw.Draw(img) + + +def goccia(d, cx, cy, r, fill, fattore_punta=2.35): + """Goccia con la punta smussata: la punta aguzza, a 86 px, sparisce.""" + d.ellipse([cx - r, cy - r, cx + r, cy + r], fill=fill) + d.polygon([(cx - r * 0.11, cy - fattore_punta * r), (cx + r * 0.11, cy - fattore_punta * r), + (cx + r * 0.99, cy + r * 0.10), (cx - r * 0.99, cy + r * 0.10)], fill=fill) + + +# --------------------------------------------------------------------------- # +# A. Casa con l'onda calda dentro: "la casa che viene scaldata" +# --------------------------------------------------------------------------- # +def casa_onda(): + img, d = base_icon() + tetto = [(BASE * 0.16, BASE * 0.50), (BASE * 0.50, BASE * 0.24), (BASE * 0.84, BASE * 0.50)] + corpo = [BASE * 0.24, BASE * 0.50, BASE * 0.76, BASE * 0.78] + d.polygon(tetto, fill=WHITE) + d.rectangle(corpo, fill=WHITE) + # onda dentro il corpo: non deve toccare il tetto (si fondeva a 86 px) + onda(d, BASE * 0.26, BASE * 0.74, BASE * 0.665, BASE * 0.040, BASE * 0.078, WARM + (255,), creste=2) + return img + + +# --------------------------------------------------------------------------- # +# B. Manopola: "il controllo" +# --------------------------------------------------------------------------- # +def manopola(): + img, d = base_icon() + m = BASE * 0.125 # margine piu' largo: il pomello non deve + spessore = int(BASE * 0.115) # sfiorare l'angolo arrotondato + riquadro = [m, m, BASE - m, BASE - m] + # anello aperto in alto (la finestra della scala) e pomello in alto a destra + d.arc(riquadro, start=295, end=245, fill=WHITE, width=spessore) + cx = cy = BASE / 2 + raggio = (BASE - 2 * m) / 2 + ang = math.radians(315) + px, py = cx + raggio * math.cos(ang), cy + raggio * math.sin(ang) + r = BASE * 0.095 + d.ellipse([px - r, py - r, px + r, py + r], fill=WARM + (255,)) + # tacca al centro: il valore + d.rounded_rectangle([cx - BASE * 0.032, cy - BASE * 0.14, + cx + BASE * 0.032, cy + BASE * 0.14], + radius=BASE * 0.032, fill=WHITE) + return img + + +# --------------------------------------------------------------------------- # +# C. Goccia con la fiamma: "acqua calda" (evoluzione dell'icona attuale) +# --------------------------------------------------------------------------- # +def goccia_fiamma(): + img, d = base_icon() + cx, cy = BASE * 0.50, BASE * 0.615 + r = BASE * 0.225 + goccia(d, cx, cy, r, WHITE) + img = img.transform(img.size, Image.AFFINE, (1, 0, 0, 0, 1, -BASE * 0.055)) + d = ImageDraw.Draw(img) + # fiamma piu' piccola: il bianco attorno deve restare spesso a 86 px + cy2 = cy + r * 0.18 - BASE * 0.055 + fr = r * 0.42 + d.ellipse([cx - fr, cy2 - fr, cx + fr, cy2 + fr], fill=WARM + (255,)) + d.polygon([(cx - fr * 0.13, cy2 - fr * 2.15), (cx + fr * 0.13, cy2 - fr * 2.15), + (cx + fr * 0.96, cy2 + fr * 0.20)], fill=WARM + (255,)) + return img + + +# --------------------------------------------------------------------------- # +# D. Casa e goccia insieme: "riscaldamento e acqua calda" +# --------------------------------------------------------------------------- # +def casa_goccia(): + img, d = base_icon() + tetto = [(BASE * 0.16, BASE * 0.50), (BASE * 0.50, BASE * 0.24), (BASE * 0.84, BASE * 0.50)] + corpo = [BASE * 0.24, BASE * 0.50, BASE * 0.76, BASE * 0.78] + d.polygon(tetto, fill=WHITE) + d.rectangle(corpo, fill=WHITE) + # goccia nel corpo della casa, in arancione: a 86 px il blu si perderebbe + goccia(d, BASE * 0.50, BASE * 0.665, BASE * 0.092, WARM + (255,), fattore_punta=2.10) + return img + + +PROPOSTE = [ + ("a-casa-onda", casa_onda, "A. Casa + onda calda"), + ("b-manopola", manopola, "B. Manopola"), + ("c-goccia-fiamma", goccia_fiamma, "C. Goccia + fiamma"), + ("d-casa-goccia", casa_goccia, "D. Casa + goccia"), +] + + +def salva(img, nome, size): + fuori = img.resize((size, size), Image.LANCZOS) + fuori = fuori.convert("RGB").convert("RGBA") + fuori.putalpha(rounded_mask(size, int(size * 0.22))) + OUT.mkdir(parents=True, exist_ok=True) + percorso = OUT / f"{nome}-{size}.png" + fuori.save(percorso) + return percorso + + +def contatto(): + """Un'immagine sola: le quattro proposte a 172 px e, sotto, a 86 px.""" + larghezza = 4 * 200 + altezza = 200 + 130 + 30 + tela = Image.new("RGB", (larghezza, altezza), (16, 20, 26)) + d = ImageDraw.Draw(tela) + try: + piccolo = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 14) + except OSError: + piccolo = ImageFont.load_default() + for i, (nome, disegna, descrizione) in enumerate(PROPOSTE): + img = disegna() + grande = Image.open(salva(img, nome, 172)).convert("RGBA") + piccola = Image.open(salva(img, nome, 86)).convert("RGBA") + x = i * 200 + 14 + tela.paste(grande, (x, 14), grande.split()[3]) + tela.paste(piccola, (x + 43, 196), piccola.split()[3]) + d.text((x, 296), descrizione, font=piccolo, fill=(200, 208, 216)) + percorso = OUT / "contatto.png" + tela.save(percorso) + return percorso + + +def main(): + for nome, disegna, _ in PROPOSTE: + img = disegna() + for size in (172, 86): + print("scritto", salva(img, nome, size)) + print("scritto", contatto()) + + +if __name__ == "__main__": + main()