pub struct PdfDocument { /* private fields */ }Expand description
High-level PDF document handle.
Implementations§
Source§impl PdfDocument
impl PdfDocument
Sourcepub fn open_with_processing_limits(
data: impl Into<PdfData>,
limits: ProcessingLimits,
) -> Result<Self>
pub fn open_with_processing_limits( data: impl Into<PdfData>, limits: ProcessingLimits, ) -> Result<Self>
Open a PDF from bytes with processing limits.
Sourcepub fn open_with_password(
data: impl Into<PdfData>,
password: &str,
) -> Result<Self>
pub fn open_with_password( data: impl Into<PdfData>, password: &str, ) -> Result<Self>
Open a password-protected PDF.
Sourcepub fn open_with_password_and_processing_limits(
data: impl Into<PdfData>,
password: &str,
limits: ProcessingLimits,
) -> Result<Self>
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.
Sourcepub fn load_recovery(&self) -> LoadRecovery
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.
Sourcepub fn set_settings(&mut self, settings: InterpreterSettings)
pub fn set_settings(&mut self, settings: InterpreterSettings)
Set interpreter settings (font resolver, cmap resolver, etc.).
Sourcepub fn set_keep_ligatures(&mut self, keep: bool)
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.
Sourcepub fn set_warning_sink(&mut self, sink: WarningSinkFn)
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.
Sourcepub fn page_count(&self) -> usize
pub fn page_count(&self) -> usize
Number of pages.
Sourcepub fn page_geometry(&self, index: usize) -> Result<PageGeometry>
pub fn page_geometry(&self, index: usize) -> Result<PageGeometry>
Get the geometry of a page.
Sourcepub fn render_page(
&self,
index: usize,
options: &RenderOptions,
) -> Result<RenderedPage>
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.
Sourcepub fn render_page_with_config(
&self,
index: usize,
config: &RenderConfig,
) -> Result<RenderedPage>
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.
Sourcepub fn render_page_cmyk(&self, index: usize, dpi: u32) -> Result<RenderedPage>
pub fn render_page_cmyk(&self, index: usize, dpi: u32) -> Result<RenderedPage>
Render a single page to a CMYK buffer.
Sourcepub fn render_all(&self, options: &RenderOptions) -> Vec<RenderedPage>
pub fn render_all(&self, options: &RenderOptions) -> Vec<RenderedPage>
Render all pages, in parallel when the parallel feature is enabled.
Sourcepub fn render_all_with_config(&self, config: &RenderConfig) -> Vec<RenderedPage>
pub fn render_all_with_config(&self, config: &RenderConfig) -> Vec<RenderedPage>
Render all pages using the high-level render config.
Sourcepub fn thumbnail(
&self,
index: usize,
options: &ThumbnailOptions,
) -> Result<RenderedPage>
pub fn thumbnail( &self, index: usize, options: &ThumbnailOptions, ) -> Result<RenderedPage>
Generate a thumbnail for a single page.
Sourcepub fn thumbnails_all(&self, options: &ThumbnailOptions) -> Vec<RenderedPage>
pub fn thumbnails_all(&self, options: &ThumbnailOptions) -> Vec<RenderedPage>
Generate thumbnails for all pages, in parallel when the parallel feature is enabled.
Sourcepub fn extract_text(&self, index: usize) -> Result<String>
pub fn extract_text(&self, index: usize) -> Result<String>
Extract text from a page as a single string.
Sourcepub fn extract_text_blocks(&self, index: usize) -> Result<Vec<TextBlock>>
pub fn extract_text_blocks(&self, index: usize) -> Result<Vec<TextBlock>>
Extract structured text blocks from a page.
Sourcepub fn extract_text_blocks_rich(&self, index: usize) -> Result<Vec<TextBlock>>
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.
Sourcepub fn extract_all_text_blocks(&self) -> Vec<Vec<TextBlock>>
pub fn extract_all_text_blocks(&self) -> Vec<Vec<TextBlock>>
Extract structured text blocks from all pages, reusing interpreter settings.
Sourcepub fn extract_page_blocks(
&self,
index: usize,
first_index: usize,
) -> Result<Vec<Block>>
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.
Sourcepub fn extract_blocks(&self, options: &ExtractOptions) -> Result<Vec<Block>>
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.
Sourcepub fn extract_words(&self, options: &ExtractOptions) -> Result<Vec<Word>>
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
impl PdfDocument
Sourcepub fn page_needs_ocr(&self, index: usize) -> OcrNeed
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.
Sourcepub fn vision_advice(&self) -> Result<Vec<VisionAdvice>>
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.
Sourcepub fn extract_figures(&self, options: &ExtractOptions) -> Result<Vec<Figure>>
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();
}Sourcepub fn extract_markdown(&self, options: &ExtractOptions) -> Result<String>
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.
Sourcepub fn extract_docling(
&self,
name: &str,
options: &ExtractOptions,
) -> Result<String>
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.
Sourcepub fn extract_acroform_text(&self) -> String
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.
Sourcepub fn extract_all_text(&self) -> String
pub fn extract_all_text(&self) -> String
Extract all text from the document: page content streams plus AcroForm field values. Mirrors pdftotext behaviour.
Sourcepub fn search_text(&self, query: &str) -> Vec<usize>
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.
Sourcepub fn info(&self) -> DocumentInfo
pub fn info(&self) -> DocumentInfo
Extract document metadata.
Sourcepub fn bookmarks(&self) -> Vec<BookmarkItem>
pub fn bookmarks(&self) -> Vec<BookmarkItem>
Extract document outline / bookmarks.
Sourcepub fn page_links(&self, index: usize) -> Result<Vec<PageLink>>
pub fn page_links(&self, index: usize) -> Result<Vec<PageLink>>
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.
Sourcepub fn ocr_page(
&self,
index: usize,
backend: &dyn OcrBackend,
dpi: f64,
) -> Result<OcrResult>
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
impl PdfDocument
Sourcepub fn searchable_copy<E: OcrEngine>(
&self,
options: &ExtractOptions,
engine: &E,
) -> Result<PdfDocument>
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§
impl !RefUnwindSafe for PdfDocument
impl !UnwindSafe for PdfDocument
impl Freeze for PdfDocument
impl Send for PdfDocument
impl Sync for PdfDocument
impl Unpin for PdfDocument
impl UnsafeUnpin for PdfDocument
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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