Outil d'imposition PDF desktop (PyQt6) remplacant Quite Imposing Plus. 9 fonctions : livret, n-up, step & repeat, imposition manuelle, jointure pages, pages blanches, numerotation, masquage, fonds perdus. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
69 lines
2.1 KiB
Python
69 lines
2.1 KiB
Python
"""Moteur Imposition manuelle."""
|
|
|
|
from pypdf import PdfReader, PdfWriter, PageObject, Transformation
|
|
from .pdf_utils import get_page_size, create_crop_marks_page
|
|
|
|
|
|
def manual_impose(input_path, output_path, sheet_size, placements, crop_marks=False):
|
|
"""Imposition manuelle : placer des pages a des positions precises.
|
|
|
|
sheet_size: (largeur, hauteur) en points
|
|
placements: liste de dicts:
|
|
{"page": int (1-based), "x": float, "y": float, "scale": float, "rotation": int}
|
|
"""
|
|
reader = PdfReader(input_path)
|
|
pages = reader.pages
|
|
sheet_w, sheet_h = sheet_size
|
|
|
|
writer = PdfWriter()
|
|
sheet = PageObject.create_blank_page(width=sheet_w, height=sheet_h)
|
|
|
|
mark_positions = []
|
|
|
|
for p in placements:
|
|
page_idx = p["page"] - 1
|
|
if page_idx < 0 or page_idx >= len(pages):
|
|
continue
|
|
|
|
page = pages[page_idx]
|
|
page_w, page_h = get_page_size(page)
|
|
x = p.get("x", 0)
|
|
y = p.get("y", 0)
|
|
scale = p.get("scale", 1.0)
|
|
rotation = p.get("rotation", 0)
|
|
|
|
overlay = PageObject.create_blank_page(width=sheet_w, height=sheet_h)
|
|
overlay.merge_page(page)
|
|
|
|
transform = Transformation()
|
|
if rotation:
|
|
# Rotation autour du centre de la page
|
|
cx = page_w / 2
|
|
cy = page_h / 2
|
|
transform = transform.translate(-cx, -cy)
|
|
transform = transform.rotate(rotation)
|
|
transform = transform.translate(cx, cy)
|
|
transform = transform.scale(scale, scale).translate(x, y)
|
|
overlay.add_transformation(transform)
|
|
sheet.merge_page(overlay)
|
|
|
|
if crop_marks:
|
|
scaled_w = page_w * scale
|
|
scaled_h = page_h * scale
|
|
mark_positions.extend([
|
|
(x, y),
|
|
(x + scaled_w, y),
|
|
(x, y + scaled_h),
|
|
(x + scaled_w, y + scaled_h),
|
|
])
|
|
|
|
if crop_marks and mark_positions:
|
|
marks = create_crop_marks_page(sheet_w, sheet_h, mark_positions)
|
|
sheet.merge_page(marks)
|
|
|
|
writer.add_page(sheet)
|
|
|
|
with open(output_path, "wb") as f:
|
|
writer.write(f)
|
|
return output_path
|