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 tikzpicture
is 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):
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.
Best Answer
Warning: Several threads on TeX StackExchange and elsewhere identify
write18
as a security risk. The fullest discussion I found is several years old atWhat analysis of Texlive's restricted permissions model exists?
I do not understand these issues but I can see that experts who do understand them did not agree on the risk. So I will not leave the switch -enable-write18 in my PDFLaTeX, though TikZexternalize will not work without it.
Using MiKTeX with WinEdt, you can make the program quoted from the TikZ manual above work by going to Options, Execution modes, PDFLaTeX, and entering
in switches. I do not know if there is any reason you could not as well do it by adding this to switches for PDFTeXify or others.
However, when it works this way, it does require that the file name have no space. For example the file name
will prevent compiling. Use instead
Revision_on_conjugation