scanlayer
Docs / Reference

Feature Catalog

A complete, categorized list of what scanlayer does. This mirrors the library source directly: if it is not listed here, it is not implemented (see Roadmap & Limitations for what is deliberately out of scope).

Core conversion

  • Turn a scanned image or photo into a searchable PDF with an invisible, selectable text layer (convert(), scanlayer input -o output.pdf).
  • Export the raw OCR result instead of a PDF, as plain text, JSON, TSV, or hOCR, with no PDF built at all (--format / output_format=). See Output Formats.
  • Accept native .pdf files as input, automatically rasterized page by page before OCR (requires poppler). See Multi-Page and Merge.
  • Batch-convert many files in one call, mixed extensions and glob patterns welcome, one output per input.
  • Merge several images, or every page of a source PDF, into one multi-page searchable PDF (--merge / convert_merge()).
  • Validate an entire batch before committing to OCR: every input exists and is readable, Tesseract is reachable, output paths are writable (--dry-run, CLI only; library callers get the same checks via validate_all()).
  • Works both as a CLI (scanlayer) and as a Python library (import scanlayer), identical functionality either way.
  • Runs from an installed package (pip install scanlayer) or directly from a source checkout (python -m scanlayer), no install required.

Image preprocessing

  • Automatic EXIF orientation correction, applied before anything else so a sideways phone photo does not defeat later steps.
  • Automatic gross rotation correction (0/90/180/270) via Tesseract orientation and script detection (OSD).
  • Automatic fine deskew (a few degrees of tilt) via minAreaRect on detected text pixels, with outlier rejection so a false signal (like a page border) does not introduce a bad rotation.
  • Manual orientation override: disable all auto-correction (orientation="none") or force an exact angle in degrees (orientation=10).
  • Illumination correction for uneven lighting and cast shadows (common on mobile phone photos), combining a Gaussian and a morphological background estimate.
  • Denoising (fastNlMeansDenoising) and adaptive local contrast enhancement (CLAHE), tuned separately from the visual background so the displayed page never looks processed.
  • Light unsharp-mask sharpening after denoising and CLAHE, recovering edge definition that those steps soften, especially on thin strokes and accents.
  • Automatic upscaling of low-resolution images before OCR, and automatic downscaling of very large images to avoid excessive processing time and memory use.
  • Blank-page detection based on grayscale standard deviation (not OCR confidence, which is unreliable on noise), with a force override.
  • The two outputs of preprocessing (background, the visual page, and ocr_image, the Tesseract input) are kept separate throughout, so OCR-only processing never touches what is actually displayed in the PDF.

OCR engine

  • Automatic page segmentation mode (PSM) selection: several candidate PSMs are tried and the one with the highest mean confidence wins.
  • Early exit once a candidate clears a configurable confidence threshold, skipping the rest.
  • Parallel OCR passes across PSM candidates via a thread pool (Tesseract releases the GIL while running, so this is a real speedup), with a configurable worker cap.
  • Per-pass timeout, so a hung Tesseract process cannot hang the whole pipeline.
  • Configurable Tesseract engine mode (legacy, LSTM, or both).
  • Character whitelisting and blacklisting for constrained fields (pure numeric codes, for example).
  • Multi-language OCR (--lang fra+eng, or any Tesseract language combination).
  • Non-printable / control-character filtering on recognized words.
  • Per-word confidence scores retained through the whole pipeline, used for the confidence threshold, the debug overlay, and the JSON/TSV export.

Multi-column layout reconstruction

  • Geometric detection of genuine multi-column pages (prose-style: articles, letters, reports), independent of which Tesseract PSM won the OCR race.
  • Re-derives left-to-right, top-to-bottom reading order across detected columns, correcting Tesseract's tendency to interleave columns line by line.
  • Row-level gap voting for gutter detection, so a centered title or footer that overlaps the gutter does not block detection.
  • Full-width line handling (titles, headers, footers) placed before or after the column block rather than forced into one column.
  • Safety fallback: if reordering would drop or duplicate a word, the original order is kept instead.
  • Deliberately does not attempt table/grid detection; a table's narrow, per-row gutters are a structurally different problem.
  • Can be disabled per run (--no-column-detection) or globally (configure(multi_column_detection=False)).

