LaTeX embedded graphics | Include graphics in the LaTeX code
Another way to include images
Some TeX/LaTeX systems allow for including images that are not stored externally with respect to the LaTeX file itself, but rather included directly within the LaTeX file. However, since TeX/LaTeX files are plain text files and thus cannot contain binary data, we need a way to represent binary data in text form. In other words, binary data must be encoded into some text representation. The problem is that a TeX engine cannot interpret such encoded images directly. In fact, including an image is accomplished using the good old \includegraphics
command from the graphicx
package. However, this command can only deal with external image files. Yes, an external image file (along with another intermediary file) will still be created outside the LaTeX file. The key point is that you only need to distribute the LaTeX file alone.
Okay, let’s say that we somehow placed an encoded image in the LaTeX file. But how do we get the image decoded? Unfortunately, we cannot decode the file by reading it from the LaTeX file and writing it to the external image file. The text string representing the encoded image must first be written to an external text file, which can then be decoded to produce an image file.
By now, we can outline the following steps to get the desired result:
- Encode the image.
- Inject the text string representing the image data into the LaTeX file.
- Output the text string representing the image data to an external file.
- Decode the external file from Step 3.
- Include the decoded image.
The first two steps are completed by the author of the LaTeX file. A TeX engine will take care of the remaining steps, provided that it is correctly instructed, of course.
Let’s start from the very beginning. How can we encode our image to obtain a string of characters? One of the methods for doing this (and probably the most popular) is Base64.
Encoding binary data using Base64
Base64 is a group of binary-to-text encoding schemes that transforms binary data into a sequence of printable characters, limited to a set of 64 unique characters. More specifically, the source binary data is taken 6 bits at a time, then this group of 6 bits is mapped to one of 64 unique characters. As with all binary-to-text encoding schemes, Base64 is designed to carry data stored in binary formats across channels that only reliably support text content.
We can see from this short explanation that Base64 is what we need. To encode an image file to Base64, you can use a command line utility (if available on your OS), standard or third-party features of almost every programming language, or online tools such as Base64.guru or similar.
Placing the encoded image into the LaTeX file
The string of characters that you obtain as a result of encoding must be placed in the standard LaTeX filecontents*
environment in the preamble of a LaTeX file as follows:
1\documentclass{article}
2\begin{filecontents*}[overwrite]{sample-image.64}
3iVBORw0KGgoAAAANSUhEUgAAAPgAAABdCAYAAAH/B5vAAAAAGXRFWHRTb2Z0d2FyZQBBZ......
4\end{filecontents*}
5\begin{document}
6...
7\end{document}
Here it is. Step 2 is accomplished. We have the image inside the LaTeX file! But what will happen when we run the typesetting of this file with LaTeX?
A LaTeX processor will write the string of characters in the environment to an external file named sample-image.64
. Due to the use of the overwrite
option, the file will be overwritten if it already exists (e.g., if it was produced by a previous run). And that’s what accomplishes Step 3 as well!
Decoding a base64 string
Step 4 of our plan is where the differences in TeX implementations come into play. Decoding a Base64 character string is done by means of a more common thing known as the \write18
feature.
\write18
In classic TeX engines, \write<number>(<token list>)
is the primitive that writes a list of tokens. When used, this primitive is followed by an integer. If this number is negative, the tokens are written to the transcript (log) file. If the number is greater than 15
, the tokens are written to the terminal. If the number is in the range 0..15
, the tokens are written to a file whose name is specified by a preceding occurrence of the \openout
primitive. The \openout<4-bit integer>=<file name>
primitive maps a file name to a number.
Newer TeX implementations (such as PDF TeX) allow the use of \write18
. In this case, they interpret the <token list>
as a command line to be executed in the OS shell. Since this feature is obviously a potential backdoor, you might sense a touch of mystery whenever it is mentioned in TeX-related documentation or on the Internet. For this reason, the PDF TeX/LaTeX executables have command options to manage the accessibility of this feature.
Generally, there are three levels of accessibility: disabled, enabled with restrictions, and fully enabled.
In Aspose.TeX, there is a TeX job option called ShellMode
, but there are only two suitable values: NoShellEscape
and ShellRestricted
. The NoShellEscape
value means that the feature is disabled. The second value indicates that any command that needs to be executed must be implemented by the user as an extension of the Executable
class. Here, we will not delve into the details of such implementations, but we will mention that the base64
command emulation is already implemented in Aspose.TeX. By default, you can find its prototype instance in the Executables
collection property of the TeXOptions
class instance.
Decoding Base64-encoded data
To decode the contents of a file that is supposed to be some Base64-encoded data, we normally would use the following command line:
1base64 -d FILE1 > FILE2
where FILE1 is the “encoded” file and > FILE2
means that the output must be redirected to the file FILE2
.
Thus, in the body of our LaTeX file, we should add the following line:
1\immediate\write18{base64 -d sample-image.64 > sample-image.png}
The
\immediate
prefix is required to ensure that the\write
operation is performed as soon as the primitive command is encountered by the TeX scanner. Otherwise, it will be processed at the time of page ship-out.
If we run the typesetting of the file now, we will see that the image file sample-image.png
is created. Come on, open it in a viewer to check!
Including the decoded image
As we mentioned at the beginning of the article, to include the decoded image, we use the well-known LaTeX command \includegraphics
:
1\includegraphics[options]{sample-image.png}
So, the complete (nearly) LaTeX file might look as follows:
1\documentclass{article}
2\begin{filecontents*}[overwrite]{sample-image.64}
3iVBORw0KGgoAAAANSUhEUgAAAPgAAABdCAYAAAH/B5vAAAAAGXRFWHRTb2Z0d2FyZQBBZ......
4\end{filecontents*}
5\begin{document}
6 \write18{base64 -d sample-image.64 > sample-image.png}
7 \includegraphics[options]{sample-image.png}
8\end{document}
And the C# code using the Aspose.TeX API is similar to that in other articles, except for specifying the ShellMode
option:
1TeXOptions options = TeXOptions.ConsoleAppOptions(TeXConfig.ObjectLaTeX);
2// Specify a file system working directory for the output.
3options.OutputWorkingDirectory = new OutputFileSystemDirectory(RunExamples.OutputDirectory);
4// Initialize the options for saving in PDF format.
5options.SaveOptions = new PdfSaveOptions();
6// Enable the shell command execution.
7options.ShellMode = ShellMode.ShellRestricted;
8// Run LaTeX to PDF conversion.
9new TeXJob(Path.Combine(RunExamples.InputDirectory, "embedded-base64-image.tex"), new PdfDevice(), options).Run();
And now we are done with the Step 5. For truly complete examples, explore our Example project.
You may also check out the free conversion web app built based on Aspose.TeX for .NET API.