Skip to content

arnepluhar/pdf2pdfa

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pdf2pdfa

Konvertiert gescannte PDF-Dateien zu PDF/A-2b (ISO 19005-2) mit deutscher OCR und MRC-Kompression.

Enthaltene Scripts

Script Zweck
pdf2pdfa.py MRC-Kompression + PDF/A-2b Konvertierung (Hauptscript)
analyze_pdfs.py PDF-Analyse: Seiten, DPI, Farbmodus, OCR-Status, PDF/A-Version
cleanup_pdfs.py Paperless-ngx inspirierte Bereinigung: Deskew, Hintergrund-Entfernung, Re-OCR

Funktionen

  • PDF/A-2b – Langzeitarchivierungsformat nach ISO 19005-2
  • Deutsche OCR – Texterkennung mit Tesseract (Sprache: Deutsch)
  • MRC-Kompression (Mixed Raster Content)
    • Text-Maske: 300 DPI, JBIG2 verlustfrei (5–10× besser als JPEG)
    • Hintergrund: 150 DPI, JPEG Q40 (kompakte Farben/Logos)
    • 4x Upscaling vor Sauvola-Binarisierung für glatte Textkanten
  • QR-Code-sicher – JBIG2 verlustfrei erhält QR-Codes exakt
  • Batch-Verarbeitung – Einzeldateien, Glob-Muster oder ganze Ordner
  • Fortschrittsanzeige[1/5] datei.pdf
  • Fehlerprotokoll – optionale Logdatei
  • Statistik – Dateigröße vorher/nachher, Einsparung in %

Voraussetzungen

macOS (Homebrew)

brew install ocrmypdf poppler jbig2enc imagemagick
pip install pikepdf pillow numpy

Das installiert:

  • ocrmypdf (v17+) – OCR + PDF/A Metadaten
  • jbig2enc – JBIG2-Encoder für verlustfreie S/W-Kompression
  • poppler – pdftoppm für Seiten-Rendering
  • imagemagick – convert für Bildverarbeitung
  • tesseract – OCR-Engine (via ocrmypdf)

Deutsche Sprachdaten prüfen:

tesseract --list-langs | grep deu

Falls deu fehlt:

brew install tesseract-lang

Optional (für --thinning):

pip install scikit-image

Linux (Debian/Ubuntu)

sudo apt install ocrmypdf tesseract-ocr-deu jbig2enc poppler-utils imagemagick
pip install pikepdf pillow numpy

Python

Python 3.10+ wird benötigt.

Installation

git clone https://github.com/arnepluhar/pdf2pdfa.git
cd pdf2pdfa
pip install pikepdf pillow numpy

Optional: Script global verfügbar machen:

chmod +x pdf2pdfa.py
ln -s "$(pwd)/pdf2pdfa.py" /usr/local/bin/pdf2pdfa

Verwendung

Einzelne Datei

python pdf2pdfa.py scan.pdf
# Ausgabe: scan.pdf → pdfa/scan.pdf

Mehrere Dateien

python pdf2pdfa.py *.pdf
python pdf2pdfa.py rechnung.pdf vertrag.pdf brief.pdf

Ganzer Ordner

python pdf2pdfa.py /Dokumente/Scans/
# Konvertiert alle *.pdf im Ordner → /Dokumente/Scans/pdfa/

Ausgabe-Ordner anpassen

# Relativer Unterordner (wird neben der Quelldatei angelegt)
python pdf2pdfa.py *.pdf --output-dir archiv

# Absoluter Pfad
python pdf2pdfa.py /Scans/ --output-dir /Archiv/pdfa

Text-Schärfe anpassen

# Dünnere Textstriche (bei zu fettem Text)
python pdf2pdfa.py scan.pdf --sauvola-k 0.15

# Dickere Textstriche (bei zu dünnem Text)
python pdf2pdfa.py scan.pdf --sauvola-k 0.25

Kontrast verbessern

# CLAHE für blasse Scans oder vergilbtes Papier
python pdf2pdfa.py scan.pdf --clahe

