Skip to content

Instantly share code, notes, and snippets.

@ernstki
Last active June 14, 2022 16:42
Show Gist options
  • Save ernstki/d94052852e1ee0826d05c1a63de2e4a8 to your computer and use it in GitHub Desktop.
Save ernstki/d94052852e1ee0826d05c1a63de2e4a8 to your computer and use it in GitHub Desktop.
Reduce file size of PDF documents with embedded images
#!/bin/bash
##
## Reduce a PDFs byte size by using either grayscale images and/or
## the '/ebook' output target of 'gs' (Ghostscript)
##
## Requires: Ghostscript probably 7.something or higher
##
## Author: Kevin Ernst
## Date: ages ago
##
set -u
ME=$(basename $BASH_SOURCE)
GIST='https://gist.github.com/ernstki/d94052852e1ee0826d05c1a63de2e4a8'
# don't print ANSI color codes unless stdout is a terminal
if [[ -t 1 ]]; then
BOLD=$(tput bold)
UL=$(tput sgr 0 1)
BLUE=$(tput setaf 4)
YELLOW=$(tput setaf 3)
RESET=$(tput sgr0)
else
BOLD=;UL=;BLUE=;YELLOW=;RESET=
fi
WARNING="$BOLD${YELLOW}WARNING$RESET:"
suf='_crunched'
serial=
grayscale=
# '-h' or '--help'
if [[ $1 =~ ^--?h ]]; then
echo "
$BOLD$BLUE$ME$RESET - reduce file size of PDFs with embedded images
${UL}usage$RESET: $ME [-h|--help] [-g|--grayscale] FILE [FILE ...]
${UL}where$RESET: -h / --help you're looking at it
-g / --grayscale make PDFs a tiny bit smaller by converting to B&W
('--greyscale' also accepted)
${UL}source$RESET: $GIST
"
exit
fi
# '-g', '--grayscale', or '--greyscale'
if [[ $1 =~ ^--?g ]]; then
# Source http://stackoverflow.com/a/20133915
grayscale="-sProcessColorModel=DeviceGray \
-sColorConversionStrategy=Gray \
-dOverrideICC"
shift
fi
while (( $# )); do
infile=$1
outfile="${infile%.pdf}${suf}.pdf"
if [[ ! -f $1 ]]; then
echo "$WARNING Input file '$1' not found. Skipping." >&2
shift; continue
fi
# increment the serial each time so we're not clobbering existing files
# not because I really care, but just because I wondered how to do it
while [[ -f $outfile ]]; do
serial=$(printf "%03d" $(( $serial + 1 )))
outfile="${infile%.pdf}${suf}-${serial}.pdf"
done
gs -q -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -dPDFSETTINGS=/ebook \
$grayscale \
-o "$outfile" \
"$infile"
# -c "/osetcolor {/setcolor} bind def /setcolor {pop [0 0 0] osetcolor} def" \
# -sOutputFile="$outfile" "$infile"
# (didn't seem to work for PDF; maybe try again someday)
# source: http://superuser.com/a/249038
if [[ $grayscale ]]; then
echo "Finished writing grayscale output to '$outfile'."
else
echo "Finished writing output to '$outfile'."
fi
# work on the next file
shift
done
@ernstki
Copy link
Author

ernstki commented Jun 14, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment