Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

PDF.OCR

A .NET 10 console application that compresses PDFs, auto-corrects page orientation, and makes them searchable using OCR. All dependencies use fully permissive open-source licenses (MIT / Apache 2.0).

How It Works

Input PDF ─► Render ─► Orient ─► Deskew ─► OCR ─► Searchable PDF
             (PDFium)  (Tesseract  (Leptonica   (Tesseract  (PDFsharp)
                        OSD)        + SkiaSharp)  HOCR)
  1. Renders each page to a high-resolution image via PDFium (Docnet.Core)
  2. Detects orientation using Tesseract OSD (Orientation and Script Detection)
  3. Validates rotation by comparing OCR confidence on both the original and rotated image — only rotates when it genuinely improves results (≥ 5% confidence gain)
  4. Deskews the page by detecting slight scan skew via Leptonica and applying a precise sub-degree rotation with SkiaSharp to straighten text lines
  5. Runs OCR on the corrected image, extracting word text and bounding boxes via HOCR
  6. Builds a new PDF with JPEG-compressed page images and an invisible text overlay for full-text search and selection

Setup

Prerequisites

Build

cd PDF.OCR
dotnet build

Download Tesseract Trained Data

Download both files from tessdata_fast:

File Purpose
eng.traineddata English OCR (or your language of choice)
osd.traineddata Orientation and Script Detection (required for auto-rotation)

Place them in a tessdata folder next to the executable or the project directory:

PDF.OCR/
  tessdata/
    eng.traineddata
    osd.traineddata
  PDF.OCR.csproj
  Program.cs

The app searches for the tessdata folder in this order:

  1. TESSDATA_PREFIX environment variable
  2. Next to the executable (bin/Debug/net10.0/)
  3. Current working directory

Usage

dotnet run -- <input.pdf> [output.pdf] [options]

Or, after publishing:

PDF.OCR <input.pdf> [output.pdf] [options]

If no output path is given, the output is saved as <input>_searchable.pdf in the same directory.

Options

Option Description Default
--dpi <value> Render resolution for OCR 300
--quality <value> JPEG compression quality (1–100) 75
--tessdata <path> Parent directory containing tessdata folder auto-detected
--lang <code> Tesseract language code eng

Examples

# Basic — outputs scan_searchable.pdf
dotnet run -- scan.pdf

# Custom output path with lower DPI and compression
dotnet run -- scan.pdf output.pdf --dpi 200 --quality 60

# German language OCR with custom tessdata location
dotnet run -- scan.pdf --lang deu --tessdata /opt/tessdata

Sample Output

Processing 10 page(s) at 300 DPI, JPEG quality 75...
  Page 1/10... (kept original, orig 90% vs rot 90%) (deskew -0.5°) (21 words, 88% conf) done.
  Page 2/10... (rotated 90°, 50%→95%) (deskew +0.5°) (8 words, 90% conf) done.
  Page 3/10... (rotated 90°, 34%→90%) (deskew +0.4°) (103 words, 89% conf) done.
  ...
Input:  36.9 MB - scan.pdf
Output: 5.0 MB  - scan_searchable.pdf
Ratio:  13.6%

Auto-Rotation

Pages are automatically checked for incorrect orientation using Tesseract's Orientation and Script Detection (OSD). To avoid false positives, rotation is only applied when it measurably improves OCR accuracy:

  1. OSD proposes a rotation (90°, 180°, or 270°)
  2. Quick OCR is run on both the original and rotated image
  3. Rotation is applied only if confidence improves by ≥ 5 percentage points
  4. Otherwise the original orientation is kept

This ensures pages that are already correctly oriented are never accidentally rotated.

Deskew (Straightening)

After orientation correction, each page is checked for slight scan skew — the small tilt that occurs when a document isn't perfectly aligned on the scanner glass.

  1. Leptonica (bundled with Tesseract) analyzes the binarized page to detect the skew angle
  2. If the angle exceeds 0.1°, the color image is rotated by that precise amount using SkiaSharp
  3. Exposed corners from the rotation are filled with white
  4. The straightened image is then used for OCR and PDF output

Typical corrections are in the range of ±0.3° to ±1.0° — small enough to be invisible in the original, but enough to noticeably improve text alignment in the output.

Platform Support

Platform Status Notes
Windows (x64, x86) ✅ Full support Works out of the box
Linux (x64, ARM, ARM64) ⚠️ Requires setup See below
macOS (x64, Apple Silicon) ⚠️ Requires setup See below

Windows

No extra setup needed. All native libraries are included via NuGet.

Linux

Docnet.Core and SkiaSharp include Linux native binaries. However:

  1. Tesseract native library must be installed via system package manager:

    # Debian/Ubuntu
    sudo apt install libtesseract-dev libleptonica-dev
    
    # Fedora/RHEL
    sudo dnf install tesseract-devel leptonica-devel
  2. Fonts — PDFsharp needs fonts for the invisible text layer. Install a basic font package:

    sudo apt install fonts-liberation   # provides Arial-compatible fonts

    On Linux, you may also need to set a custom IFontResolver for PDFsharp if system fonts aren't found. The current code enables UseWindowsFontsUnderWindows on Windows only.

macOS

Same as Linux: install Tesseract via Homebrew (brew install tesseract) and ensure system fonts are available.

Libraries & Licenses

All dependencies use fully permissive open-source licenses — no commercial license required for any use case:

Library Version License Purpose
Docnet.Core 2.6.0 MIT PDF page rendering via PDFium
Tesseract 5.2.0 Apache 2.0 OCR engine (.NET wrapper)
PDFsharp 6.2.4 MIT PDF document creation
SkiaSharp 3.119.2 MIT Image processing (BGRA → JPEG/PNG)

License verification: each license was confirmed from the <license type="expression"> field in the package .nuspec metadata.

Architecture

Program.cs
├── Main()                 — CLI entry point, argument validation
├── MakeSearchablePdf()    — Pipeline orchestrator (open PDF → process pages → save)
├── ProcessPage()          — Per-page: render → orient → deskew → OCR → build PDF page
├── DetectRotation()       — Tesseract OSD orientation detection
├── QuickOcrConfidence()   — Fast OCR pass for rotation validation
├── RotateBitmap()         — SkiaSharp 90°/180°/270° rotation
├── DetectSkewAngle()      — Leptonica skew angle detection
├── DeskewBitmap()         — SkiaSharp sub-degree rotation for straightening
├── DrawTextOverlay()      — Invisible text layer (behind image) for searchability
├── ParseHocr()            — Extract words + bounding boxes from Tesseract HOCR
├── ParseArguments()       — CLI argument parsing
├── ResolveTessDataPath()  — Auto-detect tessdata folder location
├── DefaultOutputPath()    — Generate output filename (_searchable.pdf)
├── FormatSize()           — Human-readable file size formatting
└── PrintUsage()           — Help text

Records:
├── AppConfig              — Immutable CLI configuration
└── OcrWord                — Single word with bounding box from HOCR

Compression Notes

  • Pages are re-rendered as JPEG images at the specified quality level (default 75%)
  • Lower --quality values produce smaller files but with more compression artifacts
  • Lower --dpi values reduce file size and speed up processing but may reduce OCR accuracy
  • For best OCR accuracy, keep DPI at 300; for smallest file size, try --dpi 150 --quality 50
  • Typical compression: 80–90% size reduction on scanned PDFs

About

PDF.OCR

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages