Skip to main content

PdfDocument

Struct PdfDocument 

Source
pub struct PdfDocument { /* private fields */ }
Expand description

High-level PDF document handle.

Implementations§

Source§

impl PdfDocument

Source

pub fn open(data: impl Into<PdfData>) -> Result<Self>

Open a PDF from bytes.

Source

pub fn open_with_processing_limits( data: impl Into<PdfData>, limits: ProcessingLimits, ) -> Result<Self>

Open a PDF from bytes with processing limits.

Source

pub fn open_with_password( data: impl Into<PdfData>, password: &str, ) -> Result<Self>

Open a password-protected PDF.

Source

pub fn open_with_password_and_processing_limits( data: impl Into<PdfData>, password: &str, limits: ProcessingLimits, ) -> Result<Self>

Open a password-protected PDF with processing limits.

Source

pub fn pdf(&self) -> &Pdf

Access the underlying parsed PDF.

Source

pub fn load_recovery(&self) -> LoadRecovery

Structural recovery applied while loading this document (xref / page-tree rebuild). All-false for a document that parsed cleanly.

Source

pub fn set_settings(&mut self, settings: InterpreterSettings)

Set interpreter settings (font resolver, cmap resolver, etc.).

Source

pub fn set_keep_ligatures(&mut self, keep: bool)

Hand back the ligature code points a font declared – ffi rather than ffi – from every TEXT extraction on this document: the pages, the blocks and their spans, the markdown and JSON over them, and the AcroForm field values Self::extract_acroform_text reads.

