# How Tiled-Scan Detection Identifies JBIG2 and Strip-Image PDFs in PDF Inspector

> Learn how tiled-scan detection in PDF Inspector identifies JBIG2 and strip-image PDFs by aggregating pixel areas over 2 million, flagging documents with low large tile counts.

- Repository: [Firecrawl/pdf-inspector](https://github.com/firecrawl/pdf-inspector)
- Tags: deep-dive
- Published: 2026-08-14

---

**Tiled-scan detection identifies JBIG2 and strip-image PDFs by aggregating the pixel area of all image objects per page and flagging documents where the total exceeds ~2 million pixels while the count of large tiles remains low.**

PDF Inspector, an open-source Rust library maintained by Firecrawl, classifies PDFs into three categories: **TextBased**, **Scanned**, and **Mixed**. The tiled-scan detection algorithm specifically targets edge-case documents that appear to be mixed or text-based but are actually constructed from many small image tiles. This commonly occurs with **JBIG2-compressed documents** and "strip-image" PDFs where each scan line is stored as a separate image object.

## How Tiled-Scan Detection Works

The detection algorithm in [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs) follows a four-step process to identify these problematic PDFs before extraction begins.

### 1. Page-Wise Image Enumeration

The detector walks through PDF objects and gathers every **XObject of type Image** on each page. This collection phase captures all raster elements regardless of how they're structured in the document hierarchy.

### 2. Tile Size Aggregation

For every image object discovered, the algorithm records pixel dimensions (`width × height`). No filtering occurs at this stage—all image objects contribute to the aggregate statistics.

### 3. Threshold-Based Scoring

The `tiled_scan_detection` function applies two critical thresholds:

- **Total pixel count** must surpass a configurable limit (default **2,000,000 pixels**)
- **Large tile count** must remain below a secondary threshold (tiles > 256 px on either dimension)

When the aggregate area exceeds 2 million pixels but few individual tiles qualify as "large," the page triggers the tiled-scan flag. This pattern indicates many small image fragments rather than one or two full-page raster images.

### 4. JBIG2/Strip-Image Inference

JBIG2-encoded PDFs and strip-image formats store scan lines as **1-pixel-high individual images**. The algorithm catches these because:

- Hundreds or thousands of tiny tiles sum to exceed the pixel threshold
- The large-tile count stays minimal (few strips exceed 256×256)
- The document exhibits image-like total coverage without obvious full-page images

Upon detection, PDF Inspector reclassifies the document from **Mixed** to **Scanned**, forcing the **raster-only extraction path** for more reliable text extraction.

## Implementation Details in [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs)

The core logic resides in the `tiled_scan_detection` function within [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs). This function returns `PdfType::Scanned` when criteria are satisfied, as defined in [`src/types.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/types.rs):

```rust
// From src/types.rs - PdfType enum variants
pub enum PdfType {
    TextBased,
    Scanned,
    Mixed,
}

```

The detector feeds into [`src/extractor/mod.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/extractor/mod.rs), which orchestrates the extraction strategy. Early tiled-scan detection prevents costly mixed-mode processing on documents that behave better as pure image PDFs.

## Running Tiled-Scan Detection

### Command-Line Usage

Analyze any PDF and view classification details including tiled-scan flags:

```bash
RUST_LOG=pdf_inspector::detector=debug cargo run --release --bin detect-pdf -- \
  --analyze --json path/to/document.pdf

```

Example JSON output for a detected tiled-scan document:

```json
{
  "type": "Scanned",
  "tiled_scan": true,
  "details": {
    "total_pixels": 2137425,
    "large_tile_count": 3
  }
}

```

### Programmatic API

```rust
use pdf_inspector::process_pdf_with_options;
use pdf_inspector::options::PdfOptions;

let opts = PdfOptions::default();
let result = process_pdf_with_options("my.pdf", opts)
    .expect("PDF processing failed");

// Check classification after tiled-scan detection
println!("PDF classification: {:?}", result.pdf_type);

if let Some(details) = result.tiled_scan_details {
    println!("Tiled-scan detected: {} tiles, {} total pixels",
             details.large_tile_count, details.total_pixels);
}

```

## Key Source Files

| File | Purpose |
|------|---------|
| [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs) | Implements `tiled_scan_detection` and page sampling logic |
| [`src/extractor/mod.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/extractor/mod.rs) | Chooses extraction strategy based on detector output |
| [`src/types.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/types.rs) | Defines `PdfType` enum and `tiled_scan_details` metadata |
| [`src/bin/detect-pdf.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/bin/detect-pdf.rs) | CLI binary exposing detector functionality |
| [`AGENTS.md`](https://github.com/firecrawl/pdf-inspector/blob/main/AGENTS.md) | Architecture overview documenting tiled-scan detection |

## Summary

- **Tiled-scan detection** identifies PDFs built from many small image tiles rather than full-page rasters
- The **2 million pixel threshold** catches JBIG2 and strip-image documents where aggregate coverage indicates scanned content
- The **large-tile count filter** distinguishes true tiled scans from documents with a few oversized images
- Detection triggers **raster-only extraction**, improving text extraction quality for edge-case formats
- All logic is implemented in Rust within [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs) and exposed via library and CLI interfaces

## Frequently Asked Questions

### What is the default pixel threshold for tiled-scan detection?

The default threshold is approximately **2 million pixels** (2,000,000 px) total area per page. This value is configurable in the detection parameters within [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs).

### Why do JBIG2 PDFs require special handling?

JBIG2 compression stores each scan line or small strip as an individual 1-pixel-high image object. Without tiled-scan detection, PDF Inspector might classify these as **Mixed** documents and attempt text extraction alongside image processing, yielding poor results. The pixel-aggregation approach correctly identifies the image-dominated nature of these files.

### How does tiled-scan detection affect extraction performance?

Detection adds minimal overhead during the initial PDF analysis phase. However, it **prevents costly mixed-mode extraction** on documents that perform better with pure raster extraction. The net effect improves both accuracy and processing time for JBIG2 and strip-image PDFs.

### Can tiled-scan detection be disabled?

Yes. When using the programmatic API with `PdfOptions`, detection behavior inherits from the default configuration. Review [`src/options.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/options.rs) for configuration parameters that control detector thresholds and enablement.