# Pack images into PDF

I have many screenshots which were all taken under the same conditions: Same display resolution, same display scaling, PDF viewer at the same size, PDF zoom level the same, etc.

They are of different width and height. The widest ones have normal text width of DIN A4 paper (portrait).

I want them to be put into a PDF (paper size: DIN A4, portrait) but not one per page like

convert * output.pdf


would do but with as many as possible per page. Order matters (alphanumerical order of the file names; The files are named {1..n}.png.). The images shouldn't be stretched out in width to match the text width of the PDF but should instead all have a common (constant) zoom factor.

All the images are in the PNG format.

I prefer a command-line way to achieve this so doing it repeatedly – possibly in an automated way – is easy.

Some kind of separator between the screenshots would be nice, so it's easy to see where one ends and the next one begins.

• confused: if you take a bunch of screenshots under the same conditions, why are they different widths and heights? Also... why are you taking screenshots of a PDF viewer? I have a feeling there is a better way to do whatever you're doing. Aug 16, 2017 at 21:39
• @derobert I'm studying for an exam and have to learn using several scripts and papers, some of which I don't have the source code of. I don't want to write down everything important because that'd take a long time. A lemma or a formula often doesn't use the full text width (depending on the document style and the length of the formula, of course), but an important statement in normal text does. Some important parts are longer than others which makes them taller. I appreciate a better solution for the future but for now,I already have taken a lot of screenshots and would like to print them out. Aug 16, 2017 at 22:24
• There are ways to images into a PDF at a given position from the commandline (e.g. imagemagick or variants), but I'm not aware of any ready-made tool that calculates those positions for a given set of images (BTW, this is the bin-packing problem, which is NP-complete). You probably will have to write your own program for that, or do it manually. Aug 17, 2017 at 5:13
• @dirkt It's not a bin-packing problem. It's: "Does this next image still fit on this page? If so, put it in, if not, do a page break, then put it in." It even is a linear-time problem. Aug 17, 2017 at 12:23
• For "linear with page breaks" the simplest thing I can think of is latex. Not strictly command line, but I guess you can construct the latex file with a simple script. Aug 17, 2017 at 12:28

I waited for an answer until a few minutes before I had to have it done. Then I hacked something together which works using bash's list expansion:

\documentclass{report}
\usepackage{graphicx}
\usepackage[a4paper, total={6in, 10in}]{geometry}

\begin{document}
\includegraphics[scale=.15]{../1}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../2}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../3}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../4}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../5}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../6}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../7}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../8}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../9}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../10}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../11}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../12}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../13}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../14}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../15}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../16}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../17}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../18}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../19}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../20}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../21}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../22}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../23}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../24}\\
\rule{\textwidth}{1pt}
\includegraphics[scale=.15]{../25}\\
% [...]

\end{document}


It's super ugly as it doesn't use a loop because I don't know how to do loops in LaTeX, and one has to use bash's list expansion again or fill in the path names manually when the number of screenshots increases.

I'll accept any answer which gets the job done, too, and is ever-so-slightly less ugly.

• for loops in latex. Aug 17, 2017 at 16:51