Off by default: one glyph for three letters is a typesetting decision, and a reader that keeps U+FB03 hands back a word no search box will match (#437). Turn it on when the caller wants the file’s own characters: a typesetting tool, or a comparison against the content stream.

Outside it either way is what is not a TEXT output: the training input Self::extract_blocks_before_learning, which the models read, and glyph-level readers outside this crate.

Source

pub fn set_warning_sink(&mut self, sink: WarningSinkFn)

Install a warning sink that receives InterpreterWarnings raised during subsequent render / text-extraction operations.

Replaces any previously installed sink; all other settings (cache, limits, resolvers) are preserved. The sink is preserved across the extraction-settings clone, so it covers both rendering and extraction.

Source

pub fn page_count(&self) -> usize

Number of pages.

Source

pub fn page_geometry(&self, index: usize) -> Result<PageGeometry>

Get the geometry of a page.

Source

pub fn render_page( &self, index: usize, options: &RenderOptions, ) -> Result<RenderedPage>

Render a single page.

If the document contains an XFA template, it is automatically flattened to static PDF content before rendering. This prevents the “Please wait” placeholder page that Adobe Reader would show when rendering an XFA PDF with a conventional renderer. If flattening fails, rendering falls back to the original document as a best-effort path.

Source

pub fn render_page_with_config( &self, index: usize, config: &RenderConfig, ) -> Result<RenderedPage>

Render a single page using the high-level render config.

XFA documents are auto-flattened before rendering (same as render_page). If flattening fails, rendering falls back to the original document.

Source

pub fn render_page_cmyk(&self, index: usize, dpi: u32) -> Result<RenderedPage>

Render a single page to a CMYK buffer.

Source

pub fn render_all(&self, options: &RenderOptions) -> Vec<RenderedPage>

Render all pages, in parallel when the parallel feature is enabled.

Source

pub fn render_all_with_config(&self, config: &RenderConfig) -> Vec<RenderedPage>

Render all pages using the high-level render config.

Source

pub fn thumbnail( &self, index: usize, options: &ThumbnailOptions, ) -> Result<RenderedPage>

Generate a thumbnail for a single page.

Source

pub fn thumbnails_all(&self, options: &ThumbnailOptions) -> Vec<RenderedPage>

Generate thumbnails for all pages, in parallel when the parallel feature is enabled.

Source

pub fn extract_text(&self, index: usize) -> Result<String>

Extract text from a page as a single string.

Source

pub fn extract_text_blocks(&self, index: usize) -> Result<Vec<TextBlock>>

Extract structured text blocks from a page.

Source

pub fn extract_text_blocks_rich(&self, index: usize) -> Result<Vec<TextBlock>>

Extract structured text blocks with tight per-glyph geometry.

Same blocks as Self::extract_text_blocks, but the device runs in GeometryMode::RichGeometry so every span also carries its outline-tight glyph bounds, advances and bound sources. The door’s span dicts read those; nothing else in the engine consumes them.

Source

pub fn extract_all_text_blocks(&self) -> Vec<Vec<TextBlock>>

Extract structured text blocks from all pages, reusing interpreter settings.

Source

pub fn text_with_layout(&self) -> Vec<LayoutBlock>

Every text block of the document with its page and enclosing box.

The positional counterpart of plain text extraction: what the text_with_layout call of each binding returns.

Source

pub fn extract_page_blocks( &self, index: usize, first_index: usize, ) -> Result<Vec<Block>>

Extract one page’s paragraphs (#567).

Preview: output quality is still improving and the API may change in a minor release.

Where Self::extract_text_blocks hands back the page’s LINES, this hands back the units a caller chunks, cites or embeds: the lines merged into paragraphs, never across a column gap and never across a table.

first_index is where this page’s blocks start in the document’s reading order; Self::extract_blocks counts it for a whole document.

The heading levels are taken from THIS PAGE’s statistics, because a page asked for on its own is the only document there is to take them from (#568). A caller that wants the levels the whole document implies asks for the whole document: Self::extract_blocks runs the same classifier over every page at once.

Source

pub fn extract_blocks(&self, options: &ExtractOptions) -> Result<Vec<Block>>

Every block of the document, in reading order, numbered from zero (#567, #573).

Preview: output quality is still improving and the API may change in a minor release.

options says which pages the caller wants back; the document is read whole whatever it says, because what a block IS is decided against the rest of the document. See ExtractOptions.

A Result, and the limit collector on every page, because the whole document is exactly where a caller reading untrusted files leans on ProcessingLimits: a convenience method that swallowed a StreamTooLarge would hand back a silently short document where the caller asked to be told (codex, round 1).

NOTHING ON THE TEXT PATH RAISES IT TODAY. The only producer of that warning is the image-XObject decode, and image decode is lazy – it happens in the rendering device and not in interpret_page, which is why crates/pdfluent/tests/processing_limits.rs has to call to_images to provoke it. So this collector is the same inert guard Self::extract_text and Self::extract_page_blocks already carry, and it is here for the same reason: the day something on this path does raise it, the three methods answer alike instead of two of them answering and the convenience one going quiet.

Source

pub fn extract_words(&self, options: &ExtractOptions) -> Result<Vec<Word>>

Every word of the document, with the box it was drawn in.

Preview: output quality is still improving and the API may change in a minor release.

The extract_words=True of pymupdf4llm: what a RAG pipeline cites, highlights and grounds with. Built from the blocks Self::extract_blocks returns – same options, same window – by splitting each span’s text on whitespace and taking the union of that word’s char_bounds. A span without char_bounds gives its words the span box, split proportionally by character count. Words come in reading order, block by block and line by line. One function, no second text pass.

§Example
use pdf_engine::{ExtractOptions, PdfDocument};

let document = PdfDocument::open(std::fs::read("report.pdf").unwrap()).unwrap();
let words = document.extract_words(&ExtractOptions::default()).unwrap();
for word in &words {
    println!("p{} {:?} {:?}", word.page, word.text, word.bbox);
}
Source§

impl PdfDocument

Source

pub fn page_needs_ocr(&self, index: usize) -> OcrNeed

How much OCR one page needs: born-digital text, a scan, or text around image regions that carry no text of their own.

See crate::ocr_need::OcrNeed for what each verdict means and the thresholds behind it. A page index that does not exist reports crate::ocr_need::OcrNeed::None.

Source

pub fn vision_advice(&self) -> Result<Vec<VisionAdvice>>

Which pages are worth sending to a vision model, and why (#624).

One entry per page, in page order. What sets a flag is documented on VisionAdvice; today that is the scanned page and nothing else, and the two reasons that are not wired say so in their own documentation rather than quietly reading false.

A PAGE THAT DRAWS NOTHING IS NOT A SCAN. An empty page yields no text either, and sending it to a vision model costs a call and returns nothing; so the flag asks for ink as well as for silence. Ink is any image, glyph or path the page draws, counted by the interpreter rather than guessed from the resources: a page whose /XObject names an image nothing ever draws is not a scan of anything.

Source

pub fn extract_figures(&self, options: &ExtractOptions) -> Result<Vec<Figure>>

Every figure of the window, in reading order, with rendered pixels (#658).

Preview: output quality is still improving and the API may change in a minor release.

The BlockKind::Figure blocks Self::extract_blocks lists under these options, each with its box rendered at 150 dots per inch and encoded as PNG. One render per page that carries figures. Names are figure_names, the same ones Self::extract_markdown references.

§Example
use pdf_engine::{ExtractOptions, PdfDocument};

let document = PdfDocument::open(std::fs::read("report.pdf").unwrap()).unwrap();
let options = ExtractOptions::default();
for figure in document.extract_figures(&options).unwrap() {
    std::fs::write(&figure.name, &figure.png).unwrap();
}
Source

pub fn extract_markdown(&self, options: &ExtractOptions) -> Result<String>

The document as markdown, in reading order (#573).

Preview: output quality is still improving and the API may change in a minor release.

Self::extract_blocks and crate::to_markdown in one call, which is the whole of it: headings become # to ###, list items - and 1., a table a pipe table or an HTML one where markdown cannot hold its shape, and a change of page an HTML comment. The running heads are not in it – they are in the blocks, where a caller that wants them reads them, or the caller sets ExtractOptions::include_headers and ExtractOptions::include_footers and they are written as plain paragraphs at their reading-order position. ExtractOptions::page_separators drops the page comment instead. docs/STRUCTURED_EXTRACTION.md is the reader’s account of every one of those rules.

Monospace runs become code unless ExtractOptions::code is false: an inline span in a paragraph or a list item, a fenced block for a

A Result and not a bare String for the reason Self::extract_blocks is one: the limits a caller set on an untrusted file are the whole point of setting them, and a convenience method that swallowed a crate::limits::LimitError would hand back a silently short document to the caller who asked to be told.

With Quality::Balanced this runs the balanced tier instead of the above (#641): the layout model regions each page and the engine’s own text fills the regions. It needs the ort-layout cargo feature and the weights from an explicit pdfluent models install layout; without the feature it fails with MODEL_NOT_AVAILABLE naming the feature and the install command, and with the feature but without the files, with MODEL_NOT_AVAILABLE naming the path looked at and the install command. ExtractOptions::model_dir points the tier at a scratch directory, ExtractOptions::keep_furniture keeps running heads as paragraphs.

Source

pub fn extract_docling( &self, name: &str, options: &ExtractOptions, ) -> Result<String>

The document as a Docling DoclingDocument, in reading order (#629).

Preview: output quality is still improving and the API may change in a minor release.

Self::extract_blocks and crate::to_docling_json in one call, with every page of the window listed under pages at its size. name is DoclingDocument.name, which Docling fills with the file’s stem. What maps onto Docling’s schema and what does not is written out in crate::docling.

Source

pub fn extract_acroform_text(&self) -> String

Extract text values from AcroForm fields, including push-button captions.

Returns a single string concatenating all non-empty field values separated by newlines. Useful when the document stores its readable content in form field values rather than (or in addition to) page content streams.

Source

pub fn extract_all_text(&self) -> String

Extract all text from the document: page content streams plus AcroForm field values. Mirrors pdftotext behaviour.

Source

pub fn search_text(&self, query: &str) -> Vec<usize>

Simple text search: returns page indices containing the query string.

The query is folded the same way the pages are, so a word carrying a ligature code point – pasted out of a content stream, or typed from a file that maps its glyphs to U+FB00-FB06 – still finds the page it came from.

Source

pub fn info(&self) -> DocumentInfo

Extract document metadata.

Source

pub fn bookmarks(&self) -> Vec<BookmarkItem>

Extract document outline / bookmarks.

Every /Link annotation on one page, in /Annots order.

A link without a readable /Rect is skipped: with no region it cannot be rendered or cited. All other annots on the page are skipped too; only /Link is a link.

Source

pub fn ocr_page( &self, index: usize, backend: &dyn OcrBackend, dpi: f64, ) -> Result<OcrResult>

Run OCR on a page and return the recognized text and word positions.

The page is rendered at dpi (default 150) before recognition. Pass any [OcrBackend] implementation; use [OcrsBackend::try_default] to load the pure-Rust ocrs engine from the standard model paths.

§Example
use pdf_engine::{PdfDocument, OcrsBackend, RenderOptions};

let doc = PdfDocument::open(std::fs::read("scan.pdf").unwrap()).unwrap();
let backend = OcrsBackend::try_default().unwrap();
let result = doc.ocr_page(0, &backend, 150.0_f64).unwrap();
println!("{}", result.text);
Source§

impl PdfDocument

Source

pub fn searchable_copy<E: OcrEngine>( &self, options: &ExtractOptions, engine: &E, ) -> Result<PdfDocument>

A copy of this document with an OCR text layer over the window’s pages, recognized by engine (feature ocr-cli).

options steers which pages and how: OcrMode::Auto recognizes the pages under pdf-ocr’s text threshold, OcrMode::Force recognizes every page in the window after dropping its native text, at ExtractOptions::ocr_dpi and in ExtractOptions::ocr_language – the language only steers the engine this method is handed when that engine reads it. Pages outside the window are untouched, and an empty window reads back an unchanged copy.

OcrMode::Never is a caller error here: nothing would be recognized and the copy would be a roundtrip for nothing. Callers that take “no OCR” as a normal case want extract_blocks, which branches before this.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Send + Sync>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync> ⓘ

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

Source§

fn simd_from(_simd: S, value: T) -> T

Source§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

Source§

fn simd_from(value: T, _simd: S) -> T

Source§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

Source§

fn simd_into(self, simd: S) -> T

Source§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

Source§

fn simd_into(self, simd: S) -> T

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more