Fehlerprotokoll

python pdf2pdfa.py /Scans/ --log konvertierung.log

Ausführliche Ausgabe

python pdf2pdfa.py scan.pdf --verbose

Optionen

Option Standard Beschreibung
PDF ... PDF-Datei(en) oder Verzeichnis
--output-dir ORDNER pdfa Ausgabe-Unterordner (relativ oder absolut)
--bg-quality 1-100 40 JPEG-Qualität für Farb-Hintergrund
--bg-dpi 50-300 150 DPI für Farb-Hintergrund
--window-size N 25 Fenstergröße für Sauvola-Binarisierung
--sauvola-k K 0.18 Sauvola k-Faktor (0.15-0.25, niedriger = dünnere Striche)
--erosion N 0 Erosions-Iterationen (0-2)
--clahe aus CLAHE-Kontrastverbesserung
--thinning N 0 Zhang-Suen Thinning (0-3, benötigt scikit-image)
--log DATEI Fehlerprotokoll in Datei schreiben
--verbose, -v Ausführliche Debug-Ausgabe

Beispielausgabe

2026-07-15 10:23:01 [INFO] pdf2pdfa - PDF → PDF/A-2b Konverter (MRC-Modus)
2026-07-15 10:23:01 [INFO] Ausgabe-Ordner: pdfa | Hintergrund: 150 DPI, Q40 | Sauvola: window=25, k=0.18
2026-07-15 10:23:01 [INFO] Gefunden: 3 PDF-Datei(en)
2026-07-15 10:23:01 [INFO] [1/3] brief.pdf
2026-07-15 10:23:01 [INFO] Konvertiere: brief.pdf → pdfa/brief.pdf
2026-07-15 10:23:08 [INFO]   OK  7.2s | 4.2 MB → 0.5 MB (88.1% kleiner)
...
2026-07-15 10:23:45 [INFO] ============================================================
2026-07-15 10:23:45 [INFO] STATISTIK
2026-07-15 10:23:45 [INFO] ============================================================
2026-07-15 10:23:45 [INFO] Gesamt:        3 Datei(en)
2026-07-15 10:23:45 [INFO] Erfolgreich:   3
2026-07-15 10:23:45 [INFO] Größe vorher:  12.6 MB
2026-07-15 10:23:45 [INFO] Größe nachher: 1.5 MB
2026-07-15 10:23:45 [INFO] Einsparung:    88.1%
2026-07-15 10:23:45 [INFO] Gesamtdauer:   44.3s
2026-07-15 10:23:45 [INFO] ============================================================

Technische Details

MRC-Kompressionsstrategie

Mixed Raster Content (MRC) trennt jede Seite in zwei Ebenen:

Ebene Auflösung Kompression Inhalt
Text-Maske 300 DPI (4x upscaled) JBIG2 verlustfrei S/W-Text, QR-Codes
Hintergrund 150 DPI JPEG Q40 Farben, Logos, Fotos

Warum MRC?

  • ~85-90% Dateigröße-Reduktion (vs. ~50% ohne MRC)
  • Gestochen scharfer Text bei 300 DPI
  • Kompakter Hintergrund ohne sichtbare Artefakte

Sauvola-Binarisierung

Die Text-Maske wird mit adaptiver Sauvola-Schwellwertbildung erstellt:

  1. Graustufenbild 4x upscalen (300 → 1200 DPI äquivalent)
  2. Sauvola-Algorithmus mit lokalem Fenster (25×4 = 100 px)
  3. Binärmaske zurück auf 300 DPI skalieren (Majority Voting)
  4. JBIG2 verlustfrei komprimieren

Der --sauvola-k Parameter steuert die Empfindlichkeit:

  • Niedriger (0.10-0.15): Dünnere Striche, mehr Details
  • Standard (0.18): Ausgewogen
  • Höher (0.20-0.25): Dickere Striche, weniger Rauschen

Dokumente mit vorhandenem OCR-Text

Falls ein PDF bereits OCR-Text enthält, wird automatisch auf skip_text=True zurückgegriffen: Das Dokument wird trotzdem zu PDF/A-2b konvertiert und komprimiert, aber nicht erneut per OCR verarbeitet.

Ausgabe-Ordner-Logik

  • Relativer Pfad (z. B. pdfa): Wird als Unterordner neben jeder Quelldatei angelegt
  • Absoluter Pfad (z. B. /Archiv/pdfa): Alle Ausgabedateien landen in diesem Ordner

Architektur-Entscheidungen

Siehe docs/adr-001-tool-choice.md für die vollständige Begründung der Tool-Wahl.

Lizenz

MIT – siehe LICENSE


analyze_pdfs.py

Analysiert PDFs und zeigt eine Übersichtstabelle mit:

  • Seitenzahl, Dateigröße, DPI
  • Farbmodus (Farbe/Graustufen)
  • OCR-Status
  • PDF/A-Version (1a, 1b, 2a, 2b, 3a, 3b)

Verwendung

python analyze_pdfs.py /Pfad/zu/PDFs/

# JSON-Export
python analyze_pdfs.py /Pfad/zu/PDFs/ --json analyse.json

Beispielausgabe

============================================================================
Filename                                      Pages     Size     DPI      Color  OCR    PDF/A Images
============================================================================
2024-01-15 - Rechnung.pdf                         1    54 KB     300      color    ✓ PDF/A-2b      2
2024-02-20 - Vertrag.pdf                          4   320 KB     300  grayscale    ✓ PDF/A-2b     11
============================================================================

Summary: 2 PDFs, 5 pages, 374 KB total
OCR: 2/2, PDF/A: 2/2, Grayscale: 1/2

cleanup_pdfs.py

Paperless-ngx inspirierte Bereinigung für bereits vorhandene PDFs. Ideal für:

  • Verbesserung der OCR-Qualität (Deutsch)
  • Konvertierung zu PDF/A-2b
  • Deskew (schiefe Scans begradigen)
  • Hintergrund-Entfernung (durchscheinende Rückseiten)

Modi

Modus Beschreibung Dateigröße
--redo-ocr (Standard) Ersetzt nur OCR-Layer, behält Bilder ≈ gleich
--force-ocr Rendert PDF komplett neu (ermöglicht --deskew) größer
--skip-ocr Nur PDF/A-2b Konvertierung variabel

Verwendung

# Standard: Nur OCR verbessern + PDF/A-2b
python cleanup_pdfs.py /Pfad/zu/PDFs/ -o ausgabe/

# Mit Deskew (benötigt --force-ocr)
python cleanup_pdfs.py /Pfad/zu/PDFs/ -o ausgabe/ --force-ocr

# Volle Pipeline: Unpaper + Hintergrund-Entfernung
python cleanup_pdfs.py /Pfad/zu/PDFs/ -o ausgabe/ --full-pipeline --unpaper --remove-background

# Einzeldatei
python cleanup_pdfs.py dokument.pdf -o ausgabe/

Optionen

Option Beschreibung
-o, --output Ausgabe-Ordner (Standard: ./cleaned)
--force-ocr PDF komplett neu rendern (langsamer, größere Dateien)
--skip-ocr Nur PDF/A-2b, kein OCR
--unpaper Unpaper für Deskew/Cleanup (langsam, gut für alte Scans)
--remove-background Hintergrund/Durchscheinen entfernen
--grayscale In Graustufen konvertieren
-l, --language OCR-Sprache (Standard: deu+eng)
-j, --workers Parallele Verarbeitung
--overwrite Vorhandene Dateien überschreiben

Hinweise

  • --redo-ocr ist nicht kompatibel mit --deskew, --clean-final, --remove-background
  • Für Deskew muss --force-ocr verwendet werden (rendert das PDF neu)
  • --full-pipeline wird automatisch aktiviert bei --unpaper oder --remove-background

About

PDF/A-2b-Script

Resources

License

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages