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.svga 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:
- Itera los SVGs detectando
svg_is_emf_only(). - Extrae EMF de los datos base64 a un subdirectorio
_emf2png/. - Lote 1: liboffice convierte todos los EMF a SVG vectorial en una sola invocación.
- Rasterizado: rsvg-convert transforma SVG→PNG a
png_widthpx. - Lote 2 (fallback): si rsvg falló, liboffice convierte EMF→PNG directo.
- Postprocesa cada PNG exitoso (blanco→transparente, autocrop, escalado).
- Borra el SVG original si hay PNG reemplazante.
- 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:
Truesi 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):
- Convierte RGBA.
- Identifica “casi-blanco” (R≥240 AND G≥240 AND B≥240) con
ImageChops.darker()(AND bitwise). - Resta casi-blanco del canal alpha → blanco→transparente.
- Autocrop por bbox del alpha.
- Si width < min_width, escala (LANCZOS).
- 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_widthflag (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
- Memoria: LibreOffice puede picar >500 MB con ficheros de 40 MB. No es escalable a stencils muy grandes (>100 MB).
- Tiempo: EMF→SVG lleva minutos en lote; EMF→PNG es más rápido pero con menos calidad.
- Fallidos se descartan: no hay reintento. Un master sin convertir no aparece en la librería.
- 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():
- Detección: itera SVGs, identifica solo-EMF.
- Conversión:
convert_emf_only_svgs(). - Validación post-conversión: comprueba que no hayan quedado SVGs solo-EMF sin convertir → los descarta con warning.
- 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 demasters[]. - 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]]