diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/slidepacker | 99 |
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() |
