CreaRack-SL

Servicio: Conversor EMF → SVG/PNG (stencils Visio)

Ubicación

racks/utils/visio_parser.py — módulo convert_emf_only_svgs() y helpers.

Propósito

Convertir arte bitmap incrustado (EMF) de stencils Visio a formatos renderizables por navegador (PNG/SVG vectorial). Dirigido a fabricantes como Cisco que distribuyen stencils con arte nativo de Windows en lugar de geometría Visio.

Interfaz pública

convert_emf_only_svgs(temp_dir, svg_names, png_width=2400, timeout=600)

Entrada:

  • temp_dir (str): directorio con SVGs generados por libvisio-ng.
  • svg_names (list[str]): nombres de fichero .svg a procesar.
  • png_width (int): ancho destino en píxeles para rasterizado (default 2400, nítido en modal).
  • timeout (int): timeout para invocaciones de LibreOffice/rsvg (default 600 s).

Salida:

  • dict: {svg_name_original: png_name_reemplazante} para los stencils convertidos con éxito.

Comportamiento:

  1. Itera los SVGs detectando svg_is_emf_only().
  2. Extrae EMF de los datos base64 a un subdirectorio _emf2png/.
  3. Lote 1: liboffice convierte todos los EMF a SVG vectorial en una sola invocación.
  4. Rasterizado: rsvg-convert transforma SVG→PNG a png_width px.
  5. Lote 2 (fallback): si rsvg falló, liboffice convierte EMF→PNG directo.
  6. Postprocesa cada PNG exitoso (blanco→transparente, autocrop, escalado).
  7. Borra el SVG original si hay PNG reemplazante.
  8. Limpia el directorio temporal _emf2png/.

Excepciones:

  • Ninguna lanzada. Los errores en conversión se capturan (try/except) y el stencil fallido se omite del resultado → el llamador lo descarta.

Casos de uso:

  • Cisco Catalyst (9200/9300/9000): 165 masters solo-EMF.
  • Cualquier vendor que incruste arte bitmap.
  • Los SVGs con geometría real (Eaton) se ignoran.

svg_is_emf_only(svg_text)

Entrada:

  • svg_text (str): contenido del SVG generado por libvisio-ng.

Salida:

  • bool: True si el SVG contiene SOLO un EMF incrustado (sin geometría vectorial).

Lógica:

  • Detecta data:image/emf;base64, (expresión regular).
  • Verifica ausencia de cualquier etiqueta de geometría: <path>, <rect>, <line>, <polyline>, <polygon>, <ellipse>, <circle>, <text>.
  • Ambas condiciones deben cumplirse para retornar True.

Usos:

  • Screening previo en convert_emf_only_svgs().
  • Tests unitarios de detección.
  • Validación post-conversión (para descartar fallidos).

_postprocess_stencil_png(png_path, min_width=800)

Entrada:

  • png_path (str): ruta del PNG a postprocesar.
  • min_width (int): ancho mínimo después de autocrop (default 800 px).

Salida:

  • Modifica el PNG in situ (guarda).

Operaciones (todas en C vía Pillow, sin loop por píxel):

  1. Convierte RGBA.
  2. Identifica “casi-blanco” (R≥240 AND G≥240 AND B≥240) con ImageChops.darker() (AND bitwise).
  3. Resta casi-blanco del canal alpha → blanco→transparente.
  4. Autocrop por bbox del alpha.
  5. Si width < min_width, escala (LANCZOS).
  6. Guarda PNG.

Robustez:

  • Si algo falla (lectura, conversión, PIL), la excepción se captura silenciosamente (no revierte el PNG original).

Datos de entrada

  • EMF binarios: extraídos de atributos data:image/emf;base64,... en SVGs de libvisio-ng.
  • Ficheros .vss/.vsdx de Cisco: 40–87 MB; Catalyst 9000 tiene 165 masters, pico de ~700 MB en memoria durante conversión.

Datos de salida

  • PNGs renderizables: 2400 px de ancho (escalables sin pérdida en el modal de stenciles).
  • Metadatos preservados: nombre de master, altura en U, half_width flag (si aplica) — NOT tocados por este servicio.

Dependencias

  • LibreOffice: headless, debe estar instalado en el worker. Convierte EMF→SVG y EMF→PNG.
  • rsvg-convert: herramienta CLI de librsvg, convierte SVG vectorial→PNG nítido.
  • Pillow (PIL): postproceso de imágenes (alpha, crop, resize).
  • subprocess: invocación de herramientas externas.

Limitaciones y trade-offs

  1. Memoria: LibreOffice puede picar >500 MB con ficheros de 40 MB. No es escalable a stencils muy grandes (>100 MB).
  2. Tiempo: EMF→SVG lleva minutos en lote; EMF→PNG es más rápido pero con menos calidad.
  3. Fallidos se descartan: no hay reintento. Un master sin convertir no aparece en la librería.
  4. Auto-reparación: los stencils importados rotos (pre-fix) no se arreglan sin re-importar.

Integración con flujo de importación

Llamado desde racks.tasks.convert_visio_async() tras libvisio_ng.convert():

  1. Detección: itera SVGs, identifica solo-EMF.
  2. Conversión: convert_emf_only_svgs().
  3. Validación post-conversión: comprueba que no hayan quedado SVGs solo-EMF sin convertir → los descarta con warning.
  4. Metadatos: los nombres de master, altura en U, etc., se preservan (este servicio solo toca imágenes).

Testing

  • Unit tests (test_emf_only_detection): mock SVG con/sin EMF.
  • Integration tests (test_emf_only_svgs_become_png_masters): flujo completo con stencil fake.
  • Descarte (test_emf_only_unconvertible_is_dropped): master fallido se quita de masters[].
  • QA real (test_real_vsdx_converts_and_imports, Cisco Catalyst 9000):
    • 165 masters, ≥90% convertidos a PNG.
    • Guardia de memoria: <900 MB → skip con aviso.

Véase también

  • [[feature—stencils—visio-emf-to-png]]
  • [[entity—racks—function—svg-is-emf-only]]
  • [[entity—racks—model—stencil]]
  • [[entity—racks—task—convert-visio-async]]
  • [[concept—infrastructure—liboffice-workers]]