6

I have a problem when trying to scale and externalize a tikzpicture that includes an external graphics file. Using the following code will result in an output of the document but the figure is not externalized into a separate file. Also, an error message is produced. When commenting tikzexternalize or using input{test.tikz} (i.e. not scaling the tikzpicture) everything works, though obviously without the corresponding effect. Also, tikzpictures without an external graphic work just fine. Is there any way to combine tikzscale and tikzexternalize for tikzpictures including an external graphic?

\documentclass[crop,10pt,border=0]{standalone}
\usepackage[english]{babel}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{external}
\tikzexternalize[shell escape=-enable-write18]
\usepackage{tikzscale}
\usepackage{mwe}
\usepackage{filecontents}

\begin{document}
\setlength{\textwidth}{510pt}
\begin{filecontents}{test.tikz}
\begin{tikzpicture}
\node at (0,0) {\includegraphics[width=.25\textwidth]{example-image-a}};
\end{tikzpicture}
\end{filecontents}
This is my document.
% \input{test.tikz}
    \includegraphics[width=0.5\textwidth]{test.tikz}
\end{document}

The error message is the following:

! Package tikz Error: Sorry, the system call 'pdflatex -enable-write18 -halt-on -error -interaction=batchmode -jobname "external-test-figure0" "\def\tikzextern alrealjob{external-test}\input{external-test}"' did NOT result in a usable outp ut file 'external-test-figure0' (expected one of .pdf:.jpg:.jpeg:.png:). Please verify that you have enabled system calls. For pdflatex, this is 'pdflatex -sh ell-escape'. Sometimes it is also named 'write 18' or something like that. Or m aybe the command simply failed? Error messages can be found in 'external-test-f igure0.log'. If you continue now, I'll try to typeset the picture.

  • 1
    Could you please post the complete error message? Is it one of those "Sorry, ..." ones? – sdaau Jun 20 '14 at 2:50
  • @sdaau Yep, it's one of those, i'll add it to the question. – Janek Jun 20 '14 at 11:29
2

Ok, I've found a workaround for this. As this has been bothering me for a long time and also includes some other issues to consider, I'll answer this step by step.

Task: Create a tikzpicture consisting of an external graphics (.png,.jpg,.pdf) that will not result in an error when used with tikzscale and \tikzexternalize.

Questions: Why a tikzpicture and not just \includegraphics?
-Because I want to add some elements to the picture, which is easy to do in tikz.
Why using tikzscale?
-Because I like to have my figures to have the same width as the text while keeping the fontsize of axes, nodes etc. independent of the figure's width. tikzscale is the tool for this.
Why \tikzexternalize?
-Not using \tikzexternalize means that every tikzpicture is recompiled every time, the document is compiled. Depending on the tikzpicture's complexity, this will take a lot of time.

The first approach:
The first approach can be seen in the original question. I placed a node in a tikzpicture and filled it with \includegraphics. This results in an error. The document is produced correctly, but the tikzpictureis not externalized i.e. saved in a separate .pdf.

The second approach:
In some earlier work I learned that pgfplots' \addplot graphics actually works with tikzscale and \tikzexternalize. The idea is now to put the exterael graphic in the axis environment and to hide the axes, ticks and labels. Let's assume we want a tikzpicture containing the following graphics (example-image-16x10.jpg included in the mwe package):
example-image-16x10
The code then reads as follows (the tikzpicture is written in a separate file test.tikz to load it with tikzscale's \includegraphics). note the ticks=none and axis lines=none options to hide the axes, ticks and labels:

\documentclass[10pt]{scrartcl}
\usepackage[english]{babel}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{external}
\tikzexternalize[shell escape=-enable-write18]
\usepackage{tikzscale}
\usepackage{pgfplots}
\usepackage{mwe}
\usepackage{filecontents}
\pgfplotsset{compat=1.10}
\begin{document}
\begin{filecontents}{test.tikz}
\begin{tikzpicture}
\begin{axis}[
    xmin=0,xmax=1,ymin=0,ymax=1,
    ticks=none,
    axis lines=none,
    ]
    \addplot graphics [xmin=0,xmax=1,ymin=0,ymax=1] {example-image-16x10};
\end{axis}
\end{tikzpicture}
\end{filecontents}
First we will include the picture as a normal graphics:
\begin{figure}[hb]
    \centering
    \includegraphics[width=0.5\textwidth]{example-image-16x10}
    \caption{This is the figure without using \textit{tikzpicture}.}
\end{figure}
\newline Next, we include the figure as a \textit{tikzpicture} using \textit{tikzscale}.
\begin{figure}
    \centering
    \includegraphics[width=0.5\textwidth]{test.tikz}
    \caption{This is my figure in \textit{tikzpicture}'s \textit{axis} environment. Unfortunaltely it is stretched into a square shape.}
    \end{figure}
\end{document}

When one compiles this code (twice), one will note, that the graphics in the tikzpicture is streched vertically, as pgfplots' axis environment tends to crate square shaped plots. To keep the original image's aspect ratio, one has to define a new \addplot command that will measure the original image's aspect ratio and scale the axes accordingly as demonstrated in an earlier question \addplot graphics: maintaining image's aspect ratio despite different scaling of axes.
The final code is then:

\documentclass[10pt]{scrartcl}
\usepackage[english]{babel}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{external}
\tikzexternalize[shell escape=-enable-write18]
\usepackage{tikzscale}
\usepackage{pgfplots}
\usepackage{mwe}
\usepackage{filecontents}
\pgfplotsset{compat=1.10}

\makeatletter
\newcommand\addplotgraphicsnatural[2][]{%
    \begingroup
    \pgfqkeys{/pgfplots/plot graphics}{#1}%
    \setbox0=\hbox{\includegraphics{#2}}%
    \pgfmathparse{\wd0/(\pgfkeysvalueof{/pgfplots/plot graphics/xmax} - \pgfkeysvalueof{/pgfplots/plot graphics/xmin})}%
    \let\xunit=\pgfmathresult
    \pgfmathparse{\ht0/(\pgfkeysvalueof{/pgfplots/plot graphics/ymax} - \pgfkeysvalueof{/pgfplots/plot graphics/ymin})}%
    \let\yunit=\pgfmathresult
    \xdef\marshal{%
        \noexpand\pgfplotsset{unit vector ratio={\xunit\space \yunit}}%
    }%
    \endgroup
    \marshal
    \addplot graphics[#1] {#2};
}   
\makeatother


\begin{document}
\begin{filecontents}{test.tikz}
\begin{tikzpicture}
\begin{axis}[
    xmin=0,xmax=1,ymin=0,ymax=1,
    ticks=none,
    axis lines=none,
    ]
    \addplotgraphicsnatural [xmin=0,xmax=1,ymin=0,ymax=1] {example-image-16x10};
\end{axis}
\end{tikzpicture}
\end{filecontents}
First we will include the picture as a normal graphics:
\begin{figure}[hb]
    \centering
    \includegraphics[width=0.5\textwidth]{example-image-16x10}
    \caption{This is the figure without using \textit{tikzpicture}.}
\end{figure}
\newline Next, we include the figure as a \textit{tikzpicture} using \textit{tikzscale}.
\begin{figure}
    \centering
    \includegraphics[width=0.5\textwidth]{test.tikz}
    \caption{This is my figure in \textit{tikzpicture}'s \textit{axis} environment. Unfortunaltely it is stretched into a square shape.}
    \end{figure}
\end{document}

This will produce the desired document as well as the externalized figure. I don't know whether there is a more elegant way to do this, but it works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.