4

My usual practice for large documents with a lot of illustrations is to organize the graphics files into one or more subdirectories, and then to add those subdirectories to the graphics path so that \includegraphics can find the illustrations:

\documentclass{article}
\usepackage{graphicx}
\graphicspath{{images/}}
\begin{document}
\includegraphics[width=\linewidth]{cc-by-sa}
\end{document}

The problem with this approach is that if my TeX installation happens to contain a file named, say, cc-by-sa.png (which, coincidentally, TeX Live 2015 does), then \includegraphics uses that graphic instead of mine. In this case, instead of ./images/cc-by-sa.pdf, my document contains /opt/texlive/2015/texmf-dist/tex/latex/stex/mikoslides/cc-by-sa.png.

Maybe the package authors had good reasons for implementing this behaviour, but I find it inconvenient for my use cases. When I am naming a graphics file for use in my document, I don't want to have to manually check for clashes against a list of all graphics in my entire TeX installation (which, to be safe, is something I need to do every time I update TeX Live, since package authors occasionally add graphics files).

How can I prevent \includegraphics from looking for graphics in my entire TeX installation, or at least from looking there first? I want my own manually specified graphics paths to take precedence.

The package documentation (dated 2014/04/27) seems to contradict itself as to whether this is possible. On page 12 it says that \graphicspath "may be used to specify a list of directories in which to search for graphics files" and that "the default setting of this path is \input@path". To me this implies that there exists a default which will be overridden if \graphicspath is explicitly set. However, the following page suggests that manually setting \graphicspath only supplements, but does not replace, the default: "Note that LaTeX will find the graphics file by searching along TEXINPUTS (and possibly other places, as specified with \graphicspath)". The search order is not specified.

  • What about adding the directories to TEXINPUTS instead? – cfr Apr 7 '16 at 21:40
  • Unless that can be done from within the LaTeX document, it's a rather inconvenient solution. – Psychonaut Apr 7 '16 at 21:56
  • @Psychonaut It's what I'd do, or rather I'd just make sure that TEXINPUTS starts with .//: so that subdirectories of the current directory are at the head of the search path, path searching with TEXINPUTS is much faster than \graphicspath which does the logic in TeX rather than C – David Carlisle Apr 7 '16 at 22:33
  • Yes, but it also means that everyone with whom I share the document source (coauthors, publishers, etc.) may need to make the same change to their environment. – Psychonaut Apr 8 '16 at 7:35
4

The \includegraphics macro relies on \IfFileExists to check for existence of the file and take actions in order to determine the picture's bounding box.

