What is the best way to build a flow that inserts the last page between every page, regardless of how many pages the incoming PDF contains?
We often receive business cards as PDF files where the last page contains the back of the card, while the other pages contain the fronts with different people's contact details.
Insert last page between every page (1-A-2-A-3-A)
- magnussandstrom
- Advanced member
- Posts: 563
- Joined: Thu Jul 30, 2020 6:34 pm
- Location: Sweden
- Contact:
Re: Insert last page between every page (1-A-2-A-3-A)
Try this app, it can do that:
https://www0.enfocus.com/en/appstore/pr ... -pages-pro
https://www0.enfocus.com/en/appstore/pr ... -pages-pro
- magnussandstrom
- Advanced member
- Posts: 563
- Joined: Thu Jul 30, 2020 6:34 pm
- Location: Sweden
- Contact:
Re: Insert last page between every page (1-A-2-A-3-A)
I can solve it, but it’s not pretty. I’m wondering how others have solved it, I guess that it’s quite common.
- magnussandstrom
- Advanced member
- Posts: 563
- Joined: Thu Jul 30, 2020 6:34 pm
- Location: Sweden
- Contact:
Re: Insert last page between every page (1-A-2-A-3-A)
I ended upp building a small app using Python.
Code: Select all
import argparse
import os
import shutil
import sys
import tempfile
from pathlib import Path
import fitz # PyMuPDF
EXIT_SUCCESS = 0
EXIT_USAGE_ERROR = 1
EXIT_INPUT_ERROR = 2
EXIT_PROCESSING_ERROR = 3
def info(message: str) -> None:
"""Write normal status messages to stdout."""
print(message)
def error(message: str) -> None:
"""Write error messages to stderr."""
print(message, file=sys.stderr)
def validate_input_path(path: Path) -> None:
if not path.exists():
raise FileNotFoundError(f"Input file does not exist: {path}")
if not path.is_file():
raise ValueError(f"Input is not a file: {path}")
if path.suffix.lower() != ".pdf":
raise ValueError(f"Input file must be a PDF: {path}")
def interleave_last_page(input_pdf: Path, output_pdf: Path) -> None:
validate_input_path(input_pdf)
output_pdf.parent.mkdir(parents=True, exist_ok=True)
temp_path = None
try:
with fitz.open(str(input_pdf)) as src:
if src.page_count < 3:
raise ValueError("Input PDF must contain at least 3 pages.")
last_page_index = src.page_count - 1
expected_output_pages = (src.page_count - 1) * 2
with fitz.open() as out:
metadata = src.metadata or {}
if metadata:
try:
out.set_metadata(metadata)
except Exception:
pass
for i in range(last_page_index):
out.insert_pdf(src, from_page=i, to_page=i)
out.insert_pdf(src, from_page=last_page_index, to_page=last_page_index)
if out.page_count != expected_output_pages:
raise RuntimeError(
f"Internal error: output has {out.page_count} pages "
f"(expected {expected_output_pages})."
)
fd, temp_name = tempfile.mkstemp(
prefix=output_pdf.stem + "_",
suffix=".tmp.pdf",
dir=str(output_pdf.parent),
)
os.close(fd)
temp_path = Path(temp_name)
out.save(str(temp_path))
shutil.move(str(temp_path), str(output_pdf))
temp_path = None
# SUCCESS LOG → STDOUT
info(f"INPUT={input_pdf}")
info(f"INPUT_PAGES={last_page_index + 1}")
info(f"OUTPUT={output_pdf}")
info(f"OUTPUT_PAGES={expected_output_pages}")
info("STATUS=OK")
finally:
if temp_path is not None and temp_path.exists():
try:
temp_path.unlink()
except Exception:
pass
def parse_args(argv=None):
parser = argparse.ArgumentParser(
description="Insert the last page between all previous pages in a PDF."
)
parser.add_argument("input_pdf", help="Path to input PDF")
parser.add_argument("output_pdf", help="Path to output PDF")
return parser.parse_args(argv)
def main(argv=None) -> int:
try:
args = parse_args(argv)
input_pdf = Path(args.input_pdf)
output_pdf = Path(args.output_pdf)
interleave_last_page(input_pdf, output_pdf)
return EXIT_SUCCESS
except SystemExit:
raise
except (FileNotFoundError, ValueError) as e:
error(f"ERROR={e}")
return EXIT_INPUT_ERROR
except Exception as e:
error(f"ERROR={e}")
return EXIT_PROCESSING_ERROR
if __name__ == "__main__":
sys.exit(main())