PDFGraph is a Rust command-line tool for offline PDF compression on Ubuntu.
Its executable and Debian package are named pdfgraph.
Handles text/vector PDFs, scanned PDFs, and PDFs containing photos. Uses QPDF
for lossless optimization and optionally Ghostscript for image downsampling.
No uploads, accounts, telemetry, API keys, or Rust crate dependencies.
Download pdfgraph_0.1.0_amd64.deb from this repository's GitHub Releases,
then run from your downloads directory:
sudo apt install ./pdfgraph_0.1.0_amd64.deb
pdfgraph --helpThe package depends on QPDF and recommends Ghostscript (installed by apt by default). To install just the lossless mode:
sudo apt install --no-install-recommends ./pdfgraph_0.1.0_amd64.debThe release workflow builds amd64/x86-64 packages on Ubuntu 22.04. For ARM64, build from source or build the package on an ARM64 Ubuntu machine. Older Ubuntu versions and other distributions are not tested by this project.
Installation may need the internet to fetch packages. Compression needs no
internet after installation. For an air-gapped computer, transfer the .deb
along with QPDF, Ghostscript, and their dependencies for that Ubuntu version
and architecture. The Rust executable alone does not include these engines.
# Text PDFs and lossless image/structure optimization
pdfgraph report.pdf
# Scans and image-heavy PDFs: downsample color/grayscale images to 150 DPI
pdfgraph scan.pdf --mode balanced -o scan-smaller.pdf
# Stronger downsampling (72 DPI)
pdfgraph photos.pdf --mode small -o photos-small.pdf
# Choose image resolution; monochrome target is twice this value
pdfgraph scan.pdf --mode balanced --dpi 200 -o scan-200dpi.pdf
# Replace an existing output
pdfgraph report.pdf -o smaller.pdf --force
# Paths with spaces
pdfgraph "My Documents/book.pdf" -o "My Documents/book-small.pdf"
# Filenames beginning with a dash
pdfgraph -- -report.pdfBy default, report.pdf produces report.compressed.pdf alongside the input.
The output directory must exist. The input is never overwritten; even
--force rejects the input itself, hard links to it, and output symlinks.
Outputs have private permissions (0600). Exit codes: 0 success, 1
processing failure, 2 invalid command arguments.
| Mode | Engines | Behavior |
|---|---|---|
lossless (default) |
QPDF | Compress PDF objects and streams; no image downsampling or lossy image encoding |
balanced |
QPDF + Ghostscript | Also try 150 DPI color/grayscale and 300 DPI monochrome images |
small |
QPDF + Ghostscript | Also try 72 DPI color/grayscale and 144 DPI monochrome images |
--dpi accepts 36 through 1200, in image modes only. These are downsampling
targets: lower-resolution images are not enlarged, and engine thresholds can
leave near-target images unchanged. Image modes retain text/vector content
where supported by Ghostscript; they do not intentionally rasterize whole pages.
Each candidate is checked with QPDF and must have the same page count. The smallest candidate wins; if none is smaller, the original bytes are copied to the output. The command reports which method won and the bytes/percentage saved. Already-optimized PDFs may have no savings. A specific final size is not guaranteed.
Install Rust 1.74+ / Cargo using your preferred toolchain installer, plus:
sudo apt update
sudo apt install build-essential qpdf ghostscript
git clone https://github.com/catalystcode-dev/PDFGraph.git
cd PDFGraph
cargo build --release --locked --offline
sudo install -m 755 target/release/pdfgraph /usr/local/bin/pdfgraph
pdfgraph report.pdfRust builds require no crate downloads because this project uses only the standard library. The Rust toolchain, linker, and compression engines must already be installed for a fully offline build. Cargo builds for your current operating system: a build on macOS is a macOS executable, not an Ubuntu executable.
On Ubuntu with Rust installed:
sudo apt install build-essential dpkg-dev python3 qpdf ghostscript
bash scripts/build-deb.sh
sudo apt install ./dist/pdfgraph_0.1.0_amd64.debThe script builds natively, calculates shared-library dependencies, and writes
the package to dist/. QPDF and Ghostscript are system dependencies,
not bundled copies.
sudo apt install qpdf ghostscript poppler-utils python3
cargo fmt --check
cargo clippy --all-targets --locked --offline -- -D warnings
cargo test --locked --offline
cargo build --locked --offline
python3 tests/smoke.pyThe integration suite generates text and image PDFs, runs all three modes,
checks file sizes, input preservation, page counts, extracted text and pixel
equality for lossless rendering. It also exercises malformed/encrypted inputs,
existing outputs, aliases, missing engines and unusual paths. Fixtures/renders
are kept under ignored tmp/smoke/ for inspection.
- Rewriting a PDF invalidates its digital signatures. Keep signed originals.
- Ghostscript rewrites the document and can alter or discard forms, annotations,
links, tags, attachments or other interactive content. Use
losslesswhen those features matter. PDF/A and PDF/UA conformance are not guaranteed. - Encrypted PDFs are rejected, including those that open without a password.
- Structural checks and page counts cannot guarantee visual or semantic equivalence. Review important documents after image compression.
- QPDF warnings are printed; successful repairs may be accepted. Engine errors fail the command without replacing the destination. Requested image modes require Ghostscript; missing engines do not silently change the requested mode.
- Work uses a private temporary directory beside the output and may need disk
space for several copies. Normal success/errors clean it up. Forced termination
or a crash can leave a
.pdfgraph-*directory; remove it after confirming no compression process is using it. - Publication is atomic on ordinary Ubuntu filesystems. Without
--force, the filesystem must support hard links. Only one PDF is processed per command. - QPDF and Ghostscript are run directly, without a shell. Keep these system packages updated when processing PDFs from untrusted sources.
Engine option references: QPDF command-line documentation and Ghostscript PDF output documentation.
This Rust wrapper is MIT licensed; see LICENSE. QPDF and Ghostscript are separately installed software with their own licenses.