Automating TeX Equations Conversion to Images
I recently had the following problem. I wrote a paper for a conference using L^{a}T_{e}X
but the publisher wanted a WYSIWYG file for the proceedings.
And, unfortunately, pandoc
output did not came out so great, especially with equations.
But, fortunately, you can fairly easily generate images directly from your L^{a}T_{e}X source.
Here is how to do it using T_{e}X \write
command.
T_{e}X Streams
T_{e}X has the ability to write and read text file for later input by T_{e}X or other programs.
This is how L^{a}T_{e}X or L^{a}T_{e}X packages generate
tables of content (.toc files)
, list of Figures (.lof),
, crossreferences (.aux),
, navigation (.nav — Beamer)
, indexes (.ind — makeindex command)
or bibliographies (.bibl, .blg, .bcf, .run.xml —BibT_{e}X).
To create an output stream, use \openout
\openout<number> = <filename>
where <number>
is the stream identifier (kinda like a file descriptor in C^{1}
)
which must be between 0 and 15 in T_{e}X for writing to text files.
But this limit varies from one T_{e}X engine to the other (LuaT_{e}X goes up to 255).
Also, some <number>
have a special meaning such as 18 which executes system commands.
And that’s what we are going to use to generate our image equations.
The \newwrite
command allocate a number between 0 and 15 for use with \openout
\newwrite\fd
\openout\fd=<filename>
And now, we’re ready to write to the stream :
\write\fd{<tokenlist>}
Another important command is the \immediate
command.
By default, T_{e}X actually writes whenever it fancies to
which is fine most of the time
but sometimes, you need to write at once, like when issuing a system command
whose result is needed right after.
\immediate\write18{<systemcommands>}
And since we will be writing L^{a}T_{e}X commands to a file, we also need the \unexpanded
command
to prevent macro expansion
png Generation
Since T_{e}X can write files and execute system commands, the idea is that we can generate a pdf file for each equation and convert it to png on the fly.
Therefore, for each equation, we
 set the equation number (optional)
 generate a L^{a}T_{e}X file for each equation
 compile it
 convert the resulting pdf to an image
 import the resulting image to the main file
The last step is optional but allows for checking the resulting image.
The template to generate individual L^{a}T_{e}X equations files looks like this
\documentclass[preview]{standalone}
\usepackage{amsmath}
\begin{document}
\makeatletter
\advance \csname c@equation\endcsname <equationnumber>\relax%% set equation number
\makeatother
<equation>
\end{align}
\end{document}
And here the command to compile the generated L^{a}T_{e}X file and convert the pdf to png using convert
pdflatex haltonerror jobname "\pname{\pngeqc}" "\pname{\pngeqc}.tex";%
convert density 300 colorspace RGB transparent white "\pname{\pngeqc}.pdf" "\pname{\pngeqc}.png";%
where \pngeqc
is the equation number and \pname
an helper macro to format the files’ name.
The ability to send command to the system is totally unsafe (think \immediate\write18{rm rf ./*}
) and therefore is disabled by default.
This is why we need do compile the main file with the shellescape
option.
Putting everything together, this is what it looks like :
%% Equation counter (TeX)
\newcount\pngeqc%
\pngeqc 1\relax%
%%
%% Helper command to format the file name
%%
\def\pname#1{fig\the#1}%
%%
%% Helper command to import the equation png file
%%
\newcommand\includepng[1]{%
{%
\centering
\includegraphics[width=\linewidth]{\pname{#1}.png}%
}
}%
%%
\newcommand{\pngequation}[1]{%
%%
%% Local equation counter
%%
\newcount\eqc
\eqc\the\pngeqc\relax%
%% eqc 1
\advance\eqc 1 \relax%
%% Set Latex equation count
\csname c@equation\endcsname\eqc\relax
%%
%% Write the equation in #1 to a Latex file
%%
%%
%% Create output stream
\newwrite\fd\relax%
\immediate\openout\fd=\pname{\pngeqc}.tex%%
\immediate\write\fd{\unexpanded{%
%%
%% Write Latex header
%%
\documentclass[varwidth]{standalone}
\usepackage{amsmath}%
\begin{document}
%%
%% Set Latex equation count
%%
\advance \csname c@equation\endcsname%
}
%%
\the\eqc%
%%
\unexpanded{%
\relax
%% Write the equation block
\begin{align}#1\end{align}%
%%
\end{document}
}}%
%% Close the output stream
\immediate\closeout\fd%
%%
%% Create a subprocess to compile the Latex file and convert the resulting pdf to png
%%
\immediate\write18{%
pdflatex haltonerror jobname "\pname{\pngeqc}" "\pname{\pngeqc}.tex";%
convert density 300 colorspace RGB transparent white "\pname{\pngeqc}.pdf" "\pname{\pngeqc}.png";%
}
%% Display equation in the main file
\begin{align}#1\end{align}%
%% Import the png in the main file
\includepng{\pngeqc}
%%
\pngeqc\csname c@equation\endcsname
\advance\pngeqc 1 \relax%
}
Note that this displays the equation twice (its T_{e}X rendering and the png image). Also, this what written for a separate file that contained the missing equations. This can be modified to fit in the original file.
And this is how to use it :
%% set equation number
\pngeqc=3\relax%
%%
\pngequation{%
\sin^2 \theta + \cos^2 \theta = 1
}
%%
\pngequation{%
\sin \theta & = \pm \sqrt{ 1 + \cos^2 \theta } \\
\cos \theta & = \pm \sqrt{ 1 + \sin^2 \theta }
}
%%
\pngeqc=11\relax%
%%
\pngequation{%
e^{x+i y} = e^{x}( \cos y + i \sin y )
}
The result looks like this :
Of course, there’s plenty of room for improvement. For instance, the png equations look different than the pdf equations and I failed to fixed that. This is a common problem when using L^{a}T_{e}X. It is incredibly hard to simply achieve what you want (compared to, say, css}. That said, I’m far from being a L^{a}T_{e}X guruninja. All I know is this worked for me.

In C, file descriptors are represented as objects of type
int
, while streams are represented asFILE * struct
. On Unix platforms, File descriptors point to an entry in the file descriptor table maintained by the kernel. [↩]
OpenEdition suggests that you cite this post as follows:
Thomas Soubiran (September 17, 2023). Automating TeX Equations Conversion to Images. NUMA. Retrieved August 10, 2024 from https://doi.org/10.58079/vn48