[Tex/LaTex] Can pdflatex (or any tex package) automatically rescale included images which have been reduced in size

graphicspdftexresolution

I'm writing my thesis in LaTeX, generating it with pdflatex. I have a large number of figures, many of which are bitmaps (as opposed to SVG) in PNG/JPEG format. I've generally created them to be fairly high resolution (say 1600×1200-ish) to ensure that whatever size they end up in the document, they'll be at least 300dpi when printed.

As I'm writing/laying out the document, I'm including graphics (using \includegraphics from the graphicx package) and setting widths/heights as appropriate (e.g. subfigures are quite small). I don't need the images to be any more than about 300 dpi at best, so where I have shrunk a 1600×1200 image down to say 5cm, the image is now at 800 dpi. So despite including some very small (on the page) images, the PDF is becoming quite large.

Is there a way to tell pdflatex or graphicx (or something else involved?) to convert all images to a maximum of 300 dpi, based on the dimensions I'm setting with say \includegraphics[width=2in]{filename}? i.e. so it scales the image to a max of 600×600 pixels as it includes it in the PDF (leaving the original file untouched).

I know I can resize the original images with various command line applications, and include the pre-resized versions, but given the images vary in size considerably, it wouldn't be as simple as making sure they're all 300dpi for a constant printed size. It'd also be nice to be able to easily create different versions of PDFs (web vs final print) without resizing images manually, so that the 'web' PDF capped images at say 72-100 dpi while the final print one could cap at 600 (if at all).

Update: I've found a poor solution to the problem in some cases (quite long so I've added it as an answer myself, see below). By reprocessing the PDF after creation, you can convert all images to JPEGs at a specific resolution (in dpi). This is good for docs with only JPEGs, but sucks if you have PNG (or similar non-lossy-compression) diagrams which are PNG for a reason (e.g. simple diagrams with hard edges).

So I'm still after a solution that can do this without forcing the same compression algorithm on all images (whether it's a LaTeX macro/package, or a script that parses the LaTeX and produces appropriately sized files, or a post-processor that doesn't take a one-compression-algorithm-fits-all approach).

Best Answer

I've tried a little black magic with LaTeX, and found out how to do it without external scripts ─ though it still is somewhat dirty and not that easy to use. Basically, you would need to call ImageMagick from inside LaTeX.

To do this, you need to call it with --shell-escape parameter. This allows for using a command named \write18, that executes a parameter passed to it. Then you could add the following code to the preamble:

\newcommand{\doConvert}[2]{\immediate\write18{convert #1 -resample %
  300x300 -resize #2 #1.rs}}
\newcommand{\imgRs}[4]{\doConvert{#1.#2}{#3x#4}%
  \includegraphics[width=#3, height=#4, type=#2, ext=.#2.rs, read=.#2.rs]{#1}%
}

This enables you to call \imgRs{file}{extension}{width_in_pts}{height_in_pts} in order to convert the image to 300 dpi and include it in the document.

Of course you could always specify the dimensions in inches or any other units: you would just have to change the call to \doConvert in imgRs to account for scaling from unit used to points -- and you would have to use the dimensions consistently. It could be possible to actually find out what were the units used, or make some parameters optional, but it's independent of this solution.