# tikz - output pdf with specific ratio

When use tikz generate a pdf file, I use below command to convert it to 1920x1080 png file.

convert -density 300 exam.pdf -resize 1920x1080  out.png


But if the original pdf is not 16:9 ratio, then the output file will not exactly as expected, (e.g. 1080x1080).

How can I instruct tikz to output a pdf with fix ratio (16:9 for example).

BTW, this method will use resize, will this conversion lost image quality? how to keep best quality to convert a pdf to png?

for example:

\documentclass[border=2mm]{standalone}
\usepackage{tikz}
\begin{document}
\tiny\begin{tikzpicture}[]
\draw (0,0) circle (5cm);
\end{tikzpicture}
\end{document}


This circle will generate a pdf with 10cmx10cm, so default ratio is 1:1. what I need is circle still a circle but ratio is 16:9.

• In order to "resize" the tikzpicture, one can either (i) rescale the x and/or y direction(s) or (ii) extend the bounding box in the x and/or y direction(s). Both of them can be automatically done by writing some stuff to the aux file and recovering it in the next run. Obviously, (i) "deforms" the picture while (ii) creates some empty space. Which of these options (if any) are you looking for?
– user194703
Mar 23 '20 at 16:43
• Thanks, update circle sample but still not figure out how do keep output ratio at 16:9. Mar 23 '20 at 16:54
• Well, as I asked in the above comment, the options are (i) to change, say, the xscale, which deforms the circle, or (ii) add white space. You need to decide which of these options you want to go for.
– user194703
Mar 23 '20 at 16:59
• @Schrödinger'scat Option 2 should be great. I do not want to deform the image but add some width/height background is fine. Mar 23 '20 at 18:28
• Mar 23 '20 at 19:00

This is a code that extends the bounding box symmetrically to match a target width:height ratio. It does it in a way that respects additional margins that can come from the standalone class, but also works for non-standalone documents.

\documentclass[tikz,border=2mm]{standalone}
\makeatletter
\tikzset{fixed ratio/.code={\def\tikz@pft##1:##2;{\edef\pgfutil@tempx{##1}\edef\pgfutil@tempy{##2}}%
\expandafter\tikz@pft#1;%
\tikzset{execute at end picture={%
\ifcsname sa@border@right\endcsname
\pgfmathsetmacro\pgfutil@tempa{((\pgf@picmaxx+\sa@border@right-\pgf@picminx+\sa@border@left)/%
(\pgf@picmaxy+\sa@border@top-\pgf@picminy+\sa@border@bottom)}%
\else
\pgfmathsetmacro\pgfutil@tempa{((\pgf@picmaxx-\pgf@picminx)/(\pgf@picmaxy-\pgf@picminy)}%
\fi
\pgfmathsetmacro\pgfutil@tempb{(\pgfutil@tempx/\pgfutil@tempy)}%
\ifdim\pgfutil@tempa pt=\pgfutil@tempb pt\relax
\else
\ifdim\pgfutil@tempb pt>\pgfutil@tempa pt\relax
% target ratio greater than actual
\pgfmathsetmacro\pgfutil@tempc{-(\pgf@picmaxx-\pgf@picminx)%
+\pgfutil@tempb*(\pgf@picmaxy-\pgf@picminy)}%
\path ([xshift=-0.5*\pgfutil@tempc]current bounding box.west)
([xshift=0.5*\pgfutil@tempc]current bounding box.east);
\else
% target ratio smaller than actual
\pgfmathsetmacro\pgfutil@tempc{-(\pgf@picmaxy-\pgf@picminy)%
+(\pgf@picmaxx-\pgf@picminx)/\pgfutil@tempb}%
\path ([yshift=-0.5*\pgfutil@tempc]current bounding box.south)
([yshift=0.5*\pgfutil@tempc]current bounding box.north);
\fi
\fi
}%
}}
}
\makeatother

\begin{document}
\begin{tikzpicture}[fixed ratio=16:9]
\end{tikzpicture}
\begin{tikzpicture}[fixed ratio=9:16]
\end{tikzpicture}
\end{document}


• It's awesome but hard for me to understand this language! it solved my question gracefully. thanks Mar 23 '20 at 18:30
• @lucky1928 You're welcome. Yes, it has many @ in but to my knowledge this is the easiest way to find out what the standalone margins are, and whether they exist at all. Also, the dimensions of the tikzpicture are stored in \pgf@picmaxx and company. Using this information allows one to figure out how much horizontal or vertical space is to be added. Finally, using execute at end picture makes makes sure that these things will be computed when the tikzpicture is "done" (unless someone else injects another execute at end picture, of course).
– user194703
Mar 23 '20 at 19:48

If dimensions of final result are know, you can use tcolorbox addings for TikZ which can resize a TiKZ figure to adjust on desired path. This path can fix final dimenssions. Some examples:

\documentclass[tikz, border=2mm]{standalone}
\usepackage[skins]{tcolorbox}

\begin{document}

\begin{standalone}
\begin{tikzpicture}
\path[fill zoom picture={%
\draw (0,0) circle (5cm);}] (0,0) rectangle ++(16,9);
\end{tikzpicture}

\begin{tikzpicture}
\path[fill zoom picture={%
\draw (0,0) circle (5cm);}] (0,0) rectangle ++(10,10);
\end{tikzpicture}

\begin{tikzpicture}
\path[fill zoom picture={%
\draw (0,0) circle (5cm);}] (0,0) rectangle ++(20,25);
\end{tikzpicture}
\end{standalone}
\end{document}


• Are you sure that the dimensions of the full objects, including the symmetric margin of 2mm, have the desired ratio?
– user194703
Mar 23 '20 at 19:22

Another solution, do some math:

\documentclass[border=0mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\tiny\begin{tikzpicture}[]
\draw (0,0) circle (5cm);
% keep ratio
\def\ratio{16/9}
\path let \p1=(current bounding box.center),
\p2=(current bounding box.east),
\p3=(current bounding box.north),
\p4=(current bounding box.west),
\p5=(current bounding box.south),
\n1={\y3-\y1},
\n2={\n1*\ratio},
\n3={\y5 - \y1},
\n4={\n3*\ratio}
in
[use as bounding box] (\n4,\y5) rectangle (\n2,\y3);
\end{tikzpicture}
\end{document}


BTW, do not add border since it will impact on ratio.