from __future__ import annotations
import numpy as np
from .libs.pdf_to_image import convert_pdf_to_image, resize_image
from .libs.processing.align_images import get_alignment_data
def _prepare_alignment_images(
*,
scanned_logsheet_pdf: str,
template_pdf: str,
page: int,
dpi: int = 300,
):
"""Load scan and template pages and resize them to a common pixel size.
Args:
scanned_logsheet_pdf: Path to the scanned multi-page PDF.
template_pdf: Path to the template PDF for this side.
page: Zero-based page index in the scan PDF.
dpi: Rasterization resolution.
Returns:
Pair ``(logsheet_image, template_image)`` as ``numpy`` arrays (BGR).
"""
template_image = np.array(convert_pdf_to_image(template_pdf, dpi=dpi))
logsheet_image = np.array(convert_pdf_to_image(
scanned_logsheet_pdf, page=page, dpi=dpi))
height, width, _ = logsheet_image.shape
# Keep both images in the same resolution before corner detection.
logsheet_image = resize_image(logsheet_image, (width, height))
template_image = resize_image(template_image, (width, height))
return logsheet_image, template_image
[docs]
def get_page_alignment_data(
*,
scanned_logsheet_pdf: str,
template_pdf: str,
page: int = 0,
dpi: int = 300,
) -> dict:
"""Corners and image dimensions for automatic alignment of one scan page.
Args:
scanned_logsheet_pdf: Path to the scanned PDF.
template_pdf: Path to the template PDF.
page: Scan page index (``0`` = front, ``1`` = back when applicable).
dpi: Rasterization resolution.
Returns:
Dict with ``templatePoints``, ``targetPoints``, ``imageWidth``, ``imageHeight``
(JSON-friendly point dicts and integers).
"""
logsheet_image, template_image = _prepare_alignment_images(
scanned_logsheet_pdf=scanned_logsheet_pdf,
template_pdf=template_pdf,
page=page,
dpi=dpi,
)
alignment_data = get_alignment_data(logsheet_image, template_image)
height, width, _ = logsheet_image.shape
alignment_data["imageWidth"] = int(width)
alignment_data["imageHeight"] = int(height)
return alignment_data
[docs]
def build_alignment_payload(
*,
scanned_logsheet_pdf: str,
template_pdf: str,
backside_template_pdf: str | None = None,
dpi: int = 300,
) -> dict:
"""Build a payload with front (and optional back) alignment corner data.
Args:
scanned_logsheet_pdf: Path to the scanned PDF (at least two pages if back is used).
template_pdf: Front template PDF path.
backside_template_pdf: Optional back template PDF path.
dpi: Rasterization resolution.
Returns:
Dict with keys ``frontside`` (dict) and ``backside`` (dict or ``None``).
"""
frontside_alignment_data = get_page_alignment_data(
scanned_logsheet_pdf=scanned_logsheet_pdf,
template_pdf=template_pdf,
page=0,
dpi=dpi,
)
backside_alignment_data = None
if backside_template_pdf:
backside_alignment_data = get_page_alignment_data(
scanned_logsheet_pdf=scanned_logsheet_pdf,
template_pdf=backside_template_pdf,
page=1,
dpi=dpi,
)
return {
"frontside": frontside_alignment_data,
"backside": backside_alignment_data,
}