You can try Ghostscript (see here and, for optimizations, this German article) – or, for even more compression, pdfsizeopt (see here). The latter takes a lot longer, but gets better results on scanned text pages.
Ghostscript
Should be provided by your package management. On Debian/Ubuntu/Mint etc, you can install it using sudo apt install ghostscript
. You then can use a shell script wrapper like the one I compiled going by the above sources:
#!/bin/bash
# Compress/Optimize PDF files
# see: https://askubuntu.com/a/256449/68291
# and: https://www.linux-community.de/ausgaben/linuxuser/2019/04/optimal-kombiniert/
[[ -z "$1" ]] && {
echo
echo "Compress/Optimize PDF files"
echo "Syntax:"
echo " ${0} <InFile> [OutFile] [level]"
echo ""
echo "Levels:"
echo "- screen: 72dpi (low res)"
echo "- ebook: 150dpi (OK; default if not specified otherwise)"
echo "- prepress: 300dpi (Acrobat Distiller 'Prepress Optimized')"
echo "- printer: 300dpi (Acrobat Distiller 'Print Optimized')"
echo "- default: ???dpi (auto-select, usually results in bigger file)"
exit 1
}
[[ ! -f "$1" ]] && {
echo
echo "Input File '${1}' not found, nothing to do."
exit 5
}
outfile="$2"
[[ -z "$2" ]] && outfile=${1%\.pdf}_comp.pdf
[[ -f "$outfile" ]] && {
echo
echo "The specified output file '$outfile' does already exist, aborting."
exit 3
}
case "$3" in
screen) level="-dPDFSETTINGS=/screen" ;; # 72dpi
prepress) level="-dPDFSETTINGS=/prepress" ;; # 300dpi
printer) level="-dPDFSETTINGS=/printer" ;; # 300dpi
default) level="-dPDFSETTINGS=/default" ;; # auto-estimate
*) level="-dPDFSETTINGS=/ebook -dColorImageResolution=150 -dGrayImageResolution=150 -dMonoImageResolution=150 -dMonoImageDownsampleType=/Subsample" ;; # 150dpi
esac;
gs -sDEVICE=pdfwrite \
-dColorImageDownsampleType=/Bicubic \
-dGrayImageDownsampleType=/Bicubic \
-dMonoImageDownsampleType=/Bicubic \
-dCompatibilityLevel=1.4 $level -dNOPAUSE -dQUIET -dBATCH -sOutputFile=$outfile $1
Called without parameters it tells you its syntax. With just the input PDF as parameter, it compresses images to 150dpi (ebook), writing output to a file having _comp
(aka "compressed") appended to its basename.
PdfSizeOpt
This requires quite some binaries downloaded from different places (mostly Github). To make it easier, here's a script performing the "installation" steps – just run it in an empty directory:
wget https://github.com/pts/tif22pnm/releases/download/2014-01-09/png22pnm.xstatic
wget https://github.com/pts/sam2p/releases/download/v0.49.4/sam2p.xstatic
wget http://www.jonof.id.au/files/kenutils/pngout-20200115-linux.tar.gz
wget https://github.com/pts/pdfsizeopt-jbig2/releases/download/2017-01-24/jbig2.xstatic
wget https://raw.githubusercontent.com/pts/pdfsizeopt/master/pdfsizeopt.single
mv png22pnm.xstatic png22pnm
mv sam2p.xstatic sam2p
mv jbig2.xstatic jbig2
tar xf pngout-20200115-linux.tar.gz --strip-components=2 pngout-20200115-linux/amd64/pngout
chmod u+x pdfsizeopt.single png22pnm sam2p
Then you can use the following wrapper script to compress your PDF files (works very good on scanned text pages; not sure if it's really suited for graphical stuff):
#!/bin/bash
# see: https://askubuntu.com/a/1011292
# takes quite long but gets good results on scanned text pages, even leaving OCR intact
[[ -z "$1" ]] && {
echo
echo "Compress PDF consisting of scanned text pages."
echo
echo "Usage: $0 <infile>"
echo
echo "Run 'pdfsizeopt.single --help' for more details."
echo
exit
}
./pdfsizeopt.single --v=30 --do-fast-bilevel-images=yes $1 ${1%\.pdf}_opt.pdf
(if you want to call it from anywhere, adjust the path of ./pdfsizeopt.single
to point to where the tools have been placed, and make an alias to the script)
I decided to include the --do-fast-bilevel-images=yes
parameter as it speeds up processing a lot (on a test PDF: about 2min without the parameter, less than a second with the parameter), plus --v=30
to reduce output to a usable level. There are many more parameters you can play with to optimize results to your liking.