Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pdfcompress

Portable, self-contained PDF compressor. A single executable with Ghostscript (statically linked) embedded inside: copy it to any Linux server or Apple Silicon Mac and it works — no installation and no extra files required.


Quick start

./pdfcompress input.pdf

Produces input-compressed.pdf in the same folder, using the ebook profile.

Syntax

./pdfcompress input.pdf [output.pdf] [profile]
Argument Required Description
input.pdf Yes Source PDF to compress.
output.pdf No Output path. Defaults to <input>-compressed.pdf.
profile No Compression level. Defaults to ebook.

Profiles (quality → size)

Profile Resolution Recommended use
screen 72 dpi Smallest size (screen, web, email).
ebook 150 dpi Default. Good balance.
printer 300 dpi Quality printing.
prepress 300 dpi Highest quality (prepress).

Examples

# Default compression (ebook)
./pdfcompress raw.pdf

# Specifying the output file
./pdfcompress raw.pdf result.pdf

# Maximum compression for email
./pdfcompress raw.pdf light.pdf screen

# High quality for printing
./pdfcompress report.pdf report-print.pdf printer

Sample file (dummy.pdf)

The repository ships dummy.pdf so you can check any build straight away without looking for a PDF first: 5 pages of text with two embedded TrueType fonts, 881 KB (that weight is mostly the fonts — there are no images).

./pdfcompress dummy.pdf
Compressing PDF...
Input:       dummy.pdf
Profile:     ebook
Ghostscript: embedded (10.04.0)
PDF compressed successfully.
Original:   881107 bytes
Compressed: 74083 bytes
Reduction:  91.59%
Output:     ./dummy-compressed.pdf

Reference results (Ghostscript 10.04.0):

Profile Original Compressed Reduction
ebook 881,107 B 74,083 B 91.59 %
screen 881,107 B 74,119 B 91.59 %

The darwin-arm64 build reproduces both figures. The output is not byte-identical between runs, though: Ghostscript stamps CreationDate, ModDate and a document ID into the PDF, so two runs over the same input differ in a few dozen bytes and the total size can drift by a couple of bytes.

screen does not beat ebook here because the sample has no images to downsample: the gain comes from re-encoding the embedded fonts and streams, so both profiles converge. Use a scanned/image-heavy PDF to see the profiles apart.

dummy.pdf is the only PDF tracked in the repository; every generated output (*-compressed.pdf and any other local .pdf) is git-ignored.

Getting the binary

Each release ships one executable per platform on the Releases page. Pick the one matching your machine — that single file is all you need:

Asset For
pdfcompress-linux-x86_64 Intel/AMD Linux servers (uname -s -mLinux x86_64)
pdfcompress-linux-arm64 ARM64 Linux: Graviton, Ampere, linux/arm64 containers on Apple Silicon (uname -s -mLinux aarch64)
pdfcompress-darwin-arm64 Apple Silicon Macs, M1 onwards (uname -s -mDarwin arm64)

The assets are split by OS and CPU architecture, not by distribution. The Linux builds are statically linked, so the host's libc is irrelevant: the same pdfcompress-linux-* runs on glibc distributions (Debian, Ubuntu, RHEL) and on musl ones (Alpine) alike. Alpine only needs bash installed, which the launcher's shebang requires and busybox does not provide. CI verifies this on every build by running the freshly built Linux binary inside an alpine:3 container.

# Download (adjust the URL to the release and platform you want)
curl -sL -o pdfcompress <release-asset-url>
chmod +x pdfcompress
./pdfcompress document.pdf

Running the wrong asset is not silent — the launcher checks both the OS and the architecture on startup and tells you which one to download instead. Checking the architecture alone would not be enough: an Apple Silicon Mac reports arm64 just like an ARM Linux server, but it cannot run the Linux binary.

To make it available from any path:

sudo mv pdfcompress /usr/local/bin/
pdfcompress document.pdf

Building from source

The binary is not committed to the repository; it is built by build.sh and published to Releases. To build it yourself:

./build.sh              # embeds Ghostscript 10.04.0 by default
./build.sh 10.04.0      # or pin a specific version

Requirements:

  • Linux: gcc, make, curl and a static glibc — sudo apt-get install build-essential libc6-dev on Debian/Ubuntu.
  • macOS: the Xcode Command Line Tools (xcode-select --install). Nothing from Homebrew: build.sh deliberately builds with an empty PKG_CONFIG_PATH and fails if the result links against anything outside /usr/lib and /System/Library, which would make the binary non-portable.

Ghostscript is compiled natively, so build.sh always produces a binary for the machine it runs on (it refuses to run on an unsupported platform). To get the macOS executable, build on a Mac — which is exactly what the release workflow does, one runner per platform.

See TECHNOLOGY.md for the full details of how the binary is built and why.

How it works

pdfcompress is a shell script with a gzip-compressed Ghostscript binary appended at the end. On first run it extracts that binary to a temporary cache and reuses it on subsequent runs:

/tmp/.pdfcompress-<hash>/gs

The cache is keyed by the binary's hash, so extraction only happens once. You can delete that directory safely; it will be regenerated automatically.

Exit codes

Code Meaning
0 PDF compressed successfully.
1 Usage or runtime error (arguments, file, etc.).
2 The result was not smaller than the original.

Requirements

  • Linux on x86_64 or arm64, or macOS on Apple Silicon, matching the asset you downloaded. Any Linux distribution: the build is static, so glibc and musl systems are equally fine.
  • Standard utilities: bash, gzip/gunzip, awk, tail, wc — present by default on any Linux distribution and on macOS alike. On minimal container images such as Alpine, bash is the one that is usually missing (apk add bash); busybox ash does not satisfy the launcher's shebang.

On an Apple Silicon Mac (M1/M2/M3…)

Download pdfcompress-darwin-arm64 and run it directly; it needs no Docker, no VM and no Ghostscript installed:

chmod +x pdfcompress-darwin-arm64
./pdfcompress-darwin-arm64 document.pdf

macOS runs Mach-O binaries, so a linux-* asset will not work there whatever the architecture says — the launcher stops with a message pointing at the right one.

If macOS has flagged the download as quarantined and Gatekeeper complains, clear the flag once:

xattr -d com.apple.quarantine pdfcompress-darwin-arm64

In a container

Both linux-* assets run unmodified inside containers, including musl-based ones. On Alpine the only prerequisite is bash:

RUN apk add --no-cache bash
COPY pdfcompress-linux-arm64 /usr/local/bin/pdfcompress
RUN chmod +x /usr/local/bin/pdfcompress

Pick the asset by the container's architecture, not the host's: a linux/arm64 image on an Apple Silicon Mac needs pdfcompress-linux-arm64, even though the same machine would need pdfcompress-darwin-arm64 outside Docker.

Other platforms

Intel Macs and 32-bit targets are not published, but the build supports any platform it can compile on natively: add the target to the matrix in .github/workflows/release.yml with a runner of that platform, or run ./build.sh on the machine itself.

License

pdfcompress embeds Ghostscript and is distributed under the AGPL-3.0 license. See LICENSE and NOTICE.md for details and practical implications.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages