| """Split a PDF into two contiguous halves by page (PyMuPDF)."""
|
| from __future__ import annotations
|
|
|
| from dataclasses import dataclass
|
|
|
|
|
| @dataclass(frozen=True)
|
| class PdfSplitMeta:
|
| page_range_a: str
|
| page_range_b: str
|
| total_pages: int
|
|
|
|
|
| def split_pdf_two_halves(src_path: str, dest_a: str, dest_b: str) -> tuple[PdfSplitMeta | None, str]:
|
| """
|
| First half = pages 1 .. floor(n/2), second half = rest (at least one page each requires n >= 2).
|
| Returns (meta, "") on success or (None, error_message).
|
| """
|
| try:
|
| import fitz
|
| except ImportError:
|
| return None, "PyMuPDF (fitz) is not installed."
|
|
|
| doc = None
|
| try:
|
| doc = fitz.open(src_path)
|
| n = len(doc)
|
| if n < 2:
|
| return None, "This PDF has only one page; split requires at least two pages. Try compressing or splitting the file manually."
|
|
|
| mid = n // 2
|
| out_a = fitz.open()
|
| try:
|
| out_a.insert_pdf(doc, from_page=0, to_page=mid - 1)
|
| out_a.save(dest_a)
|
| finally:
|
| out_a.close()
|
|
|
| out_b = fitz.open()
|
| try:
|
| out_b.insert_pdf(doc, from_page=mid, to_page=n - 1)
|
| out_b.save(dest_b)
|
| finally:
|
| out_b.close()
|
|
|
| meta = PdfSplitMeta(
|
| page_range_a=f"1-{mid}",
|
| page_range_b=f"{mid + 1}-{n}",
|
| total_pages=n,
|
| )
|
| return meta, ""
|
| except Exception as e:
|
| return None, f"PDF split failed: {e}"
|
| finally:
|
| if doc is not None:
|
| try:
|
| doc.close()
|
| except Exception:
|
| pass
|
|
|