#!/bin/bash set -euo pipefail function show_usage { cat <<-END usage: $0 [OPTIONS...] input_file output_file Converts a PDF file to a series of JPEG images using convert to reduce the quality and then merges back the result in a single pdf options: -q, --quality Set the JPEG quality (default: 75) -v, --verbose Enable verbose output -h, --help Display this help message END exit 1 } quality=75 verbose=false while [[ $# -gt 0 ]] do key="$1" case $key in -q|--quality) quality="$2" shift # past argument shift # past value ;; -v|--verbose) verbose=true shift # past argument ;; -h|--help) show_usage ;; -*) echo "Unknown option: $key" show_usage ;; *) break ;; esac done if [ -z "$1" ] || [ -z "$2" ]; then show_usage fi input_file="$1" output_file="$2" temp_pages_dir="$(mktemp -d)" function logf { if [ "$verbose" = true ]; then printf "$@" fi } logf "Converting \"$input_file\" to \"$output_file\"\n" page_count=$(pdfinfo "$input_file" | grep Pages | awk '{print $2}') logf "Processing $page_count pages\n" start=$(date +%s.%N) for i in $(seq 0 $((page_count-1))); do iter_start=$(date +%s.%N) convert -density 300 -quality "$quality" "${input_file}[$i]" "$temp_pages_dir/$i.jpg" # Compute estimated remaining time end=$(date +%s.%N) elapsed=$(echo "$end - $start" | bc) iter_elapsed=$(echo "$end - $iter_start" | bc) remaining=$(echo "($elapsed / ($i + 1)) * ($page_count - $i)" | bc) remaining_fmt=$(printf "%02d:%02d:%02d" $((remaining/3600)) $((remaining/60)) $((remaining%60))) logf "Compressed page $((i+1)) in $(printf '%.2f' "$iter_elapsed")s (estimated remaining time $remaining_fmt)\n" done logf "Merging compressed pages to a single PDF\n" convert "$temp_pages_dir"/*.jpg "$output_file" rm -r "$temp_pages_dir" logf "Done\n"