PerfectVector
Por Irene Kim9 min de lectura

Imágenes SVG en WeasyPrint: corrige logotipos ausentes en PDF

Corrige logotipos SVG ausentes en PDF de WeasyPrint con una URL base correcta y tamaños CSS explícitos, y comprueba trazados vectoriales, proporciones e ilustración en el PDF guardado.

En esta página

WeasyPrint puede colocar un SVG en un PDF mediante un elemento de imagen HTML. Si el logotipo desaparece al pasar HTML como cadena, comprueba primero la URL de la imagen: una ruta relativa necesita una URL base. Una vez cargado el archivo, establece su tamaño de impresión en CSS e inspecciona el PDF guardado. La referencia actual de la API de WeasyPrint documenta este requisito de base_url.

El ejemplo siguiente reproduce ese caso de imagen ausente con un logotipo original en forma de marco. También comprueba que el PDF reparado contenga geometría de dibujo vectorial al tamaño solicitado. Si ya tienes un SVG, empieza con ese archivo. La vectorización solo entra en este flujo cuando la ilustración original existe como píxeles.

Comprueba la carga antes de cambiar la ilustración

Se puede crear un PDF aunque falte su logotipo. Comprueba la advertencia del recurso, resuelve la ruta de imagen y vuelve a renderizar el mismo SVG antes de editar sus formas o convertirlo a otro formato.

Reproduce el SVG ausente con un documento pequeño

Probamos con Python 3.13.9 y WeasyPrint 70.0. Usa un entorno de proyecto e instala la versión fijada:

python -m pip install "weasyprint==70.0"
python -m weasyprint --info

WeasyPrint también necesita bibliotecas nativas, incluido Pango. Sigue sus instrucciones de instalación según el sistema operativo si fallan la importación o el comando de versión. Una biblioteca nativa ausente es un problema diferente de un logotipo ausente.

Crea esta estructura de carpetas:

example/
  render.py
  assets/
    logo.svg

Guarda esta ilustración original de demostración como assets/logo.svg. La abertura central permite inspeccionar algo más útil que un rectángulo sólido. Es geometría creada manualmente, no una conversión de PerfectVector.

<svg xmlns="http://www.w3.org/2000/svg"
     width="120" height="60" viewBox="0 0 120 60">
  <path fill="#087f8c" fill-rule="evenodd"
        d="M0 0H120V60H0Z M20 15V45H100V15Z"/>
</svg>

Coloca lo siguiente en render.py:

from pathlib import Path
import logging
from weasyprint import HTML
 
logging.basicConfig(level=logging.WARNING)
root = Path(__file__).resolve().parent
 
html = """<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    @page { size: A4; margin: 20mm; }
    body { margin: 0; }
    .logo { display: block; width: 60mm; height: auto; }
  </style>
</head>
<body>
  <img class="logo" src="assets/logo.svg" alt="Frame logo">
</body>
</html>
"""
 
HTML(string=html).write_pdf(root / "missing-base.pdf")
 
HTML(
    string=html,
    base_url=root.as_uri() + "/",
).write_pdf(root / "resolved.pdf")

Ejecuta python render.py. En nuestro primer PDF, el marco no aparecía y se mostraba el texto alternativo de la imagen. El registro contenía:

Relative URI reference without a base URI: assets/logo.svg

El segundo PDF mostró el marco verde azulado con su abertura intacta. Ambas llamadas produjeron un archivo, por lo que la existencia de un PDF no era por sí sola una comprobación útil de éxito.

Da a las rutas relativas una carpeta inicial estable

assets/logo.svg identifica un archivo relativo a otra ubicación. El base_url de la segunda llamada proporciona ese punto de partida. root.as_uri() crea una URI de archivo absoluta; la barra final la convierte en una base de directorio. El logotipo permanece en la misma carpeta assets y el contenido SVG no cambia.

Usar Path(__file__) también mantiene el ejemplo vinculado a la carpeta del script cuando lo ejecutas desde otro directorio de trabajo. En un cuaderno, usa una carpeta explícita del proyecto, ya que __file__ normalmente no está disponible.

Ilustración de una imagen SVG en una carpeta conectada mediante una flecha a la misma ilustración en una página de documento
Ilustración de resolución de recursos: el documento necesita una ruta hasta el archivo SVG antes de colocar la ilustración.

Hay otra prueba de control útil. Guarda el HTML como invoice.html junto a render.py y carga el propio archivo:

HTML(filename=str(root / "invoice.html")).write_pdf(
    root / "from-file.pdf"
)

WeasyPrint puede deducir una base a partir del nombre de archivo o URL de entrada. Nuestra prueba basada en archivo produjo el mismo marco que el caso con base explícita. Una cadena HTML no tiene un nombre de archivo correspondiente del que deducirlo. Estos modos de entrada y sus reglas de resolución de base se documentan en el constructor HTML.

Para una imagen alojada detrás de un inicio de sesión, una URL correcta puede seguir siendo insuficiente. La documentación del recuperador de URL indica que el cliente HTTP predeterminado no proporciona cookies ni autenticación. Usa el mecanismo de obtención de recursos aprobado de tu aplicación y pruébalo en el entorno que genera el PDF. No supongas que un logotipo visible en tu navegador con sesión iniciada sea accesible para el proceso PDF.

Establece el tamaño de imagen por separado del tamaño de página PDF

El ejemplo usa @page para la hoja A4 y los márgenes, mientras que .logo establece una anchura de imagen de 60 mm. Su proporción original 2:1 le da 30 mm de altura con height: auto. En nuestro PDF guardado, el marco medía 60 × 30 mm y empezaba a 20 mm de los bordes superior e izquierdo de la página.