If \graphicspath has been set, the standard \input@path is locally reset to \Ginput@path (whose value is derived from the argument to \graphicspath.

Here is the definition of \IfFileExists in latex.ltx (the later one, there is another one that is used during startup):

\long\def \IfFileExists#1#2#3{%
  \openin\@inputcheck#1 %
  \ifeof\@inputcheck
    \ifx\input@path\@undefined
      \def\reserved@a{#3}%
    \else
      \def\reserved@a{\@iffileonpath{#1}{#2}{#3}}%
    \fi
  \else
    \closein\@inputcheck
    \edef\@filef@und{#1 }%
    \def\reserved@a{#2}%
  \fi
  \reserved@a}

The file is first tested with \openin that uses TEXINPUTS by design of the TeX system. If nothing is found there, \ifeof would be true and \input@path is used for the next lookup.

As a consequence, directories specified with \graphicspath are always looked for after system directories.

The only way (lest of redefining \IfFileExists) is to specify the directory in the call of \includegraphics:

\includegraphics[width=\linewidth]{./images/cc-by-sa}

A (slow) implementation of the lookup with \Ginput@path in front of TEXINPUTS:

\documentclass{article}
\usepackage{graphicx}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\slowincludegraphics}{O{}m}
 {
  \psychonaut_ig:nn { #1 } { #2 }
 }

\cs_new_protected:Nn \psychonaut_ig:nn
 {
  \tl_if_in:nnTF { #2 } { / }
   {% an explicit path has been passed
    \includegraphics[#1]{#2}
   }
   {% do the slow processing
    \_psychonaut_ig:nn { #1 } { #2 }
   }
 }
\cs_new_protected:Nn \_psychonaut_ig:nn
 {
  \tl_map_inline:cn { Ginput@path }
   {
    \_psychonaut_file_if_exist:nT { ##1#2 }
     {
      \tl_map_break:n { \includegraphics[#1]{##1#2} }
     }
   }
 }
\bool_new:N \l__psychonaut_file_exist_bool
\prg_new_conditional:Nnn \_psychonaut_file_if_exist:n { T }
 {
  \bool_set_false:N \l__psychonaut_file_exist_bool
  \clist_map_inline:cn { Gin@extensions }
   {
    \file_if_exist:nT { #1##1 }
     {
      \clist_map_break:n { \bool_set_true:N \l__psychonaut_file_exist_bool }
     }
   }
  \bool_if:NTF \l__psychonaut_file_exist_bool
   {
    \prg_return_true:
   }
   {
    \prg_return_false:
   }
 }

\AtBeginDocument
 {
  \tl_if_exist:cF { Ginput@path } { \tl_new:c { Ginput@path } }
  \tl_put_right:cn { Ginput@path } { {} }
 }
\ExplSyntaxOff

\graphicspath{{images/}}

\begin{document}

\slowincludegraphics[width=\linewidth]{cc-by-sa}

\end{document}
  • This leads me to believe that \graphicspath is, in general, unsafe and should never be used. In fact, right now there are dozens of CTAN packages which use it in their documentation; any or all of these could be broken if someone accidentally or deliberately contributed a new package with clashing graphics filenames. – Psychonaut Apr 7 '16 at 21:49
  • 1
    @Psychonaut \graphicspath is indeed not the recommended device. However, I added an implementation of the lookup like you want. Slow, but there's little you can do about it. – egreg Apr 7 '16 at 22:07
  • 1
    @Psychonaut Note that the scenario you describe is usually unproblematic because the contents of doc/ are not searched for input files. So if package A has image.png in its doc directory and package B has image.png in its, each package's documentation will use the appropriate image. Of course, this is no guarantee because some packages install graphics into input directories. But images used solely in the documentation would not usually be installed in a path in TEXINPUTS. – cfr Apr 7 '16 at 22:12
  • 1
    @Psychonaut Also, in most implementations, the current directory is searched first. So even if some package installs image.png under tex/latex/..., packages A and B will still use their own copies provided their documentation includes the .tex file and image.png in the same directory. – cfr Apr 7 '16 at 22:14
  • 2
    Alternatively, I find naming images in Welsh generally works ;). – cfr Apr 7 '16 at 22:18
3

The situation is similar to input TeX files (as it uses the same mechanism to find files)

If you prepend the filename with ./ then it will only look in the current directory before using the graphics path

\documentclass{article}

\usepackage{graphicx}

\graphicspath{{images/}}

\begin{document}

%known name clash with image in input path
\includegraphics{./example-image}

\end{document}

if images contains an image (also) called example-image.png then you get

<images/./example-image.png, id=1, 401.5pt x 301.125pt>
<use images/./example-image.png>

so the local one is used.

If instead you use

\includegraphics{example-image}

then the log shows

<example-image.png, id=1, 401.5pt x 301.125pt> <use example-image.png>

and in fact the one from here is used

$ kpsewhich example-image.png
/usr/local/texlive/2015/texmf-dist/tex/latex/mwe/example-image.png

The graphics package couldn't be that explicit about the interaction with TEXINPUTS as at the time it was writen (1993 mostly) not all TeX systems had TEXINPUTS and those that had didn't all use the variable in the same way. (Which was why LaTeX has \input@path at all, to allow file search for package files on systems with no built in path search, it just got re-used for graphics as it was there....)

  • So, er... egreg is mistaken in claiming that 'The only way...'? – cfr Apr 7 '16 at 22:35
  • @cfr I couldn't possibly comment on my elders:-) – David Carlisle Apr 8 '16 at 6:33
  • @DavidCarlisle, thanks to you and egreg for the explanations. As you (David) are the author of the graphicx documentation, perhaps you might consider revising the text on pages 12 and 13 to better explain the path-searching behaviour, as well as the issue and workarounds discussed here? – Psychonaut Apr 8 '16 at 7:41

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.