- Demonter les pages : couper en 2 sans reordonner (sous Delivretiser) - Masquage visuel : selection au curseur sur l'apercu + plage de pages - Regles horizontale/verticale en mm (menu Affichage) - Fonds perdus : filigrane rouge pour visualiser les bleeds - Reperes de coupe : marques a l'exterieur (page agrandie), 2 traits/coin - Numerotation : couleur configurable via selecteur - Decalage : Trim & Shift renomme en francais, creep -> chasse - Recadrages multiples cumulatifs (plages differentes) - Fix spinbox format personnalise (fleches aleatoires) - Fix combo livret : option Automatique preservee Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
109 lines
4.1 KiB
Python
109 lines
4.1 KiB
Python
"""Moteur Reperes de coupe autonomes."""
|
|
|
|
from pypdf import PdfReader, PdfWriter, PageObject, Transformation
|
|
from reportlab.pdfgen import canvas
|
|
from .pdf_utils import get_page_size
|
|
import io
|
|
|
|
|
|
def add_crop_marks(input_path, output_path, mark_length=14.17, mark_offset=7.09,
|
|
line_width=0.25, color=(0, 0, 0), center_marks=False,
|
|
apply_to="all", current_page=0, **_kwargs):
|
|
"""Ajouter des reperes de coupe sur les pages.
|
|
|
|
Les marques sont placees a l'exterieur de la zone d'impression.
|
|
Chaque coin a 2 traits (1 horizontal + 1 vertical) formant un L.
|
|
La page est agrandie pour contenir les marques.
|
|
"""
|
|
reader = PdfReader(input_path)
|
|
writer = PdfWriter()
|
|
|
|
margin = mark_offset + mark_length
|
|
|
|
for i, page in enumerate(reader.pages):
|
|
page_num = i + 1
|
|
should_apply = False
|
|
if apply_to == "all":
|
|
should_apply = True
|
|
elif apply_to == "even":
|
|
should_apply = page_num % 2 == 0
|
|
elif apply_to == "odd":
|
|
should_apply = page_num % 2 != 0
|
|
elif apply_to == "current":
|
|
should_apply = i == current_page
|
|
|
|
if should_apply:
|
|
w, h = get_page_size(page)
|
|
# Canvas agrandi pour inclure les marques
|
|
cw = w + 2 * margin
|
|
ch = h + 2 * margin
|
|
|
|
packet = io.BytesIO()
|
|
c = canvas.Canvas(packet, pagesize=(cw, ch))
|
|
c.setLineWidth(line_width)
|
|
c.setStrokeColorRGB(*color)
|
|
|
|
# Les coordonnees de la zone d'impression dans le canvas agrandi
|
|
ox, oy = margin, margin # origine de la page originale
|
|
|
|
# 4 coins — 2 traits par coin (L exterieur)
|
|
# Bas-gauche
|
|
c.line(ox - mark_offset - mark_length, oy, ox - mark_offset, oy)
|
|
c.line(ox, oy - mark_offset - mark_length, ox, oy - mark_offset)
|
|
# Bas-droite
|
|
c.line(ox + w + mark_offset, oy, ox + w + mark_offset + mark_length, oy)
|
|
c.line(ox + w, oy - mark_offset - mark_length, ox + w, oy - mark_offset)
|
|
# Haut-gauche
|
|
c.line(ox - mark_offset - mark_length, oy + h, ox - mark_offset, oy + h)
|
|
c.line(ox, oy + h + mark_offset, ox, oy + h + mark_offset + mark_length)
|
|
# Haut-droite
|
|
c.line(ox + w + mark_offset, oy + h, ox + w + mark_offset + mark_length, oy + h)
|
|
c.line(ox + w, oy + h + mark_offset, ox + w, oy + h + mark_offset + mark_length)
|
|
|
|
# Reperes de centrage
|
|
if center_marks:
|
|
mid_x = ox + w / 2
|
|
mid_y = oy + h / 2
|
|
ml = mark_length * 0.7
|
|
# Haut
|
|
c.line(mid_x, oy + h + mark_offset, mid_x, oy + h + mark_offset + ml)
|
|
# Bas
|
|
c.line(mid_x, oy - mark_offset, mid_x, oy - mark_offset - ml)
|
|
# Gauche
|
|
c.line(ox - mark_offset, mid_y, ox - mark_offset - ml, mid_y)
|
|
# Droite
|
|
c.line(ox + w + mark_offset, mid_y, ox + w + mark_offset + ml, mid_y)
|
|
|
|
c.showPage()
|
|
c.save()
|
|
packet.seek(0)
|
|
overlay_reader = PdfReader(packet)
|
|
overlay_page = overlay_reader.pages[0]
|
|
|
|
# Creer une nouvelle page agrandie
|
|
new_page = PageObject.create_blank_page(width=cw, height=ch)
|
|
# Placer la page originale au centre (decalee de margin)
|
|
page.add_transformation(Transformation().translate(margin, margin))
|
|
new_page.merge_page(page)
|
|
# Ajouter les marques de coupe par-dessus
|
|
new_page.merge_page(overlay_page)
|
|
writer.add_page(new_page)
|
|
else:
|
|
writer.add_page(page)
|
|
|
|
with open(output_path, "wb") as f:
|
|
writer.write(f)
|
|
return output_path
|
|
|
|
|
|
def remove_crop_marks(input_path, output_path):
|
|
"""Enlever les reperes de coupe (remet mediabox = cropbox)."""
|
|
reader = PdfReader(input_path)
|
|
writer = PdfWriter()
|
|
for page in reader.pages:
|
|
page.cropbox = page.mediabox
|
|
writer.add_page(page)
|
|
with open(output_path, "wb") as f:
|
|
writer.write(f)
|
|
return output_path
|