27

We have a printer at our office that prints PDF files from a USB stick. It prints most files okay, but it has problems with some, especially ones generated with Latex. Some PDFs it simply refuses to print, some PDFs it prints with courier-type font, and some it prints fine except for equations.

I'm looking for a way to "distill" PDFs into a dead-sure format to print. Either by simplifying / normalizing the PDF to the point that any renderer will render it correctly, or by simply making each page a 600dpi raster image in the PDF. (I could split the PDF into individual raster images and combine them manually, but I want something scriptable.)

The output file size doesn't matter, as long as it's sure to print, has A4 paper size (or the original) and 300~600dpi resolution.

3

6 Answers 6

35

After unsuccessfully trying some options to render the fonts as outlines (including this question and pstoedit), I figured out a way to easily convert the PDF into rasterized form using ImageMagick:

convert -density 600 +antialias input.pdf output.pdf

This creates a PDF rendered at 600 dpi, with antialias turned off (unnecessary at that resolution).

The output files are huge (~30 MB for an 8-page document) and extremely slow to print, but should work as long as the printer has enough memory to render the content.

5
  • 1
    Yes! I used this to flatten the layers in my PDF to great success. +antialias wasn't necessary because we only had images (it made no difference) and I dropped the resolution to 150 as that seemed good enough for archiving without taking up so much space. Thanks!
    – mlissner
    Oct 15, 2014 at 18:57
  • 3
    Note that convert does not preserve the contents of forms you might have filled out. (I wanted to rasterize a PDF in order to make sure that the form contents look the same everywhere, in particular that they will be displayed by every PDF viewer in the first place.) In order to preserve the form contents, use evince (or whatever application you used to fill out the form) to print the document "to a file" – this is another PDF where the form contents have actually become part of the regular text. Then you still might rasterize this new PDF, depending on your needs.
    – balu
    Apr 13, 2017 at 9:42
  • Note that this turns antialiasing on (+antialias) rather than turning it off (-antialias).
    – xiii1408
    Jun 19, 2018 at 22:59
  • 1
    No, +antialias disables antialiasing: imagemagick.org/script/command-line-options.php?#antialias
    – Sampo
    Jun 20, 2018 at 15:21
  • 1
    I needed to tweak imagemagick (stackoverflow.com/questions/42928765/…) in order to make this work.
    – SteveSong
    Jan 18, 2019 at 16:25
9

This is an improvement on the Accepted answer: it also lets gs optimize the file so that it's not so huge, and fixes an occasional compatibility problem:

convert -render -density 300 input.pdf tmp.pdf
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dNOPAUSE -dQUIET -dBATCH -sOutputFile=input-scanned.pdf tmp.pdf

I use this very frequently: any time I annotated a PDF or sign an autograph on one, etc, and want to fix those edits or make them ultra-portable. Thus, as a bash script (ie put this in your ~/.aliases and open a new terminal window):

