import fitz from pptx import Presentation from pptx.util import Inches, Pt from pptx.dml.color import RGBColor from pptx.enum.text import PP_ALIGN import io PDF_PATH = r"C:\Users\jhodgkin\Documents\dev\primary-song-slides\MyFlagMyFlag-Color.pdf" OUT_PATH = r"C:\Users\jhodgkin\Documents\dev\primary-song-slides\MyFlagMyFlag.pptx" DPI = 96 SLIDE_W = Inches(13.333) SLIDE_H = Inches(7.5) TEXT_BOX_H = Inches(2.1) FONT_SIZE = Pt(44) TEXT_COLOR = RGBColor(0x0D, 0x27, 0x6D) # deep navy blue # PDF pages 1-8 (0-based) map to the 8 lyric lines # Page 0 is the overview thumbnail sheet — skip it SLIDES = [ (1, "My flag, my flag, my country's flag,"), (2, "I love to see you wave;"), (3, "My flag, my flag, my country's flag,"), (4, "The banner of the brave."), (5, "Wave on, wave on forever,"), (6, "The banner of the free;"), (7, "Wave on, wave on forever,"), (8, "The flag of liberty."), ] def render_page(page): mat = fitz.Matrix(DPI / 72, DPI / 72) pix = page.get_pixmap(matrix=mat, alpha=False) return io.BytesIO(pix.tobytes("jpeg", jpg_quality=85)), pix.width, pix.height def add_slide(doc, prs, blank_layout, page_idx, lyric): page = doc[page_idx] img_bytes, pw, ph = render_page(page) slide = prs.slides.add_slide(blank_layout) aspect = pw / ph h = SLIDE_H w = int(h * aspect) if w > SLIDE_W: w = SLIDE_W h = int(w / aspect) left = (SLIDE_W - w) // 2 top = (SLIDE_H - h) // 2 slide.shapes.add_picture(img_bytes, left, top, width=w, height=h) tb_top = SLIDE_H - TEXT_BOX_H txBox = slide.shapes.add_textbox(Inches(0.25), tb_top, SLIDE_W - Inches(0.5), TEXT_BOX_H) tf = txBox.text_frame tf.word_wrap = True lines = lyric.split("\n") for i, line in enumerate(lines): p = tf.paragraphs[0] if i == 0 else tf.add_paragraph() p.alignment = PP_ALIGN.CENTER run = p.add_run() run.text = line run.font.bold = True run.font.size = FONT_SIZE run.font.color.rgb = TEXT_COLOR print(f" Slide {len(prs.slides):2d} (pg {page_idx+1:2d}): {lyric[:60]}") def main(): doc = fitz.open(PDF_PATH) prs = Presentation() prs.slide_width = SLIDE_W prs.slide_height = SLIDE_H blank_layout = prs.slide_layouts[6] for page_idx, lyric in SLIDES: add_slide(doc, prs, blank_layout, page_idx, lyric) prs.save(OUT_PATH) print(f"\nSaved: {OUT_PATH} ({len(SLIDES)} slides)") if __name__ == "__main__": main()