Files
labstream-organizador/hacer_icono.py
Labstream 8c5153e8ed OrganiLAB 1.6.1: organizador, actualizador, interfaz 1.6 y publicación
Primer commit del proyecto. Incluye el rediseño 1.6 (riel de pasos en la barra
lateral), el actualizador con reintentos y respaldo, publicar.sh y la nueva
opción de desconectar carpetas (1.6.1).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 14:26:02 -05:00

72 líneas
2.8 KiB
Python
Original Blame Histórico

Este archivo contiene caracteres Unicode ambiguos

Este archivo contiene caracteres Unicode que pueden confundirse con otros caracteres. Si crees que esto es intencional, puedes ignorar esta advertencia. Usa el botón de Escape para revelarlos.

# -*- coding: utf-8 -*-
"""Genera static/organilab.png (256 px) y static/organilab.ico (256/48/32/16) sin dependencias:
el logo OrganiLAB, cuadrado azul redondeado con tres barras blancas."""
import os
import zlib
import struct
AQUI = os.path.dirname(os.path.abspath(__file__))
AZUL = (0x1F, 0x57, 0xD6)
def pinta(n):
"""devuelve filas RGBA del logo a n×n"""
r = n * 7 / 32 # radio de las esquinas (7/32 como el SVG)
barras = [(8, 18, 1.0), (14, 13, .85), (20, 8, .65)] # (y, ancho, opacidad) en unidades de 32
filas = []
for y in range(n):
fila = bytearray()
for x in range(n):
# cuadrado redondeado con antialias sencillo (4 muestras)
dentro = 0
for sx, sy in ((.25, .25), (.75, .25), (.25, .75), (.75, .75)):
px, py = x + sx, y + sy
cx = min(max(px, r), n - r)
cy = min(max(py, r), n - r)
if (px - cx) ** 2 + (py - cy) ** 2 <= r * r:
dentro += 1
a = dentro / 4
if a == 0:
fila += bytes((0, 0, 0, 0))
continue
col = list(AZUL)
for by, bw, op in barras:
y0, y1 = by * n / 32, (by + 4) * n / 32
x0, x1 = 7 * n / 32, (7 + bw) * n / 32
rb = 2 * n / 32
if y0 <= y + .5 < y1 and x0 <= x + .5 < x1:
# esquinas de la barra redondeadas
cx = min(max(x + .5, x0 + rb), x1 - rb)
cy = min(max(y + .5, y0 + rb), y1 - rb)
if (x + .5 - cx) ** 2 + (y + .5 - cy) ** 2 <= rb * rb:
col = [int(c + (255 - c) * op) for c in AZUL]
fila += bytes((col[0], col[1], col[2], int(255 * a)))
filas.append(bytes(fila))
return filas
def png(n):
filas = pinta(n)
raw = b"".join(b"\x00" + f for f in filas)
def chunk(t, d):
return struct.pack(">I", len(d)) + t + d + struct.pack(">I", zlib.crc32(t + d) & 0xffffffff)
return (b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", n, n, 8, 6, 0, 0, 0))
+ chunk(b"IDAT", zlib.compress(raw, 9)) + chunk(b"IEND", b""))
tamanos = (256, 48, 32, 16)
imgs = [png(t) for t in tamanos]
with open(os.path.join(AQUI, "static", "organilab.png"), "wb") as fh:
fh.write(imgs[0])
# ICO con PNG incrustados (válido desde Windows Vista)
cab = struct.pack("<HHH", 0, 1, len(tamanos))
off = 6 + 16 * len(tamanos)
entradas = b""
for t, im in zip(tamanos, imgs):
entradas += struct.pack("<BBBBHHII", t % 256, t % 256, 0, 0, 1, 32, len(im), off)
off += len(im)
with open(os.path.join(AQUI, "static", "organilab.ico"), "wb") as fh:
fh.write(cab + entradas + b"".join(imgs))
print("icono listo:", [len(i) for i in imgs])