# 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.