MatteoScript's picture
Upload 6 files
7687049 verified
"""Post-processing PDF (pip-only).
Obiettivo:
- rimuovere pagine *visivamente* vuote (tipicamente solo footer/logo e numero pagina)
che possono comparire in template DOCX complessi dopo la conversione.
Implementazione:
- usa PyMuPDF (fitz) per rasterizzare ogni pagina a bassa risoluzione
- calcola la frazione di pixel "quasi bianchi" e il numero di pixel non bianchi
- se la pagina è "troppo bianca" e con pochissimi pixel scuri => considerata vuota
- crea un nuovo PDF senza quelle pagine.
Nota:
La soglia è tarata per il caso tipico "pagina bianca con solo numero pagina".
"""
from __future__ import annotations
from pathlib import Path
from typing import List
def remove_blank_pages_pdf(
pdf_path: Path,
*,
zoom: float = 0.35,
white_thr: int = 245,
white_frac_thr: float = 0.995,
max_nonwhite_pixels: int = 3500,
) -> int:
"""Rimuove pagine visivamente vuote da un PDF.
Ritorna il numero di pagine rimosse.
"""
import fitz # PyMuPDF
import numpy as np
pdf_path = Path(pdf_path)
doc = fitz.open(str(pdf_path))
if doc.page_count == 0:
return 0
keep: List[int] = []
for i in range(doc.page_count):
page = doc.load_page(i)
pix = page.get_pixmap(matrix=fitz.Matrix(zoom, zoom), alpha=False)
img = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, 3)
white = np.all(img >= white_thr, axis=2)
white_frac = float(white.mean())
nonwhite = int((~white).sum())
# Se è molto bianca e con pochissimi pixel non bianchi => pagina vuota
if not (white_frac >= white_frac_thr and nonwhite <= max_nonwhite_pixels):
keep.append(i)
removed = doc.page_count - len(keep)
if removed <= 0:
doc.close()
return 0
new_doc = fitz.open()
new_doc.insert_pdf(doc, from_page=min(keep), to_page=max(keep), start_at=0)
# insert_pdf sopra copia range continuo: per keep non contiguo bisogna copiare singole pagine
if len(keep) != (max(keep) - min(keep) + 1):
new_doc = fitz.open()
for i in keep:
new_doc.insert_pdf(doc, from_page=i, to_page=i)
doc.close()
tmp = pdf_path.with_suffix(".tmp.pdf")
new_doc.save(str(tmp))
new_doc.close()
tmp.replace(pdf_path)
return removed