feat(scan): support iX1600 duplex scanning on Linux
This commit is contained in:
74
agents/fedeo-device-agent/scripts/scan_document.py
Normal file
74
agents/fedeo-device-agent/scripts/scan_document.py
Normal file
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Assemble ordered scanner pages; OpenCV is optional, PDF creation is not."""
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def create_document(inputs, output, resolution, use_postprocess=False, profile="document", strict=False):
|
||||
if not inputs:
|
||||
raise ValueError("Keine Seiten vorhanden")
|
||||
output = Path(output)
|
||||
file_format = {".pdf": "PDF", ".png": "PNG", ".tiff": "TIFF"}.get(output.suffix.lower())
|
||||
if not file_format:
|
||||
raise ValueError("Unbekanntes Ausgabeformat")
|
||||
if file_format != "PDF" and len(inputs) != 1:
|
||||
raise ValueError("Mehrseitige Scans benötigen PDF als Ausgabeformat")
|
||||
|
||||
warnings = []
|
||||
processor = None
|
||||
if use_postprocess:
|
||||
try:
|
||||
from opencv_postprocess import postprocess
|
||||
processor = postprocess
|
||||
except ImportError:
|
||||
if strict:
|
||||
raise
|
||||
warnings.append("OpenCV fehlt; alle Seiten wurden ohne Bildkorrektur übernommen.")
|
||||
|
||||
partial = output.with_name(output.name + ".partial")
|
||||
try:
|
||||
for index, input_path in enumerate(inputs):
|
||||
input_path = Path(input_path)
|
||||
image_path = input_path
|
||||
corrected = input_path.with_name(input_path.stem + ".corrected.png")
|
||||
if processor:
|
||||
try:
|
||||
processor(input_path, corrected, profile)
|
||||
image_path = corrected
|
||||
except Exception:
|
||||
if strict:
|
||||
raise
|
||||
warnings.append(f"Seite {index + 1}: Bildkorrektur fehlgeschlagen; Rohscan übernommen.")
|
||||
|
||||
# Only one decoded page is kept in memory, even for large duplex stacks.
|
||||
with Image.open(image_path) as image:
|
||||
with image.convert("RGB") as rgb:
|
||||
if file_format == "PDF":
|
||||
rgb.save(partial, "PDF", resolution=resolution, quality=90, append=index > 0)
|
||||
else:
|
||||
rgb.save(partial, file_format, dpi=(resolution, resolution))
|
||||
corrected.unlink(missing_ok=True)
|
||||
partial.replace(output)
|
||||
finally:
|
||||
partial.unlink(missing_ok=True)
|
||||
|
||||
return {"pageCount": len(inputs), "warnings": warnings}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Scan-Seiten zu einer Datei zusammenführen")
|
||||
parser.add_argument("--inputs", nargs="+", required=True)
|
||||
parser.add_argument("--output", required=True)
|
||||
parser.add_argument("--resolution", type=float, required=True)
|
||||
parser.add_argument("--profile", choices=["document", "receipt", "raw"], default="document")
|
||||
parser.add_argument("--postprocess", action="store_true")
|
||||
parser.add_argument("--strict", action="store_true")
|
||||
args = parser.parse_args()
|
||||
print(json.dumps(create_document(args.inputs, args.output, args.resolution, args.postprocess, args.profile, args.strict)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user