(The script calls evince at the end. That's a PDF viewer. You can replace that with your favourite PDF viewer).

rasterizePDF() {
echo "Usage: rasterizePDF fromfile.pdf : this makes a 300dpi raster version. And optimizes it with ghostscript. Output is fromfile.pdf-scanned.pdf"
tmpfile=$(mktemp).pdf
echo "Creating raster version... (in $tmpfile)"
convert -render -density 300 $1 $tmpfile
echo "Optimizing to shrink pdf file..."
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dNOPAUSE -dQUIET -dBATCH -sOutputFile=$1-scanned.pdf $tmpfile
evince $1-scanned.pdf&
echo "Finished; launched viewer."
}
2
  • 1
    Wow, this optimization part with gs is huge, thanks! I went from 248MB to 13MB for 80-page slides (the original is 7.5MB). May 18, 2021 at 8:53
  • 1
    FWIW, this worked for printing a PDF that contained a bunch of high-resolution JPG images on a Kyocera FS-C5100DN. And the resulting PDF was just a few MiBs big (instead of 300 or so after the convert step). However, the printer still needed 15 minutes for starting to print the PDF (11 pages). Still an improvement over the original 29 MiB PDF where the printing didn't even start after half an hour of the printer displaying 'Processing'. With Sampo's answer the printing started a bit faster (perhaps after 5 minutes or so). Apr 15, 2023 at 10:37
3

I think my current preferred way to do it is:

  1. Use pdftoppm to convert the PDF file into a series of images.

    $ pdftoppm source.pdf output -png

  2. Use img2pdf to create a pdf file out of those images.

    $ img2pdf *.png -o output.pdf

The good news is you can create a bash script to automate the whole process for you.

Here is a bash script that will distill all pdf files within a directory and preserve the originals in a new directory "originals".

#!/bin/bash

mkdir "originals";
for filename in ./*.pdf; do
    pdftoppm "$filename" output -png
    mv "$filename" ./originals
    img2pdf *.png "-o" "$filename"
    rm *.png
done

Credits: img2pdf answer & pdftoppm answer & bash script help: 1 & 2

(Side note) You can install img2pdf using:

$ sudo apt install img2pdf

1
  • I've found that pdftoppm doesn't work with the pdf files on archive.org.
    – user193478
    May 26, 2021 at 23:47
2

Using imagemagick is, in my experience, not stable with high resolutions and/or big files. Many printers can do 1200 dpi and up, so the rasterized file should have similar resolution. A better solution is to use pdf2djvu which is faster, more robust, and even creates files with a size that often rivals the original PDF at 1200 or 2400 dpi. These files can be viewed and printed using okular or evince.

Example:

pdf2djvu -d 2400 file.pdf > rastered.djvu
1
  • With djvu there is the risk of the JB2 compression being to aggressive, i.e. characters or digits being wrongly substituted which could start a nightmare when printing financial or construction documents, similar to what was observed with some Xerox devices. Apr 15, 2023 at 10:30
0

Solution

The following code rasterizes a.pdfc.pdf at 1200 DPI, by initially rasterize at 2400 DPI then downscale by 2 before output. Documentation.

gs -dNOPAUSE -dBATCH -sDEVICE=pdfimage24 -r2400 -dDownScaleFactor=2 -o c.pdf a.pdf

If you only need to print black and white, you can replace pdfimage24 with pdfimage8 in order to speed up.

Benchmark

As can be seen, the solution above is the fastest, only lose to pdf2ps + ps2pdf (but pdf2ps + ps2pdf is not guaranteed to rasterize the file), and to pdf2ppm (but convert to .jpg enlarge the file)

Solution Time taken (s) Memory taken (KiB) Output file size (KiB) Printing time (s)
pdftoppm (1200) (.jpg) + img2pdf (†) 2.710 603092 10341.3
pdf2ps + ps2pdf with temporary file (source) (*) 4.110 37596 1706.4
pdfimage8 (1200) 4.180 35668 2348.6 9.5
pdfimage24 (1200/2) 5.020 36088 1971.9 9.7
pdfimage24 (1200) 6.520 36212 3316.1
pdf2ps + ps2pdf with pipe (*) 7.230 37668 1706.4
convert (600) 9.560 964532 5953.6
pdftoppm (1200) (.tiff) + img2pdf (†) 10.850 1539512 14483.3
convert (600) + gs to optimize (source) 12.010 964532 1989.4 9.9
pdfimage8 (2400/2) 20.350 43872 3481.9
pdfimage24 (2400/2) 23.510 46484 4833.2 15.8
pdftoppm (1200) (.png) + img2pdf (source) (†) 33.000 626896 14127.2

(*): Solution doesn't actually always rasterize PDF, but gs may decide to do that in some (it's unknown in which case it will, probably the cases where the PDF is too complicated) cases.

(†): the code as written will only work for 1-page PDF file, but it can be adapted.

Details of benchmarked solutions

pdftoppm (1200) (.jpg) + img2pdf (†)

pdftoppm -progress -r 1200 -jpeg a.pdf a
img2pdf a-1.jpg -o c.pdf

pdf2ps + ps2pdf with temporary file (source) (*)

gs -sDEVICE=ps2write -dNOCACHE -sOutputFile=c.ps -q -dBATCH -dNOPAUSE a.pdf
ps2pdf c.ps c.pdf

pdfimage8 (1200)

gs -dNOPAUSE -dBATCH -sDEVICE=pdfimage8 -r1200 -o c.pdf a.pdf

pdfimage24 (1200/2)

gs -dNOPAUSE -dBATCH -sDEVICE=pdfimage24 -r1200 -dDownScaleFactor=2 -o c.pdf a.pdf

pdfimage24 (1200)

gs -dNOPAUSE -dBATCH -sDEVICE=pdfimage24 -r1200 -o c.pdf a.pdf

pdf2ps + ps2pdf with pipe (*)

gs -sDEVICE=ps2write -dNOCACHE -sOutputFile=- -q -dBATCH -dNOPAUSE a.pdf -c quit | ps2pdf - c.pdf

convert (600)

convert -density 600 a.pdf c.pdf

pdftoppm (1200) (.tiff) + img2pdf (†)

pdftoppm -progress -r 1200 -tiff a.pdf a
img2pdf a-1.tif -o c.pdf

convert (600) + gs to optimize (source)

convert -density 600 a.pdf b.pdf
gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite  -sOutputFile=c.pdf b.pdf   -q

pdfimage8 (2400/2)

gs -dNOPAUSE -dBATCH -sDEVICE=pdfimage8 -r2400 -dDownScaleFactor=2 -o c.pdf a.pdf

pdfimage24 (2400/2)

gs -dNOPAUSE -dBATCH -sDEVICE=pdfimage24 -r2400 -dDownScaleFactor=2 -o c.pdf a.pdf

pdftoppm (1200) (.png) + img2pdf (source) (†)

pdftoppm -progress -r 1200 -png a.pdf a
img2pdf a-1.png -o c.pdf

Source code of the benchmark can be found here.

1
-2

Another alternative is to convert to images via something like

pdfimages

From man page, "Pdfimages saves images from a Portable Document Format (PDF) file as Portable Pixmap (PPM), Portable Bitmap (PBM), or JPEG files. Pdfimages reads the PDF file PDF-file, scans one or more pages, and writes one PPM, PBM, or JPEG file for each image, image-root-nnn.xxx, where nnn is the image number and xxx is the image type (.ppm, .pbm, .jpg)."

Then use pdftk to convert back to PDF https://www.pdflabs.com/docs/pdftk-cli-examples/

Finally, print this file. Obviously, the key question is how to script this.

You could automate this via an simple webpage of some sort for users. Finally, they print out the converted file and you should have a higher performance and working printout?

1
  • 6
    pdfimages extracts embedded raster images from PDF files, is does not rasterize the text or vector graphics.
    – Sampo
    Feb 25, 2015 at 21:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .