Spaces:
Running
Running
File size: 5,358 Bytes
632bab6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | """
Genera docs/linkedin_cover.png — immagine di copertina per l'articolo LinkedIn.
Dimensioni: 1920 x 1080 px (formato raccomandato LinkedIn 2024/2025)
"""
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
ROOT = Path(__file__).parent.parent
OUT = ROOT / "docs" / "linkedin_cover.png"
W, H = 1920, 1080
# Palette
BG_TOP = (10, 25, 47) # navy scuro
BG_BOT = (17, 34, 64) # navy medio
ACCENT = (100, 180, 255) # azzurro chiaro
WHITE = (255, 255, 255)
GRAY = (160, 180, 210)
DOT_COLOR = (30, 60, 100)
def load_font(name: str, size: int) -> ImageFont.FreeTypeFont:
fonts_dir = Path("C:/Windows/Fonts")
candidates = [
name,
str(fonts_dir / name),
str(fonts_dir / "segoeui.ttf"),
str(fonts_dir / "arial.ttf"),
str(fonts_dir / "calibri.ttf"),
]
for path in candidates:
try:
return ImageFont.truetype(path, size)
except (IOError, OSError):
pass
return ImageFont.load_default()
def draw_gradient(draw: ImageDraw.ImageDraw) -> None:
for y in range(H):
t = y / H
r = int(BG_TOP[0] * (1 - t) + BG_BOT[0] * t)
g = int(BG_TOP[1] * (1 - t) + BG_BOT[1] * t)
b = int(BG_TOP[2] * (1 - t) + BG_BOT[2] * t)
draw.line([(0, y), (W, y)], fill=(r, g, b))
def draw_dot_pattern(draw: ImageDraw.ImageDraw) -> None:
"""Pattern di punti che richiama le impronte della scrittura."""
spacing = 48
for row in range(0, H // spacing + 1):
for col in range(0, W // spacing + 1):
cx = col * spacing + (spacing // 2 if row % 2 else 0)
cy = row * spacing
r = 2
draw.ellipse([cx - r, cy - r, cx + r, cy + r], fill=DOT_COLOR)
def draw_accent_lines(draw: ImageDraw.ImageDraw) -> None:
"""Linee orizzontali sottili a sinistra — richiamano righe di scrittura."""
x0, x1 = 80, 520
for y in [360, 380, 400, 420, 440, 460]:
alpha = 180 if y == 360 else 80
draw.line([(x0, y), (x1, y)], fill=(*ACCENT[:3], alpha), width=2)
def centered_text(draw: ImageDraw.ImageDraw, text: str, font, y: int,
fill=WHITE, x_offset: int = 0) -> None:
bbox = draw.textbbox((0, 0), text, font=font)
tw = bbox[2] - bbox[0]
x = (W - tw) // 2 + x_offset
draw.text((x, y), text, font=font, fill=fill)
def main() -> None:
img = Image.new("RGB", (W, H), BG_TOP)
draw = ImageDraw.Draw(img)
draw_gradient(draw)
draw_dot_pattern(draw)
# Linea accent verticale sinistra
draw.rectangle([60, 200, 66, 880], fill=ACCENT)
# Linee orizzontali "di scrittura"
for i, y in enumerate(range(340, 560, 28)):
length = 420 - i * 15
opacity = max(40, 130 - i * 18)
draw.line([(100, y), (100 + length, y)],
fill=(ACCENT[0], ACCENT[1], ACCENT[2]), width=1)
# Simbolo grafico — lente stilizzata
cx, cy, cr = 1650, 400, 120
draw.ellipse([cx - cr, cy - cr, cx + cr, cy + cr],
outline=ACCENT, width=4)
draw.ellipse([cx - cr + 16, cy - cr + 16, cx + cr - 16, cy + cr - 16],
outline=(*ACCENT, 80), width=2)
# Manico lente
lx = int(cx + cr * 0.7)
ly = int(cy + cr * 0.7)
draw.line([(lx, ly), (lx + 80, ly + 80)], fill=ACCENT, width=6)
draw.line([(lx + 80, ly + 80), (lx + 95, ly + 95)], fill=ACCENT, width=10)
# Righe stilizzate dentro la lente (testo simulato)
for i, offset in enumerate([-40, -15, 10, 35]):
length = [80, 60, 75, 45][i]
draw.line([(cx - length // 2, cy + offset),
(cx + length // 2, cy + offset)],
fill=(*WHITE, 60), width=2)
# Testo principale
font_main = load_font("segoeuib.ttf", 160)
font_sub = load_font("segoeui.ttf", 52)
font_tag = load_font("segoeui.ttf", 38)
font_badge = load_font("segoeui.ttf", 34)
font_url = load_font("segoeui.ttf", 28)
# "GraphoLab"
centered_text(draw, "GraphoLab", font_main, 300)
# Linea accent sotto il titolo
bbox = draw.textbbox((0, 0), "GraphoLab", font=font_main)
tw = bbox[2] - bbox[0]
lx0 = (W - tw) // 2
draw.rectangle([lx0, 490, lx0 + tw, 496], fill=ACCENT)
# Sottotitolo
centered_text(draw, "Artificial Intelligence in Forensic Graphology",
font_sub, 530, fill=ACCENT)
# Tag line
centered_text(draw,
"Handwritten Text Recognition · Signature Verification · Writer Identification",
font_tag, 620, fill=GRAY)
# Badge
badge_text = "8 Labs · Gradio App · Open Source · Apache 2.0"
bbox = draw.textbbox((0, 0), badge_text, font=font_badge)
bw = bbox[2] - bbox[0] + 60
bh = bbox[3] - bbox[1] + 24
bx = (W - bw) // 2
by = 730
draw.rounded_rectangle([bx, by, bx + bw, by + bh],
radius=8, fill=(20, 50, 90), outline=ACCENT, width=2)
centered_text(draw, badge_text, font_badge, by + 12, fill=WHITE)
# URL GitHub
centered_text(draw, "github.com/fabioantonini/GraphoLab",
font_url, 840, fill=GRAY)
# Linea di separazione in basso
draw.rectangle([0, H - 6, W, H], fill=ACCENT)
img.save(OUT, "PNG")
print(f"Creato: {OUT} ({W}x{H}px)")
if __name__ == "__main__":
main()
|