Aquí el dibujo ocupa todo su viewBox. Tu logotipo puede tener espacio vacío dentro de ese rectángulo, así que una caja de imagen de 60 mm puede contener una marca visiblemente más estrecha. Comprueba el lienzo SVG antes de compensarlo con una anchura CSS mayor arbitraria. La guía de tamaño de importación SVG explica esta distinción con más detalle.

Mantén write_pdf() con su valor predeterminado zoom=1 al comprobar dimensiones físicas. La referencia de salida PDF de WeasyPrint advierte que cambiar zoom también escala las unidades CSS físicas y los tamaños de página con nombre.

Qué vesPrimera comprobaciónSiguiente paso
El texto alternativo sustituye al logotipoURL de imagen y registro de recursosProporciona una URL base válida o una URL absoluta accesible
El logotipo aparece con tamaño incorrectoAnchura CSS y relación de aspecto originalEstablece una anchura física e inspecciona el lienzo SVG
Falta parte de la ilustraciónLímites originales y función SVG concretaReduce a un ejemplo pequeño que falle y compara el PDF exportado
El renderizado local funciona, pero el del servidor fallaArchivos, fuentes y acceso URL disponiblesPrueba con los recursos del proceso desplegado

Inspecciona el contenido y el aspecto del PDF

La documentación actual de formatos de WeasyPrint indica que las imágenes SVG se renderizan como vectores en la salida PDF. Eso no significa que cualquier archivo terminado en .svg sea una ilustración completamente vectorial: un SVG puede contener un mapa de bits incrustado. Compruébalo con el diagnóstico de imágenes incrustadas cuando el resultado siga viéndose pixelado.

Para este ejemplo sencillo, inspeccionamos los PDF guardados con PyMuPDF 1.26.7:

Caso de entradaRegistros de dibujoImágenes incrustadasMarco visible
Cadena HTML sin base00Ausente; apareció el texto alternativo
Cadena HTML con base de carpeta1060 × 30 mm, abertura conservada
HTML cargado por nombre de archivo10Mismo resultado que la cadena resuelta

Estos resultados se aplican al marco proporcionado, no a todas las funciones SVG. Un trazado compuesto tampoco significa una forma visible única: su subtrazado interior define la abertura.

Para inspeccionar tu resolved.pdf, instala pymupdf==1.26.7 y ejecuta:

import pymupdf
 
with pymupdf.open("resolved.pdf") as document:
    page = document[0]
    print("Drawing records:", len(page.get_drawings()))
    print("Embedded images:", len(page.get_images()))
    for drawing in page.get_drawings():
        box = drawing["rect"]
        print("Bounds in mm:", box.width * 25.4 / 72,
              box.height * 25.4 / 72)

La referencia de Page de PyMuPDF documenta los métodos de inspección de dibujos e imágenes. Estos recuentos son diagnósticos, no un certificado de fidelidad. Abre también el PDF: comprueba la abertura, los colores, las proporciones y las letras al tamaño real de entrega. Inspecciona las ilustraciones complejas elemento por elemento y repite las comprobaciones al actualizar el renderizador.

Cuándo conviene preparar primero un nuevo SVG

Cuando el único logotipo disponible es un PNG o JPG, el vectorizador de logotipos de PerfectVector puede preparar una primera versión SVG antes de colocarla en el documento HTML. Inspecciona los contornos, las aberturas pequeñas y las letras en un editor y prueba el SVG mediante el mismo proceso WeasyPrint. La guía de vectorización de imágenes explica qué cambia cuando los píxeles se convierten en trazados.

Conserva un SVG editable original cuando exista. Corrige su referencia de archivo o distribución en lugar de volver a vectorizarlo. Las fotografías pueden seguir siendo imágenes rasterizadas y las letras de marca exactas pueden necesitar la fuente original o un redibujo manual. La vectorización no repara archivos de servidor ausentes, autenticación ni funciones de renderizado incompatibles.

Si solo necesitas convertir un SVG en su propia página PDF, el flujo de exportación de CairoSVG cubre esa tarea más pequeña. WeasyPrint encaja en el caso de documentos HTML, donde la ilustración comparte página con otro contenido.

Preguntas frecuentes

¿Por qué WeasyPrint crea un PDF sin mi logotipo SVG? Un fallo de carga de imagen puede permitir que se renderice el resto del documento. Comprueba el registro de recursos y la URL de imagen. En la prueba proporcionada, una cadena HTML con ruta de imagen relativa necesitó una URL base explícita.

¿Tengo que convertir primero el SVG en PNG? No. WeasyPrint acepta imágenes SVG. Conserva las ilustraciones vectoriales compatibles como SVG cuando esa sea la salida prevista y comprueba el PDF guardado. Una exportación rasterizada es una alternativa cuando eliges deliberadamente el aspecto sobre la geometría vectorial.

¿base_url cambia el tamaño impreso del logotipo? No. Proporciona la base para resolver URL de recursos relativas. Establece el tamaño de colocación de la imagen con CSS y comprueba por separado las dimensiones y el viewBox del SVG.

Fuentes

  1. Referencia de API de WeasyPrint — Documenta entradas HTML, URL base, salida SVG y comportamiento del zoom PDF.
  2. Primeros pasos de WeasyPrint — Cubre instalación y obtención de recursos, incluidos los límites de autenticación.
  3. Referencia de Page de PyMuPDF — Documenta los métodos de inspección de dibujos e imágenes incrustadas usados en el ejemplo.

¿Solo tienes un logotipo rasterizado? Prepara un SVG con PerfectVector, inspecciona sus formas y letras, colócalo en tu HTML y verifica su aspecto y tamaño físico en el PDF guardado.

Más del blog

Empieza con un SVG más limpio
y fácil de editar