# rpdf
**Repository Path**: graviton/rpdf
## Basic Information
- **Project Name**: rpdf
- **Description**: PDF to text, AI Agent tools, by Rust
- **Primary Language**: Unknown
- **License**: AGPL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-08-02
- **Last Updated**: 2026-11-03
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# rpdf
Extract text and images from PDF files, for feeding to coding assistants and
other programs.
Text comes out in reading order with page markers, so a quotation can be traced
back to its page. `--info` and `--toc` let a caller see what a document holds
before extracting anything, and `--pages` then limits the work to what matters
— useful when the alternative is dumping a 500-page book into a context window.
Pure Rust, no C dependencies.
```
cargo build --release
./target/release/rpdf book.pdf
```
Prebuilt Linux x86_64 binaries (glibc ≥ 2.28) are attached to each
[release](http://10.0.255.1:10001/yangmingyang/rpdf/-/releases).
## Usage
```
rpdf [OPTIONS]
-o, --output Write text here instead of stdout
-i, --images Also extract images into this directory
-p, --pages Only these pages: `2-50`, `1-5,8,12-`, `-20`
--no-text Skip text extraction (images only)
--no-page-markers Omit the `=== page N ===` marker before each page
--info Title, author, page count, dates
--toc Table of contents (bookmarks) with page numbers
--max-bytes Stop after roughly N bytes of text, and say so
--min-image-size Skip images smaller than this on either side
-s, --search Report only the pages and lines that match
-e, --regex Treat --search as a regular expression
--no-layout Do not reorder two-column pages
--password Password for an encrypted PDF
--json Emit one JSON document instead of plain text
-q, --quiet Suppress warnings on stderr
```
### Finding your way around a document
```console
$ rpdf book.pdf --info --toc --no-text
Pages: 496
Creator: LaTeX with hyperref package
Created: 2020-02-16 14:05:06
I 基础篇 .. 31
1 Haskell简介 .. 35
1.1 Haskell的由来 .. 35
$ rpdf book.pdf --pages 35-38
=== page 35 ===
第 1 章
Haskell 简介
...
```
### Searching
`--search` matches literally, so `f(x)` and `2.2` mean themselves. Add
`--regex` for patterns. Both are case-insensitive; a pattern can opt out with
the inline flag `(?-i)`.
Each page is searched as a whole, so a phrase that wraps onto the next line
is still found: in a literal phrase any run of whitespace matches line breaks
too, and a word hyphenated at the end of a line matches unbroken. A regular
expression sees the line breaks as `\n` (match them with `\s`); `^` and `$`
anchor at each line. A hit shows every line the match covers.
```console
$ rpdf tutorial.pdf --search "size(3cm)"
8: size(3cm);
12: size(3cm);
$ rpdf tutorial.pdf --search '^[0-9]+\.[0-9]+ Arrow' --regex
1: 2.2 Arrowheads . . . . . . . . . . . . . . . . . . 8
8: 2.2 Arrowheads
```
### Images
```console
$ rpdf paper.pdf --no-text --images ./out --pages 3-8 --min-image-size 64
extracted 12 image(s) to ./out
./out/img_418x0_4256x6176.png (page 3, object 418 0, re-encoded as PNG with alpha from soft mask)
```
JPEG streams are stored as-is. Everything else is re-encoded as PNG, including
JPEG 2000, JBIG2 and CCITT G3/G4, with soft masks (`/SMask`) composited into an
alpha channel. Data that cannot be decoded still reaches disk in a container
that opens — CCITT is wrapped in a TIFF — with the reason recorded in the note.
### JSON
`--json` emits one document: `file`, `pages`, and whichever of `info`, `toc`,
`text` (or `matches`) and `images` were requested.
```console
$ rpdf paper.pdf --pages 1 --toc --json | jq '.text[0].page'
1
```
## What it handles
- **Text**: content-stream walking with CTM/text-matrix tracking and the full
text state (character and word spacing, horizontal scaling, saved and
restored with the graphics state), ToUnicode CMaps, `/Encoding`
differences with glyph-name fallback for the codes an incomplete ToUnicode
leaves out, predefined CJK CMaps (GBK, Big5, Shift-JIS, EUC-KR) without a
ToUnicode, Type3 font matrices, real font widths for space detection,
recursion into Form XObjects. Overprinted (fake bold) text is read once.
- **Layout**: lines rebuilt from glyph positions, in the orientation `/Rotate`
shows the page; two-column pages reordered into reading order, with
`--no-layout` as the escape hatch.
- **Images**: Flate (with PNG/TIFF predictors), LZW, RunLength, ASCIIHex,
ASCII85, DCT, JPEG 2000, JBIG2, CCITT G3/G4, and chains of them;
DeviceGray/RGB/CMYK, CalRGB/CalGray, Lab, Indexed, ICCBased, Separation and
DeviceN (as gray); 1/2/4/8/16 bits per component; soft and stencil masks;
inline (BI/EI) images, including named colour spaces. Masks composited into
an image and page thumbnails are not written out separately.
- **Speed**: fonts and Form XObjects are parsed once per document, and pages
are extracted in parallel; `--max-bytes` stops the extraction, not just the
output.
- **Damaged files**: missing `/Root`, truncated cross-reference tables, and
encryption dictionaries written inline are repaired before parsing.
- **Encrypted files**: RC4 and AES; an empty password is tried first, so
documents that carry only an owner password open without `--password`.
## Known limits
- Colour is passed through as-is: CalRGB and ICCBased images are not converted,
which differs from a colour-managed renderer by up to a few levels per
channel.
- Two-column detection is heuristic. It errs towards leaving pages alone, and
`--no-layout` disables it.
- Mathematics comes out as a sequence of positioned glyphs, not as structure.
- A glyph can only be read as what the font says it is. A ToUnicode map that
is wrong is taken at its word, and a subset font with neither a ToUnicode
map, usable glyph names nor a `cmap` table yields `U+FFFD`.
- Vertical (top-to-bottom) writing is not laid out as columns.
- Scanned pages carry no text; rpdf warns when most pages are (nearly) empty,
and OCR has to come first.
- Tagged-PDF structure, form fields and annotations are ignored.
## Development
See [AGENTS.md](AGENTS.md) for the module layout, the invariants behind the
layout and image code, and how changes are verified.