pgf icon indicating copy to clipboard operation
pgf copied to clipboard

`\pgfimage` should support `\graphicspath`

Open JasonGross opened this issue 10 months ago • 9 comments

Brief outline of the bug

Using includegraphics cmd=\pgfimage breaks use of \graphicspath

Minimal working example (MWE)

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{pgfplots}
\DeclareUnicodeCharacter{2212}{−}
\usepgfplotslibrary{groupplots,dateplot}
\usetikzlibrary{patterns,shapes.arrows}
\pgfplotsset{compat=newest}
\usepackage{graphicx}
\usepackage{amssymb}
\begin{document}

\begin{figure}
\centering
\graphicspath{{images/}}
\begin{tikzpicture}
\begin{axis}[
    title=Example Plot,
    xlabel=$x$,
    ylabel={$f(x)$},
]
% Attempting to use \addplot graphics without specifying the full path
\addplot graphics [includegraphics cmd=\pgfimage,xmin=0,xmax=1,ymin=0,ymax=1] {some-image.png};
\end{axis}
\end{tikzpicture}
\caption{Plot with an external image}
\end{figure}

\end{document}

JasonGross avatar Apr 02 '24 22:04 JasonGross

I assume you meant an example other than example-image as example-image.pdf is in the default input path and your example as posted works without error with or without the \graphicspath (which isn't used)

davidcarlisle avatar Apr 02 '24 22:04 davidcarlisle

Yes, if you put, e.g., example-image.png in images/, then it does not work

JasonGross avatar Apr 02 '24 22:04 JasonGross

sure but you need to rename it as otherwise it'll always pick up the standard one anyway the example as posted gives no error whether or not \graphicspath is used and whether or not there is an images subdirectory. it's not my code I'm just an interested observer but is there an advantage here to using \pgfimage rather than using \includegraphics?

davidcarlisle avatar Apr 02 '24 23:04 davidcarlisle

Ah, okay, I guess I didn't quite test thoroughly enough, thanks. I've renamed it.

I'm not sure if there's any advantage, but includegraphics cmd=\pgfimage is automatically generated by tikzplotlib.

JasonGross avatar Apr 03 '24 00:04 JasonGross

Duplicate of #565 and #1259.

You can try what I posted in this TeX-SX answer,

\makeatletter
\let\pgfutil@InputIfFileExists=\InputIfFileExists
\let\pgfutil@IfFileExists=\IfFileExists
\makeatother

muzimuzhi avatar Apr 03 '24 14:04 muzimuzhi

Is there a way to make this work with \tikzexternalize?

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{pgfplots}
\usepackage{import}
\DeclareUnicodeCharacter{2212}{−}
\usepgfplotslibrary{groupplots,dateplot}
\usetikzlibrary{patterns,shapes.arrows}
\pgfplotsset{compat=newest}
\usepackage{graphicx}
\usepackage{amssymb}
\makeatletter
\let\pgfutil@InputIfFileExists=\InputIfFileExists
\let\pgfutil@IfFileExists=\IfFileExists
\makeatother
\usetikzlibrary{external}
\tikzexternalize
\begin{document}
\immediate\write18{mkdir -p images}
\begin{filecontents}{images/some-image.tex}
\documentclass{article}
\begin{document}
.
\end{document}
\end{filecontents}
\immediate\write18{pdflatex -output-directory=images images/some-image.tex}
\begin{filecontents}{images/foo.tex}
\begin{tikzpicture}
\begin{axis}[
    title=Example Plot,
    xlabel=$x$,
    ylabel={$f(x)$},
]
% Attempting to use \addplot graphics without specifying the full path
\addplot graphics [includegraphics cmd=\pgfimage,xmin=0,xmax=1,ymin=0,ymax=1] {some-image.pdf};
\end{axis}
\end{tikzpicture}
\end{filecontents}
\begin{figure}
\centering
\import{images/}{foo.tex}
\caption{Plot with an external image}
\end{figure}
\end{document}

JasonGross avatar Apr 03 '24 21:04 JasonGross

I was wrong in https://github.com/pgf-tikz/pgf/issues/1314#issuecomment-2034776456 in part. This issue is not a direct duplicate of #1259 since apart from \pgfutil@InputIfFileExists and \pgfutil@IfFileExists, to make \pgfimage aware \graphicspath one need to patch \pgf@findfile too.

Example 1 redefines all these three commands and now \pgfimage supports \graphicspath, just like \includegraphics.

\documentclass{article}
\usepackage{tikz}

\makeatletter
\let\pgfutil@InputIfFileExists=\InputIfFileExists
\let\pgfutil@IfFileExists=\IfFileExists

\ifdefined\ExplLoaderFileDate
  \ExplSyntaxOn
  \def\pgfutil@getfullnameTF{\file_get_full_name:nNTF}
  \def\pgfutil@ifemptyTF{\tl_if_empty:nTF}
  \ExplSyntaxOff

  \def\pgf@findfile#1:#2+#3{%
    \begingroup
    % similar to how \Ginput@path is used in \Ginclude@graphics, graphics.sty
    \let\input@path=\Ginput@path
    \pgf@findfile@i#1:#2+{#3}%
    \endgroup
  }
  \def\pgf@findfile@i#1:#2+#3{%
    \pgfutil@getfullnameTF{#3#1}\pgf@filefound
      {\global\let\pgf@filename=\pgf@filefound}%
      {\pgfutil@ifemptyTF{#2}{}{\pgf@findfile@i#2+{#3}}}%
  }
\fi
\makeatother

\graphicspath{{./tikz-gh1314}}

% create sub-dir "./tikz-gh1314" and image "./tikz-gh1314/some-image-2.pdf"
\immediate\write18{mkdir -p tikz-gh1314}
\begin{filecontents}[force]{tikz-gh1314/some-image-2.tex}
\documentclass{standalone}
\begin{document}
\fbox{some-image-2.tex}
\end{document}
\end{filecontents}
\immediate\write18{pdflatex -output-directory=tikz-gh1314 tikz-gh1314/some-image-2.tex}

\begin{document}
\includegraphics{some-image-2}

\pgfimage{some-image-2}
\end{document}

image

Adding the same redefinitions to example in https://github.com/pgf-tikz/pgf/issues/1314#issuecomment-2035649610, it errors in first run, but then works in all following runs. Content of some-image.tex is modified to get some content in a proper-sized image.

! Extra }, or forgotten \endgroup.
\@endfloatbox ...pagefalse \outer@nobreak \egroup 
                                                  \color@endbox 
l.74 \end{figure}

image

Example 2, \tikzexternalize example + patch

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{pgfplots}
\usepackage{import}
\DeclareUnicodeCharacter{2212}{−}
\usepgfplotslibrary{groupplots,dateplot}
\usetikzlibrary{patterns,shapes.arrows}
\pgfplotsset{compat=newest}
\usepackage{graphicx}
\usepackage{amssymb}

\usetikzlibrary{external}
\tikzexternalize

\makeatletter
\let\pgfutil@InputIfFileExists=\InputIfFileExists
\let\pgfutil@IfFileExists=\IfFileExists

\ifdefined\ExplLoaderFileDate
  \ExplSyntaxOn
  \def\pgfutil@getfullnameTF{\file_get_full_name:nNTF}
  \def\pgfutil@ifemptyTF{\tl_if_empty:nTF}
  \ExplSyntaxOff

  \def\pgf@findfile#1:#2+#3{%
    \begingroup
    % similar to how \Ginput@path is used in \Ginclude@graphics, graphics.sty
    \let\input@path=\Ginput@path
    \pgf@findfile@i#1:#2+{#3}%
    \endgroup
  }
  \def\pgf@findfile@i#1:#2+#3{%
    \pgfutil@getfullnameTF{#3#1}\pgf@filefound
      {\global\let\pgf@filename=\pgf@filefound}%
      {\pgfutil@ifemptyTF{#2}{}{\pgf@findfile@i#2+{#3}}}%
  }
\fi
\makeatother

\graphicspath{{tikz-gh1314/}}

% create sub-dir "./tikz-gh1314" and image "./tikz-gh1314/some-image-2.pdf"
\immediate\write18{mkdir -p tikz-gh1314}
\begin{filecontents}[force]{tikz-gh1314/some-image.tex}
\documentclass{standalone}
\begin{document}
\fbox{some-image.tex}
\end{document}
\end{filecontents}
\immediate\write18{pdflatex -output-directory=tikz-gh1314 tikz-gh1314/some-image.tex}

% create file "./tikz-gh1314/foo.tex"
\begin{filecontents}[force]{tikz-gh1314/foo.tex}
\begin{tikzpicture}
  \begin{axis}[
      title=Example Plot,
      xlabel=$x$,
      ylabel={$f(x)$},
  ]
    % Attempting to use \addplot graphics without specifying the full path
    \addplot graphics
      [includegraphics cmd=\pgfimage,xmin=0,xmax=1,ymin=0,ymax=1]
      {some-image.pdf};
  \end{axis}
\end{tikzpicture}
\end{filecontents}

\begin{document}
\begin{figure}
  \centering
  \import{tikz-gh1314/}{foo.tex}
  \caption{Plot with an external image}
\end{figure}
\end{document}

muzimuzhi avatar Apr 04 '24 14:04 muzimuzhi

Thank you!

it errors in first run, but then works in all following runs.

What's the cause of the error?

JasonGross avatar Apr 04 '24 14:04 JasonGross

I don't know why.

Either removing force or adding noheader option to the filecontents environment for foo.tex fixes the error.

With force option, the same file is written twice, one by main tex file and one by the externalization system call. As the current \jobname is written to header comments unless noheader is specified, I'm guessing the culprit is the change of content of generated file.

Example header

%% LaTeX2e file `bar.tex'
%% generated by the `filecontents' environment
%% from source `tikz-gh1314-external-figure0' on 2024/04/05.
%%

Example 3: A simplified version raising error ! Too many }'s.

If \input bar.tex is used in an environment, then the same error ! Extra }, or forgotten \endgroup. is raised.

\documentclass{article}
\usepackage{tikz}

\usetikzlibrary{external}
\tikzexternalize

\begin{filecontents}[force]{bar.tex}
\begin{tikzpicture}
  \draw (0,0) rectangle (1,1);
\end{tikzpicture}
\end{filecontents}

\begin{document}
\input bar.tex
\end{document}
  • expected image
  • actual/first run image

muzimuzhi avatar Apr 04 '24 16:04 muzimuzhi