feat(ci): jede Seite durchstempeln, Bestand nachgestempelt (1.2.0)
This commit is contained in:
1 parent
6858c92865
commit
ad5a3f0c6a
3 files changed
+98
-11
No files matched your search
@@ -24,6 +24,7 @@ Danach `display_file` auf die AUSGABE, nie auf das Original.
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import datetime
|
||||
import io
|
||||
import sys
|
||||
import textwrap
|
||||
@@ -47,6 +48,10 @@ ROT = "#c1121f"
|
||||
STEEL = "#3a4250"
|
||||
MUTED = "#8a94a2"
|
||||
|
||||
# Autor ist immer Kalina (Beschluss 23.10.2026): Copyright-Vermerk auf jeder Seite.
|
||||
JAHR = datetime.date.today().year
|
||||
COPYRIGHT = f"© {JAHR} kalina.si"
|
||||
|
||||
FONT = FontProperties(family="DejaVu Sans")
|
||||
FONT_BOLD = FontProperties(family="DejaVu Sans", weight="bold") # Black (900) fehlt in DejaVu
|
||||
TRACKING = 0.06 # Buchstabenabstand der Wortmarke, in Vielfachen der Schriftgröße
|
||||
@@ -131,11 +136,16 @@ def kopfbogen(breite: float, hoehe: float, rechts_text: str) -> PdfReader:
|
||||
return _als_reader(fig)
|
||||
|
||||
|
||||
def fussbogen(breite: float, hoehe: float, fuss_text: str) -> PdfReader:
|
||||
"""Transparente Seite mit Fußlinie + Fußtext (überdeckt nur den unteren Rand)."""
|
||||
def fussbogen(breite: float, hoehe: float, fuss_text: str, hintergrund: str = BONE) -> PdfReader:
|
||||
"""Seite mit Fußlinie + Fußtext. Das Band wird zuerst in der Seitenfarbe gefüllt,
|
||||
damit ein alter Fuß (z. B. „ai.m-m.bio") nicht unter dem neuen durchscheint."""
|
||||
fig, ax = _figur(breite, hoehe)
|
||||
band = plt.Rectangle((RAND_L - 1.5 * MM, FUSS_LINIE - 7.0 * MM),
|
||||
breite - RAND_L - RAND_R + 3.0 * MM, 8.4 * MM,
|
||||
facecolor=hintergrund, edgecolor="none", zorder=2)
|
||||
ax.add_patch(band)
|
||||
ax.plot([RAND_L, breite - RAND_R], [FUSS_LINIE, FUSS_LINIE], color=STEEL, linewidth=0.6, zorder=3)
|
||||
ax.text(RAND_L, FUSS_LINIE - 4.4 * MM, "KALINA · ai.m-m.bio", fontsize=6.5, color=MUTED,
|
||||
ax.text(RAND_L, FUSS_LINIE - 4.4 * MM, "KALINA · " + COPYRIGHT, fontsize=6.5, color=MUTED,
|
||||
fontproperties=FONT, ha="left", va="baseline", zorder=4)
|
||||
if fuss_text:
|
||||
ax.text(breite / 2, FUSS_LINIE - 4.4 * MM, fuss_text, fontsize=6.5, color=MUTED,
|
||||
@@ -170,7 +180,7 @@ def deckblatt(breite: float, hoehe: float, titel: str, untertitel: str, fuss_tex
|
||||
y -= 7.5 * MM
|
||||
|
||||
ax.plot([RAND_L, breite - RAND_R], [FUSS_LINIE, FUSS_LINIE], color=STEEL, linewidth=0.6, zorder=3)
|
||||
ax.text(RAND_L, FUSS_LINIE - 4.4 * MM, "KALINA · ai.m-m.bio", fontsize=6.5, color=MUTED,
|
||||
ax.text(RAND_L, FUSS_LINIE - 4.4 * MM, "KALINA · " + COPYRIGHT, fontsize=6.5, color=MUTED,
|
||||
fontproperties=FONT, ha="left", va="baseline", zorder=4)
|
||||
if fuss_text:
|
||||
ax.text(breite - RAND_R, FUSS_LINIE - 4.4 * MM, fuss_text, fontsize=6.5, color=MUTED,
|
||||
@@ -178,6 +188,43 @@ def deckblatt(breite: float, hoehe: float, titel: str, untertitel: str, fuss_tex
|
||||
return _als_reader(fig)
|
||||
|
||||
|
||||
def _bandfarben(quelle: Path, anzahl: int) -> list[str]:
|
||||
"""Haeufigste Farbe im Fussband je Seite - der Seitenhintergrund.
|
||||
|
||||
Ohne Messung wuerde ein helles Band auf dunklen Dokumenten (z. B. Ink-Seiten der CI)
|
||||
als weisser Streifen stehen.
|
||||
"""
|
||||
try:
|
||||
import pymupdf # type: ignore
|
||||
except ImportError:
|
||||
try:
|
||||
import fitz as pymupdf # type: ignore
|
||||
except ImportError:
|
||||
return [BONE] * anzahl
|
||||
farben: list[str] = []
|
||||
dok = pymupdf.open(str(quelle))
|
||||
for i in range(anzahl):
|
||||
if i >= dok.page_count:
|
||||
farben.append(BONE)
|
||||
continue
|
||||
seite = dok[i]
|
||||
h = seite.rect.height
|
||||
clip = pymupdf.Rect(RAND_L, FUSS_LINIE - 5 * MM, seite.rect.width - RAND_R, FUSS_LINIE - 1 * MM)
|
||||
try:
|
||||
pix = seite.get_pixmap(clip=clip, dpi=72)
|
||||
zaehler: dict[tuple, int] = {}
|
||||
for y in range(pix.height):
|
||||
for x in range(pix.width):
|
||||
px = pix.pixel(x, y)[:3]
|
||||
zaehler[px] = zaehler.get(px, 0) + 1
|
||||
farbe = max(zaehler.items(), key=lambda kv: kv[1])[0]
|
||||
farben.append("#%02x%02x%02x" % farbe)
|
||||
except Exception:
|
||||
farben.append(BONE)
|
||||
dok.close()
|
||||
return farben
|
||||
|
||||
|
||||
def verarbeiten(quelle: Path, ziel: Path, *, titel: str, untertitel: str, fuss: str,
|
||||
mit_deckblatt: bool, mit_fuss: bool, mit_kopf: bool) -> dict:
|
||||
leser = PdfReader(str(quelle))
|
||||
@@ -186,6 +233,7 @@ def verarbeiten(quelle: Path, ziel: Path, *, titel: str, untertitel: str, fuss:
|
||||
if breite < 100 or hoehe < 100:
|
||||
raise SystemExit(f"FEHLER: unerwartetes Seitenformat {breite:.0f}×{hoehe:.0f} pt")
|
||||
|
||||
hintergruende = _bandfarben(quelle, len(leser.pages)) if mit_fuss else []
|
||||
schreiber = PdfWriter()
|
||||
seiten = 0
|
||||
if mit_deckblatt:
|
||||
@@ -194,7 +242,8 @@ def verarbeiten(quelle: Path, ziel: Path, *, titel: str, untertitel: str, fuss:
|
||||
if abs(float(seite.mediabox.width) - breite) > 1 or abs(float(seite.mediabox.height) - hoehe) > 1:
|
||||
seite.scale_to(breite, hoehe)
|
||||
if mit_fuss:
|
||||
seite.merge_page(fussbogen(breite, hoehe, fuss).pages[0])
|
||||
farbe = hintergruende[i] if i < len(hintergruende) else BONE
|
||||
seite.merge_page(fussbogen(breite, hoehe, fuss, farbe).pages[0])
|
||||
if mit_kopf and i == 0:
|
||||
seite.merge_page(kopfbogen(breite, hoehe, "KALINA" if not fuss else fuss.upper()).pages[0])
|
||||
schreiber.add_page(seite)
|
||||
|
||||
Reference in new issue
Block a user