Exportar a imagen (TeX2img/dvisvgm/ImageMagick)

Una figura dibujada en LaTeX ya es arte vectorial antes de exportar nada: los ejes existen como curvas y las etiquetas como glifos de una fuente. Y sin embargo, en cuanto se exporta como imagen, esa información se tira con una facilidad desconcertante. Lo que decide si se tira ocurre mucho antes de lo que casi todos suponen: en la única elección de pasar por DVI o pasar por PDF. El manual de dvisvgm lo dice sin rodeos: el texto presente en archivos PDF y PostScript se convierte siempre en elementos de trazado. Si pasa por un PDF, las letras de su figura dejan de ser letras. Esta página ordena standalone, pdfcrop, dvisvgm y el rasterizado justamente en torno a ese eje.

Poner solo la figura en una página: la clase standalone

El primer paso de la exportación es darle al papel el tamaño de la figura. La clase standalone de Martin Scharrer (v1.3b en TeX Live 2024) fija las dimensiones de la página a las del contenido. Poniendo aquí solo $\displaystyle \int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}$ dentro de \documentclass[border=2pt,preview]{standalone} y ejecutando pdflatex, el PDF resultante tenía una página de 85.779 × 27.993 pt: exactamente el contorno de la fórmula. Sin border, el valor por defecto es 0pt en los cuatro lados. La clase fija el curioso 0.50001bp —pensado para que el redondeo no rebane el borde de un glifo— pero el standalone.cfg que la acompaña lo sobrescribe con \standaloneconfig{border=0pt} justo antes de procesar las opciones. Para un dibujo de TikZ se usa \documentclass[tikz,border=2pt]{standalone} y se coloca el tikzpicture justo después de \begin{document}. Para recortar un fragmento de texto corrido que deba plegarse, se le da una anchura con algo como varwidth=10cm. El paquete preview que standalone usa por debajo se escribió originalmente para preview-latex, dentro de AUCTeX en Emacs: de ahí viene la idea de componer solo una rebanada de documento.

latex
% fig.tex — a figure that is its own page
\documentclass[tikz,border=2pt]{standalone}
\begin{document}
\begin{tikzpicture}
  \draw[thick,->] (0,0) -- (3,0) node[right] {$x$};
  \draw[thick,->] (0,0) -- (0,2) node[above] {$y$};
  \draw[blue,thick] (0,0) .. controls (1,2) .. (3,1);
\end{tikzpicture}
\end{document}

Recortar los márgenes de un PDF ya hecho: pdfcrop

Cuando la figura vive dentro de un documento corriente y no se puede reconstruir, pdfcrop sirve. Es un script en Perl de Heiko Oberdiek (v1.42 en TeX Live 2024) que calcula el rectángulo envolvente del contenido de la página y encoge la caja de recorte hasta él. Medido aquí: un documento de una página en tamaño carta de 612 × 792 pt salió de pdfcrop doc.pdf doc-crop.pdf con 345 × 539 pt. Si no quiere que el margen sea cero, --margins 10 devuelve 10 pt a cada lado y da 365 × 559 pt. Una advertencia: pdfcrop llama a Ghostscript — la cabecera del script lo dice tal cual, «Requirements: Perl5, Ghostscript». Sin gs instalado no funciona. Y si de todos modos puede generar la figura con standalone, pdfcrop sobra: no crear el margen es más rápido y más exacto que recortarlo.

terminal
pdfcrop doc.pdf doc-crop.pdf              # 612x792 pt becomes 345x539 pt
pdfcrop --margins 10 doc.pdf doc-crop.pdf # keep 10 pt on every side
pdfcrop --hires doc.pdf doc-crop.pdf      # use the high-resolution bounding box

Producir un SVG: dvisvgm y por qué gana la vía DVI

