""" Genera el icono de Labmagic a partir del wordmark blanco real de Labstream. - icono.ico / icono.png: la opción elegida (OPCION_POR_DEFECTO). - iconos/opcion-N.ico|png: todas las opciones, por si se quiere cambiar (basta copiar una sobre icono.ico). - iconos/opciones.png: hoja de muestra con las opciones a 256 px y a tamaño pequeño. """ import os from PIL import Image, ImageDraw, ImageFont HERE = os.path.dirname(os.path.abspath(__file__)) LOGO_BLANCO = r"C:\Users\Munka\OneDrive\Labstream\Propuestas\0_Modelo Propuestas\Logos\Logo Blanco.png" OPCION_POR_DEFECTO = 2 ROJO = (227, 38, 44, 255) ROJO_OSCURO = (170, 22, 28, 255) NEGRO = (16, 16, 16, 255) BLANCO = (255, 255, 255, 255) SS = 4 # supermuestreo def cargar_wordmark(): """Devuelve (wordmark 'labstream', 'lab' solo, logo completo con STUDIO), todos RGBA blancos recortados.""" img = Image.open(LOGO_BLANCO).convert("RGBA") w, h = img.size full = img.crop(img.getbbox()) word = img.crop((0, 0, w, int(h * 0.66))) word = word.crop(word.getbbox()) lab = word.crop((0, 0, int(word.width * 0.295), word.height)) lab = lab.crop(lab.getbbox()) return word, lab, full def fondo(size, color, radio=0.22, borde=None, grosor=0.035, inset=0.065): s = size * SS img = Image.new("RGBA", (s, s), (0, 0, 0, 0)) d = ImageDraw.Draw(img) d.rounded_rectangle((0, 0, s - 1, s - 1), radius=int(s * radio), fill=color) if borde: i = int(s * inset) d.rounded_rectangle((i, i, s - 1 - i, s - 1 - i), radius=int(s * (radio - inset * 0.8)), outline=borde, width=max(1, int(s * grosor))) return img def pegar_centrado(base, art, ancho_rel, dy_rel=0.0): s = base.width ratio = art.height / art.width w = int(s * ancho_rel) h = int(w * ratio) art = art.resize((w, h), Image.LANCZOS) x = (s - w) // 2 y = int((s - h) / 2 + s * dy_rel) base.alpha_composite(art, (x, y)) return base def punto(base, cx_rel, cy_rel, r_rel, color): s = base.width d = ImageDraw.Draw(base) cx, cy, r = s * cx_rel, s * cy_rel, s * r_rel d.ellipse((cx - r, cy - r, cx + r, cy + r), fill=color) return base def opcion(n, size): word, lab, full = cargar_wordmark() if n == 1: # Rojo, borde blanco fino, wordmark blanco base = fondo(size, ROJO, borde=BLANCO) return pegar_centrado(base, word, 0.74) if n == 2: # Rojo, wordmark grande "lab" + punto REC blanco base = fondo(size, ROJO, borde=BLANCO) pegar_centrado(base, lab, 0.56, dy_rel=-0.03) return punto(base, 0.5, 0.78, 0.055, BLANCO) if n == 3: # Negro con borde rojo, wordmark blanco y punto rojo base = fondo(size, NEGRO, borde=ROJO, grosor=0.05) pegar_centrado(base, word, 0.74, dy_rel=-0.04) return punto(base, 0.5, 0.74, 0.05, ROJO) if n == 4: # Rojo oscuro degradado, logo completo (labstream + STUDIO) s = size * SS grad = Image.new("RGBA", (s, s), ROJO) gd = ImageDraw.Draw(grad) for y in range(s): t = y / s c = tuple(int(ROJO[i] * (1 - t) + ROJO_OSCURO[i] * t) for i in range(3)) + (255,) gd.line((0, y, s, y), fill=c) mask = fondo(size, BLANCO) base = Image.new("RGBA", (s, s), (0, 0, 0, 0)) base.paste(grad, (0, 0), mask) ImageDraw.Draw(base).rounded_rectangle((int(s * 0.065), int(s * 0.065), s - 1 - int(s * 0.065), s - 1 - int(s * 0.065)), radius=int(s * 0.17), outline=BLANCO, width=max(1, int(s * 0.03))) return pegar_centrado(base, full, 0.72) raise ValueError(n) def render(n, size): return opcion(n, size).resize((size, size), Image.LANCZOS) def guardar_ico(n, ruta_ico, ruta_png): sizes = [16, 24, 32, 48, 64, 128, 256] imgs = [render(n, s) for s in sizes] imgs[-1].save(ruta_ico, format="ICO", sizes=[(s, s) for s in sizes], append_images=imgs[:-1]) render(n, 64).save(ruta_png) def hoja(ruta): """Hoja de muestra: cada opción a 256 px, y a 48/32/16 px para ver cómo se lee en pequeño.""" try: font = ImageFont.truetype("C:/Windows/Fonts/segoeui.ttf", 22) fontb = ImageFont.truetype("C:/Windows/Fonts/segoeuib.ttf", 26) except Exception: # noqa: BLE001 font = fontb = ImageFont.load_default() nombres = {1: "1 · Rojo, borde blanco, wordmark", 2: "2 · Rojo, 'lab' grande + punto", 3: "3 · Negro, borde rojo, wordmark", 4: "4 · Rojo degradado, logo completo"} col_w, pad = 360, 40 sheet = Image.new("RGBA", (col_w * 4 + pad, 470), (24, 24, 24, 255)) d = ImageDraw.Draw(sheet) d.text((pad, 14), "Opciones de icono para Labmagic", fill=(240, 240, 240, 255), font=fontb) for i, n in enumerate((1, 2, 3, 4)): x0 = pad + i * col_w sheet.alpha_composite(render(n, 256), (x0, 60)) y = 340 xx = x0 for s in (48, 32, 16): sheet.alpha_composite(render(n, s), (xx, y + (48 - s) // 2)) xx += s + 14 d.text((x0, 405), nombres[n], fill=(200, 200, 200, 255), font=font) sheet.save(ruta) if __name__ == "__main__": out_dir = os.path.join(HERE, "iconos") os.makedirs(out_dir, exist_ok=True) for n in (1, 2, 3, 4): guardar_ico(n, os.path.join(out_dir, f"opcion-{n}.ico"), os.path.join(out_dir, f"opcion-{n}.png")) guardar_ico(OPCION_POR_DEFECTO, os.path.join(HERE, "icono.ico"), os.path.join(HERE, "icono.png")) hoja(os.path.join(out_dir, "opciones.png")) print("icono por defecto: opción", OPCION_POR_DEFECTO, "->", os.path.join(HERE, "icono.ico"))