pdf-invert
Convert a PDF into a dark-mode version by inverting its colours — without rasterizing. Text stays selectable and searchable, vector graphics stay vector, and the file stays roughly the same size.
$ uvx pdf-invert paper.pdf
Wrote paper-dark.pdf
Usage
pdf-invert INPUT [-o OUTPUT] [--invert-images] [--linearize] [-q]
INPUT— the source PDF.-o, --output— destination (default:<name>-dark.pdfbeside the input).--invert-images— also invert raster images. Off by default so photos, figures, and logos don't become negatives.--linearize— linearize output for faster web viewing.-q, --quiet— suppress warnings.
How it works
For every colour-setting operator in every content stream (page bodies, form
XObjects, tiling patterns, Type3 glyphs, annotation appearances), each channel
value v is replaced with 1 - v, and a black backdrop is placed behind the
page. Because only colours change, the text and vector geometry are untouched.
A few deliberate choices make this robust on real documents — establishing white
as the default colour (so text drawn without an explicit colour doesn't vanish
on the black backdrop), tracking the current colourspace so sc/scn are only
inverted when that's meaningful, visiting shared objects once, and never
entering soft masks. See KNOWN_LIMITATIONS.md for what's
out of scope.
Why not Ghostscript / rasterizing?
Ghostscript's setcolortransfer inverts at the render pipeline and is excellent,
but it needs a system binary and inverts everything, including images. A
rasterize-and-invert approach loses selectable text and bloats file size (often
20×). pdf-invert is pure Python (pikepdf), installs anywhere uv/pip
reaches, keeps text, and lets you preserve images.
Development
uv run pdf-invert some.pdf # run from source
Metadata
Release files for pdf-invert 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pdf_invert-0.1.0.tar.gz | 9.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pdf_invert-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.1 kB
Release files / pdf_invert-0.1.0.tar.gz
| Download URL | pdf_invert-0.1.0.tar.gz |
|---|---|
| Size | 9.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
30383c4add8518118c6df6bb2721b1010a9192acbac5216080b962c0f64fd02d
|
|
BLAKE2b-256 checksum How to use checksums |
259d47698379e4b1ab86dd270f66bba4a140926e65c640d697479a4557f3e2bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / pdf_invert-0.1.0-py3-none-any.whl
| Download URL | pdf_invert-0.1.0-py3-none-any.whl |
|---|---|
| Size | 10.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6f0cc0073d76ef8aa308092491112e57c88fe67d17c4b9562d71e7d726588f63
|
|
BLAKE2b-256 checksum How to use checksums |
50da3a1a2af2de61e0156e48bfe3cd476c7869318459ae910237fc5688eba83b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|