Para una figura destinada a la web, SVG es el primer candidato. El dvisvgm de Martin Gieseking (3.2.2 en TeX Live 2024) convierte DVI, EPS y PDF a SVG, pero lo que sale depende de la puerta por la que se entró. Colocando \def\pgfsysdriver{pgfsys-dvisvgm.def} antes de \documentclass, produciendo un DVI con latex y ejecutando dvisvgm fig.dvi, el SVG resultante llevaba los ejes y la curva como elementos <path> y las etiquetas $x$, $y$ y $y=f(x)$ como elementos <text>: las letras seguían siendo letras, remitiendo a fuentes vectoriales incrustadas en <defs>. Entrando por un PDF eso no ocurre. El manual de dvisvgm afirma sin ambages que el texto presente en archivos PDF y PostScript se convierte siempre en elementos de trazado. En efecto, al pasar el PDF de la misma figura por pdftocairo -svg de poppler, el SVG resultante tenía cero elementos <text>.

latex
% figdvi.tex — the DVI route, which keeps the labels as real text
\def\pgfsysdriver{pgfsys-dvisvgm.def}
\documentclass[tikz,border=2pt]{standalone}
\begin{document}
\begin{tikzpicture}
  \draw[thick,->] (0,0) -- (3,0) node[right] {$x$};
  \draw[blue,thick] (0,0) .. controls (1,2) .. (3,1);
\end{tikzpicture}
\end{document}
terminal
latex figdvi.tex        # produce a DVI, not a PDF
dvisvgm figdvi.dvi      # SVG with <text> elements and vector paths

# the PDF route needs a helper and outlines all text:
dvisvgm --pdf fig.pdf   # requires mutool with Ghostscript 10.01 or newer

Ir de PDF a SVG choca además con un obstáculo muy concreto. dvisvgm --pdf antes entregaba el PDF a Ghostscript, pero según el manual el nuevo intérprete de PDF introducido en Ghostscript 10.01.0 inutilizó esa vía, y dvisvgm busca ahora mutool, de MuPDF. En la máquina usada para este artículo (Ghostscript 10.03.0, sin mutool), dvisvgm --pdf fig.pdf se detiene con ERROR: can't retrieve number of pages from file fig.pdf. Así que la vía PDF exige una dependencia más; y en cuanto es Ghostscript quien procesa el archivo, se aplica la regla del manual y el texto acaba convertido en contornos de todos modos: dos razones para preferir la vía DVI. Otra opción que conviene recordar es -e (--exact-bbox): por defecto la caja envolvente se deduce de las métricas TFM, de modo que un glifo que realmente las desborde puede quedar recortado. Si las letras aparecen rebanadas en el borde de una figura, empiece por aquí.

Qué hacer con las fuentes del SVG: --font-format y --no-fonts

Conservar <text> está bien, pero queda una decisión más. Por defecto, dvisvgm usa fuentes SVG<font> y <glyph> incrustados en <defs>—, que existen en la especificación pero no están admitidas ni mucho menos en todas partes; el propio manual de dvisvgm dice, en la entrada --no-fonts, que la salida en trazados es «más compatible con la mayoría de aplicaciones que no admiten fuentes SVG». Comparando las tres variantes sobre la misma figura de TikZ: las fuentes SVG por defecto dieron 5.790 bytes, --font-format=woff2 dio 4.815 bytes (un WOFF2 como URI de datos en el src de una regla @font-face) y --no-fonts dio 8.290 bytes con cero elementos <text> y cada glifo convertido en un <path>. La regla práctica es sencilla. Para la web: --font-format=woff2 — el texto sigue siendo seleccionable y cualquier navegador lo dibuja. Para entregar el archivo a Illustrator, Inkscape o PowerPoint: --no-fonts — más grande, pero no queda nada que pueda representarse mal.

OpciónTexto dentro del SVGTamaño con la misma figuraUso adecuado
--font-format=svg<text> más fuentes SVG (por defecto)5.790 bytessoporte irregular; rara vez la opción correcta
--font-format=woff2<text> y un WOFF2 incrustado con @font-face4.815 bytespublicación web; texto seleccionable y archivo más pequeño
--no-fontssin <text>; cada glifo es un <path>8.290 bytesentrega a otro programa de dibujo; nada puede verse mal

Rasterizar a PNG, para diapositivas y herramientas antiguas

Todavía hay muchos destinos que rechazan el SVG; entonces se recurre al PNG. La resolución se fija con -r: tome 300 dpi como suelo y 600 dpi como objetivo para impresión o pantallas de alta densidad. Rasterizar a 600 dpi el PDF de la fórmula de 85.779 × 27.993 pt construido antes produjo un PNG transparente de unos 715 × 233 píxeles, tanto con Ghostscript (gs -sDEVICE=pngalpha -r600) como con pdftocairo -png -r 600 -transp de poppler. Como 72 pt son una pulgada, 85.779 ÷ 72 × 600 ≈ 715; comprobar que la cuenta cuadra es la forma de confirmar que la opción de resolución surtió efecto. Si no quiere transparencia, -sDEVICE=png16m (o pdftocairo sin -transp) da fondo blanco. Muchos textos recomiendan ImageMagick con magick -density 300 in.pdf out.png, pero ImageMagick delega el renderizado del PDF en Ghostscript. No forma parte de TeX Live ni estaba instalado en la máquina usada aquí, así que no se ha comprobado su comportamiento. Si quien dibuja de verdad es Ghostscript, llamarlo directamente ahorra una dependencia.

terminal
# Ghostscript, transparent background, 600 dpi
gs -q -dNOPAUSE -dBATCH -sDEVICE=pngalpha -r600 \
   -dTextAlphaBits=4 -dGraphicsAlphaBits=4 \
   -sOutputFile=eq.png eq.pdf

# poppler, same result, shorter to type
pdftocairo -png -r 600 -transp -singlefile eq.pdf eq

De la fuente al PNG en una orden: el convert= de standalone y --shell-escape

Si teclear tres órdenes cada vez cansa, delegue el trabajo en la opción de clase convert= de standalone. En cuanto termina la composición, la propia clase lanza una orden de conversión al intérprete de comandos. El motor puede ser imagemagick (el predeterminado), ghostscript o pdf2svg, y la resolución por defecto es density=300. Incluso sin ImageMagick, indicar ghostscript funciona: con \documentclass[border=2pt,convert={ghostscript,density=600,outext=.png}]{standalone} y pdflatex --shell-escape eqc.tex, el registro mostró gs -dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m -r600 -sOutputFile=eqc.png eqc.pdf y de esa única orden salió un PNG de 715 × 233. Como se lanza un programa externo, el escape de shell restringido no basta: hace falta --shell-escape. En un proyecto con muchas figuras es más seguro dejar la conversión en un script de compilación, para que --shell-escape no se convierta en costumbre.

latex
% eqc.tex — build the PNG in the same run
\documentclass[border=2pt,convert={ghostscript,density=600,outext=.png}]{standalone}
\usepackage{amsmath}
\begin{document}
$\displaystyle \int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}$
\end{document}

% then: pdflatex --shell-escape eqc.tex

Todo lo anterior —componer solo el fragmento, recortarlo y llevarlo luego a vector o a mapa de bits— es lo que TeX2img envuelve en una interfaz gráfica. Se pega una fórmula, se elige formato y resolución, y el programa se ocupa de la transparencia y el suavizado. Para una exportación puntual es rapidísimo; para un documento con decenas de figuras que pasa por muchas revisiones, al final resulta más cómodo integrar en la compilación las órdenes de las secciones anteriores. TeX2img es una aplicación independiente, no forma parte de TeX Live y no estaba instalada en la máquina usada aquí, así que no se ha comprobado su comportamiento.

A qué formato exportar

  • Una figura destinada a la web → SVG. Produzca un DVI con latex y ejecute dvisvgm --font-format=woff2. El texto se queda dentro de <text> y nada se degrada al ampliar.
  • Una figura que volverá a un documento LaTeX → déjela en PDF. Hecha con standalone no tiene margen y entra directa en \includegraphics.
  • Diapositivas, Word, redes sociales → PNG, con gs -sDEVICE=pngalpha -r600 o pdftocairo -png -r 600 -transp. Quite la transparencia solo si quiere fondo blanco.
  • Una figura que va a retocar en Illustrator o Inkscape → SVG con --no-fonts. Las formas se mantienen incluso donde falte la fuente.
  • Una figura con fotografía → JPEG solo para la fotografía; el dibujo de línea y las etiquetas, en SVG o PNG. Pasarlo todo a JPEG ensucia el borde de las letras.
  • Cuando dvisvgm --pdf se niega a funcionar → cambie primero a la vía DVI. Si de veras debe partir de un PDF, instale mutool de MuPDF.