PDF‑Inspector ScanStrategy Options Explained: EarlyExit, Full, Sample, and Pages
Use ScanStrategy::EarlyExit for speed on clearly text‑based PDFs, Full for maximum accuracy, Sample(N) for large documents, and Pages(Vec) when you need precise control over which pages to inspect.
The pdf‑inspector crate classifies PDF documents by scanning page content for text operators (Tj/TJ) to determine whether a file is Text‑based, Scanned, or Mixed. The ScanStrategy enum in src/detector.rs controls which pages get examined and whether the detector can stop early—letting you trade speed for classification fidelity.
ScanStrategy Variants and Their Behavior
The ScanStrategy enum is defined at lines 27–40 of src/detector.rs:
pub enum ScanStrategy {
EarlyExit, // Scan all pages, stop at first non‑text page
Full, // Scan every page regardless
Sample(u32), // Scan up to N evenly‑distributed pages
Pages(Vec<u32>), // Scan only the specified page numbers (1‑indexed)
}
The core detection logic in detect_from_document (lines 92–101) unpacks each variant into a page list and an early‑exit flag:
let (sample_indices, allow_early_exit) = match &config.strategy {
ScanStrategy::EarlyExit => ((1..=total_pages).collect::<Vec<_>>(), true),
ScanStrategy::Full => ((1..=total_pages).collect::<Vec<_>>(), false),
ScanStrategy::Sample(max_pages) => {
let n = (*max_pages).min(total_pages);
(distribute_pages(n, total_pages), false)
}
ScanStrategy::Pages(pages) => (pages.clone(), false),
};
When to Use Each ScanStrategy Option
EarlyExit: Fast Default for Text‑Heavy Pipelines
EarlyExit scans pages sequentially from 1 to N but returns immediately upon finding the first page without text operators. This was the historic default behavior.
- Best for: High‑throughput pipelines processing mostly clean, text‑based PDFs
- Trade‑off: May misclassify Mixed PDFs as Scanned if a non‑text cover page appears first
- Performance: Fastest option when the input is genuinely text‑based
Example: A batch job processing generated reports where you want minimal overhead and can tolerate occasional false negatives.
Full: Complete Accuracy for OCR Decisions
Full examines every page without early termination, building a complete picture of the document's text distribution.
- Best for: Workflows requiring precise distinctions between Scanned and Mixed PDFs
- Trade‑off: Slower on large documents, but eliminates sampling uncertainty
- Performance: Linear with page count; use when downstream OCR costs depend on exact page classification
Example: An invoice processing system where you need to know exactly which pages require OCR versus which can use fast text extraction.
Sample(N): Balanced Approximation for Large Files
ScanStrategy::Sample(N) selects N evenly‑distributed pages across the document using the distribute_pages helper, then scans only those.
- Best for: Very large PDFs (hundreds or thousands of pages) where full scanning is prohibitively slow
- Trade‑off: Statistical approximation—accuracy improves with larger
N - Performance: Bounded by
Nregardless of document length
The sampling algorithm spreads selections across first, middle, and late pages to capture structural variations (e.g., cover sheets, appendices).
Example: Archival processing of multi‑thousand‑page legal documents where you need a reasonable classification without reading every page.
Pages(Vec): Surgical Precision for Known Content
ScanStrategy::Pages(Vec<u32>) scans only the specific page numbers you provide, using 1‑based indexing.
- Best for: Callers with prior knowledge of interesting pages
- Trade‑off: Minimal work, but misses content outside the specified set
- Performance: Optimal when page relevance is pre‑determined
Example: A UI letting users preview specific pages, or a workflow extracting only cover pages and final signatures for verification.
Practical Code Examples
The DetectionConfig struct carries your chosen strategy into detect_pdf_type_with_config. Here's how to instantiate each variant:
use pdf_inspector::detector::{
detect_pdf_type_with_config, DetectionConfig, ScanStrategy,
};
fn main() -> Result<(), pdf_inspector::PdfError> {
let path = "example.pdf";
// 1️⃣ Early‑exit (fast default)
let cfg_early = DetectionConfig {
strategy: ScanStrategy::EarlyExit,
..Default::default()
};
let res_early = detect_pdf_type_with_config(path, cfg_early)?;
println!("Early‑exit result: {:?}", res_early.pdf_type);
// 2️⃣ Full scan (maximum accuracy)
let cfg_full = DetectionConfig {
strategy: ScanStrategy::Full,
..Default::default()
};
let res_full = detect_pdf_type_with_config(path, cfg_full)?;
println!("Full scan result: {:?}", res_full.pdf_type);
// 3️⃣ Sample 5 pages (good for large PDFs)
let cfg_sample = DetectionConfig {
strategy: ScanStrategy::Sample(5),
..Default::default()
};
let res_sample = detect_pdf_type_with_config(path, cfg_sample)?;
println!("Sample‑5 result: {:?}", res_sample.pdf_type);
// 4️⃣ Custom page list (e.g., only cover & last page)
let cfg_pages = DetectionConfig {
strategy: ScanStrategy::Pages(vec![1, 10]),
..Default::default()
};
let res_pages = detect_pdf_type_with_config(path, cfg_pages)?;
println!("Pages‑[1,10] result: {:?}", res_pages.pdf_type);
Ok(())
}
For CLI usage, src/bin/detect_pdf.rs exposes these as --sample N and --pages 1,2,3 flags.
Key Source Files
src/detector.rs: DefinesScanStrategy,DetectionConfig,PdfType, and thedetect_from_documentimplementationsrc/lib.rs: Public API surface withdetect_pdf_type_with_configand convenience functionssrc/bin/detect_pdf.rs: Command‑line interface forwarding flags toDetectionConfigtests/integration_tests.rs: Validation suite ensuring each strategy produces correct OCR recommendations
Summary
EarlyExit— fastest for text‑based PDFs; stops at first non‑text pageFull— complete accuracy; scans every page to distinguish Scanned from MixedSample(N)— scalable approximation for large documents using N distributed pagesPages(Vec)— maximal control; scans only specified pages when relevance is known
Choose based on your document size, required precision, and prior knowledge of page structure.
Frequently Asked Questions
What happens if Sample(N) requests more pages than the document contains?
The detector clamps N to total_pages via (*max_pages).min(total_pages) in src/detector.rs line 97, then distributes all available pages. No error occurs—Sample(100) on a 5‑page PDF simply scans all 5 pages.
Can EarlyExit and Full return different PdfType results for the same file?
Yes. EarlyExit may classify a Mixed PDF as Scanned if page 1 lacks text, while Full would correctly identify it as Mixed after finding text on later pages. Use Full when this distinction matters for downstream OCR costs.
How does the distribute_pages function select pages for Sample(N)?
The implementation spreads selections evenly across the document range, typically including first and last pages plus interior pages at calculated intervals. This captures structural patterns (covers, headers, content bodies) better than random sampling.
Is ScanStrategy configurable when using the CLI binary?
Yes. The detect_pdf binary in src/bin/detect_pdf.rs accepts --sample N for Sample(N) and --pages 1,3,5 for Pages. Without flags, it defaults to EarlyExit behavior for backward compatibility.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →