File size: 2,325 Bytes
7687049
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
"""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