aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/slidepacker99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/slidepacker b/src/slidepacker
new file mode 100755
index 0000000..d129d17
--- /dev/null
+++ b/src/slidepacker
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+
+# slidepacker - convert pdf presentations into a "fake" pptx
+# (each page is rendered as an image and pasted onto a blank slide)
+
+import argparse
+import io
+import os
+import sys
+
+import fitz # this is actually pymupdf
+from pptx import Presentation
+from pptx.util import Emu
+
+
+# core conversion
+def pack(pdf_path, output_path=None, dpi=150):
+ """convert a pdf to a pptx where each slide is a rendered page image.
+
+ args:
+ pdf_path: path to the input pdf
+ output_path: path for the output pptx (default: same stem as pdf)
+ dpi: render resolution (default: 150)
+
+ returns:
+ the output path as a string
+ """
+ if output_path is None:
+ base = os.path.splitext(pdf_path)[0]
+ output_path = base + ".pptx"
+
+ doc = fitz.open(pdf_path)
+ prs = Presentation()
+
+ # match slide dimensions to the first page
+ # fitz uses points (1pt = 1/72 inch), pptx uses emu (914400 emu/inch)
+ if len(doc) > 0:
+ rect = doc[0].rect
+ prs.slide_width = Emu(int(rect.width / 72 * 914400))
+ prs.slide_height = Emu(int(rect.height / 72 * 914400))
+
+ blank_layout = prs.slide_layouts[6] # blank slide - no placeholders
+ mat = fitz.Matrix(dpi / 72, dpi / 72)
+
+ for page in doc:
+ pix = page.get_pixmap(matrix=mat)
+ img_stream = io.BytesIO(pix.tobytes("png"))
+
+ slide = prs.slides.add_slide(blank_layout)
+ slide.shapes.add_picture(
+ img_stream,
+ left=Emu(0),
+ top=Emu(0),
+ width=prs.slide_width,
+ height=prs.slide_height,
+ )
+
+ prs.save(output_path)
+ doc.close()
+ return output_path
+
+
+# cli
+
+def main():
+ parser = argparse.ArgumentParser(
+ prog="slidepacker",
+ description="convert a pdf presentation into a fake pptx",
+ )
+ parser.add_argument("pdf", help="input pdf file")
+ parser.add_argument(
+ "output",
+ nargs="?",
+ default=None,
+ help="output pptx file (default: same stem as input pdf)",
+ )
+ parser.add_argument(
+ "--dpi",
+ type=int,
+ default=150,
+ metavar="N",
+ help="render resolution in dpi (default: 150)",
+ )
+ args = parser.parse_args()
+
+ if not os.path.isfile(args.pdf):
+ print(f"[!] error: file not found: {args.pdf}", file=sys.stderr)
+ sys.exit(1)
+
+ if not args.pdf.lower().endswith(".pdf"):
+ print(f"[!] error: not a pdf file: {args.pdf}", file=sys.stderr)
+ sys.exit(1)
+
+ result = pack(args.pdf, args.output, dpi=args.dpi)
+ print(f"[+] saved: {result}")
+
+
+if __name__ == "__main__":
+ main()