Output and PDF construction

  • Invisible, selectable text layer (PDF render mode 3) precisely positioned and horizontally stretched to match each word's detected bounding box.
  • Adaptive background compression: lossless PNG for near-binary (black-text-on-white) pages, JPEG otherwise, at a configurable quality.
  • Automatic grayscale encoding when the source image has negligible color, cutting background size roughly threefold.
  • Automatic font selection for the invisible text layer based on OCR language (a CJK CID font, a bundled DejaVu Sans, or a Helvetica fallback), or a manual override with any TTF font.
  • Standard PDF metadata: title, author, subject, creator, keywords.
  • Bounds validation on font size and horizontal text scaling, so a mis-segmented word cannot produce a malformed PDF operator.
  • Page size validation against the PDF specification's page-size limit.
  • A single failing word is skipped with a warning rather than aborting the whole page's text layer.
  • Multi-page PDF construction from independently preprocessed and OCR'd pages, each with its own dimensions, DPI, and language if needed.

Structured export formats

  • Plain text (txt), one line per detected line of text.
  • JSON (json), with full text, mean confidence, winning PSM, language, image dimensions, and a per-word array of text, confidence, and bounding box.
  • TSV (tsv), a flat, spreadsheet/pandas-friendly schema distinct from Tesseract's own TSV layout.
  • hOCR (hocr), a minimal standard document (ocr_page/ocr_line/ocrx_word) consumable by other OCR tooling.
  • Each format is also reachable as a standalone function (to_text/to_json/to_tsv/to_hocr) for programs that already have a Word list and want to skip the CLI or convert() entirely.

Batch and multi-page handling

  • One-call batch conversion with glob expansion and automatic native-PDF page rasterization built in.
  • Per-file failure isolation: one bad file in a batch does not stop the rest, and every failure is reported individually.
  • Automatic output file naming from each input's stem when writing to a folder.
  • Multi-page merge from either several separate images or the pages of a single source PDF, in a consistent page order.

Debug and diagnostics

  • --debug-image overlay: every recognized word boxed and colored by confidence tier, with its confidence score printed above it.
  • A header band on the overlay summarizing the PSM used, word count, mean confidence, language, and the orientation correction actually applied.
  • Per-stage timing in the logs (preprocessing, OCR, PDF build) to spot bottlenecks.
  • Verbose (-v) and quiet (-q) logging levels, or a fully custom log level via configure(log_level=...).

Configuration

  • A single configure(**overrides) call covering OCR, preprocessing, layout, PDF, and logging settings, with unknown keys rejected loudly.
  • Config profiles in JSON or YAML, loaded via --config on the CLI or configure_from_file() in the library.
  • A documented precedence order: direct convert() arguments override configure() calls, which override environment variables, which override hardcoded defaults.
  • get_settings() to inspect every current setting at once.
  • Automatic Tesseract binary discovery across Windows, macOS, and Linux, with a documented resolution order and an environment-variable override.

Deployment

  • Bundled-Tesseract support: a host application can ship its own Tesseract binary and tessdata next to the package, detected automatically with no configuration.
  • No hardcoded system paths; every OS-specific lookup has a fallback chain ending in a clear, actionable error rather than a cryptic one.

Error handling

  • A two-tier exception hierarchy: validation errors (bad input, bad environment, checked before any work starts) versus pipeline errors (a stage that started and failed for an operational reason).
  • Distinct, standardized CLI exit codes for user errors, environment errors, unexpected errors, processing errors, and partial batch failures.
  • Explicit blank-page detection with an opt-in override (--force), instead of silently producing an empty PDF.
  • Actionable error messages throughout (a missing poppler install, a missing Tesseract binary, an unwritable output directory) rather than raw subprocess or library tracebacks.
Looking for how to call any of this from Python? See Library API, including the individual pipeline stages underneath convert().