[Tex/LaTex] Set resolution of Tikz picture exported to pdf using \tikzexternalize

externalizeresolutiontikz-pgf

When exporting a tikzpicture to its own pdf file for publications, I want to be able to specify the exact size and resolution of the exported pdf file. Specifically 8.5 cm wide and 600 dpi images.

MWE:

\documentclass[12pt]{standalone}

\usepackage[usenames,dvipsnames]{xcolor}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,arrows.meta,external}

\tikzexternalize

\begin{document}

\resizebox{8.5cm}{!}{
     \begin{tikzpicture}
            %some drawing here
     \end{tikzpicture}
    }

\end{document}

Then use pdflatex -shell-escape TikzFigure.pdf to create the figure.

Best Answer

Resolution

TikZ is by nature a vector graphics system and the generated PDF file keeps this property. Of course, bitmap images can be included and used in the TikZ graphics. But TeX is not an program with capabilities for image processing. It only can include bitmap images and can do some transformations (e.g. scale, rotate). But it cannot change the image data. Therefore, the image resolution cannot be changed.

Scale to final width

The following hacks into internals of pgf to access the picture box, before it is typeset. At the beginning of \pgfsys@typesetpicturebox, the picture box \pgfpic has size zero and the origin of the picture is the reference point of the box. The dimensions of the picture are provided by other registers \pgf@picminx, \pgfpicminy, ... They can be used to calculate the actual with and then the scale factor. The box is then resized by the scale factor and the registers are updated according to the scale factor.

Example:

\documentclass[12pt]{standalone}

\usepackage[usenames,dvipsnames]{xcolor}
\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,arrows.meta,external}
\usepackage{etoolbox}

\tikzexternalize

\makeatletter
\newcommand*{\set@picwidth}[1]{%
  \edef\RequestedPicWidth{\the\dimexpr(#1)}%
  \edef\ActualPicWidth{\the\dimexpr\pgf@picmaxx-\pgf@picminx}%
  \ifx\RequestedPicWidth\ActualPicWidth
  \else
    \ifdim\ActualPicWidth>\z@
      \pgfmathsetmacro\ScaleFactor{\RequestedPicWidth/\ActualPicWidth}%
      \typeout{* Scale factor: \ScaleFactor}%
      \setbox\pgfpic=\hbox{%
        \scalebox{\ScaleFactor}{\box\pgfpic}%
      }%
      \pgf@picminx=\ScaleFactor\pgf@picminx
      \pgf@picmaxx=\ScaleFactor\pgf@picmaxx
      \pgf@picminy=\ScaleFactor\pgf@picminy
      \pgf@picmaxy=\ScaleFactor\pgf@picmaxy
      \pgf@shift@baseline=\ScaleFactor\pgf@shift@baseline
      \pgf@trimleft@final=\ScaleFactor\pgf@trimleft@final
      \pgf@trimright@final=\ScaleFactor\pgf@trimright@final
    \else
      \errmessage{The actual picture width (\ActualPicWidth) is not positive.}%
    \fi
  \fi
}
\newenvironment{picwidth}[1]{%
  \pretocmd\pgfsys@typesetpicturebox{\set@picwidth{#1}}{}{%
    \errmessage{Patching \noexpand\pgfsys@typesetpicturebox failed!}%
  }%
  \ignorespaces
}{%
  \ignorespacesafterend
}
\makeatother

\begin{document}
  \begin{picwidth}{8.5cm}
    \begin{tikzpicture}
      \draw (0, 0) circle[radius=1] node{Hello};
   \end{tikzpicture}%
  \end{picwidth}
\end{document}

Result

The .log file contains the calculated scale factor: 4.22034

Related Question