diff --git a/songs/anytime-anywhere/AnytimeAnywhere.pptx b/songs/anytime-anywhere/AnytimeAnywhere.pptx new file mode 100644 index 0000000..835b8b2 Binary files /dev/null and b/songs/anytime-anywhere/AnytimeAnywhere.pptx differ diff --git a/songs/anytime-anywhere/AnytimeAnywhereFlowchart.pptx b/songs/anytime-anywhere/AnytimeAnywhereFlowchart.pptx new file mode 100644 index 0000000..e8e1492 Binary files /dev/null and b/songs/anytime-anywhere/AnytimeAnywhereFlowchart.pptx differ diff --git a/songs/anytime-anywhere/anytime_anywhere.py b/songs/anytime-anywhere/anytime_anywhere.py new file mode 100644 index 0000000..6174f25 --- /dev/null +++ b/songs/anytime-anywhere/anytime_anywhere.py @@ -0,0 +1,111 @@ +from pptx import Presentation +from pptx.util import Inches, Pt +from pptx.dml.color import RGBColor +from pptx.enum.text import PP_ALIGN + +OUT_PATH = r"C:\Users\jhodgkin\Documents\dev\primary-song-slides\songs\anytime-anywhere\AnytimeAnywhere.pptx" + +SLIDE_W = Inches(13.333) +SLIDE_H = Inches(7.5) + +# Calm, prayerful palette: deep twilight blue background, soft gold accents +TWILIGHT = RGBColor(0x1C, 0x2E, 0x4A) +GOLD = RGBColor(0xE8, 0xC5, 0x6A) +WHITE = RGBColor(0xFF, 0xFF, 0xFF) + +TITLE = "Anytime, Anywhere" + +VERSES = [ + ( + "Verse 1", + "I can pray to my Heav'nly Father\n" + "Anytime, anywhere.\n" + "For He always cares,\n" + "And He hears my prayers—\n" + "Anytime, anywhere." + ), + ( + "Verse 2", + "I can listen for heav'nly guidance\n" + "Anytime, anywhere.\n" + "The Spirit will guide\n" + "As I seek His light—\n" + "Anytime, anywhere." + ), +] + + +def set_background_color(slide, color): + fill = slide.background.fill + fill.solid() + fill.fore_color.rgb = color + + +def add_gold_rule(slide, top): + rule = slide.shapes.add_shape( + 1, # rectangle + Inches(1.5), top, SLIDE_W - Inches(3.0), Inches(0.06) + ) + rule.fill.solid() + rule.fill.fore_color.rgb = GOLD + rule.line.fill.background() + + +def add_slide(prs, blank_layout, verse_label, verse_text): + slide = prs.slides.add_slide(blank_layout) + set_background_color(slide, TWILIGHT) + + add_gold_rule(slide, Inches(0.55)) + + # Song title + title_box = slide.shapes.add_textbox(Inches(0.5), Inches(0.65), SLIDE_W - Inches(1.0), Inches(0.85)) + p = title_box.text_frame.paragraphs[0] + p.alignment = PP_ALIGN.CENTER + run = p.add_run() + run.text = TITLE + run.font.size = Pt(36) + run.font.color.rgb = GOLD + run.font.bold = True + + # Verse label + label_box = slide.shapes.add_textbox(Inches(0.5), Inches(1.45), SLIDE_W - Inches(1.0), Inches(0.5)) + p2 = label_box.text_frame.paragraphs[0] + p2.alignment = PP_ALIGN.CENTER + run2 = p2.add_run() + run2.text = verse_label + run2.font.size = Pt(22) + run2.font.color.rgb = WHITE + run2.font.italic = True + + add_gold_rule(slide, Inches(1.95)) + + # Verse lyrics + lyric_box = slide.shapes.add_textbox(Inches(0.5), Inches(2.3), SLIDE_W - Inches(1.0), Inches(4.8)) + tf = lyric_box.text_frame + tf.word_wrap = True + for i, line in enumerate(verse_text.split("\n")): + 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.size = Pt(40) + run.font.color.rgb = WHITE + + print(f" Added: {verse_label}") + + +def main(): + prs = Presentation() + prs.slide_width = SLIDE_W + prs.slide_height = SLIDE_H + blank_layout = prs.slide_layouts[6] + + for label, text in VERSES: + add_slide(prs, blank_layout, label, text) + + prs.save(OUT_PATH) + print(f"\nSaved: {OUT_PATH} ({len(VERSES)} slides)") + + +if __name__ == "__main__": + main() diff --git a/songs/anytime-anywhere/anytime_anywhere_flowchart.py b/songs/anytime-anywhere/anytime_anywhere_flowchart.py new file mode 100644 index 0000000..0bd88ae --- /dev/null +++ b/songs/anytime-anywhere/anytime_anywhere_flowchart.py @@ -0,0 +1,138 @@ +from pptx import Presentation +from pptx.util import Inches, Pt +from pptx.dml.color import RGBColor +from pptx.enum.text import PP_ALIGN, MSO_ANCHOR +from pptx.enum.shapes import MSO_SHAPE + +OUT_PATH = r"C:\Users\jhodgkin\Documents\dev\primary-song-slides\songs\anytime-anywhere\AnytimeAnywhereFlowchart.pptx" + +SLIDE_W = Inches(13.333) +SLIDE_H = Inches(7.5) + +TWILIGHT = RGBColor(0x1C, 0x2E, 0x4A) +GOLD = RGBColor(0xE8, 0xC5, 0x6A) +WHITE = RGBColor(0xFF, 0xFF, 0xFF) + +TITLE = "Anytime, Anywhere" + +# Flow: A -> R, then R <-> B loop (R -> B -> back to R) +# The refrain box R appears once; both other lines feed into it. +BOX_R = "Anytime,\nanywhere" + +# (verse label, box A text, box B text) +VERSES = [ + ("Verse 1", + "I can pray to my\nHeav'nly Father", + "For He always cares,\nand He hears my prayers"), + ("Verse 2", + "I can listen for\nheav'nly guidance", + "The Spirit will guide\nas I seek His light"), +] + + +def add_box(slide, left, top, w, h, text, is_refrain): + box = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, left, top, w, h) + box.fill.solid() + box.fill.fore_color.rgb = GOLD if is_refrain else WHITE + box.line.color.rgb = GOLD + box.line.width = Pt(2.5) + + tf = box.text_frame + tf.word_wrap = True + tf.vertical_anchor = MSO_ANCHOR.MIDDLE + for i, line in enumerate(text.split("\n")): + 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.size = Pt(28) + run.font.bold = True + run.font.color.rgb = TWILIGHT + return box + + +def add_arrow(slide, shape_type, left, top, w, h): + arrow = slide.shapes.add_shape(shape_type, left, top, w, h) + arrow.fill.solid() + arrow.fill.fore_color.rgb = GOLD + arrow.line.fill.background() + return arrow + + +def add_flow_slide(prs, verse_label, box_a, box_b): + slide = prs.slides.add_slide(prs.slide_layouts[6]) + + fill = slide.background.fill + fill.solid() + fill.fore_color.rgb = TWILIGHT + + # Title + title_box = slide.shapes.add_textbox(Inches(0.5), Inches(0.35), SLIDE_W - Inches(1.0), Inches(0.9)) + p = title_box.text_frame.paragraphs[0] + p.alignment = PP_ALIGN.CENTER + run = p.add_run() + run.text = TITLE + run.font.size = Pt(40) + run.font.color.rgb = GOLD + run.font.bold = True + + # Verse label under the title + label_box = slide.shapes.add_textbox(Inches(0.5), Inches(1.05), SLIDE_W - Inches(1.0), Inches(0.45)) + p2 = label_box.text_frame.paragraphs[0] + p2.alignment = PP_ALIGN.CENTER + run2 = p2.add_run() + run2.text = verse_label + run2.font.size = Pt(20) + run2.font.color.rgb = WHITE + run2.font.italic = True + + # Layout: A on top of the left column, R below it, B to the right of R. + # A flows down into R; R and B loop (R -> B on top, B -> R underneath). + box_w = Inches(4.8) + gap_x = Inches(1.7) + left_x = (SLIDE_W - (box_w * 2 + gap_x)) / 2 + right_x = left_x + box_w + gap_x + + a_y = Inches(1.7) + a_h = Inches(1.6) + r_y = Inches(4.3) + r_h = Inches(1.9) + + add_box(slide, left_x, a_y, box_w, a_h, box_a, False) + add_box(slide, left_x, r_y, box_w, r_h, BOX_R, True) + add_box(slide, right_x, r_y, box_w, r_h, box_b, False) + + # A -> R: down arrow + arrow_w = Inches(0.7) + arrow_l = Inches(0.85) + gap_y = r_y - (a_y + a_h) + add_arrow(slide, MSO_SHAPE.DOWN_ARROW, + left_x + (box_w - arrow_w) / 2, + a_y + a_h + (gap_y - arrow_l) / 2, + arrow_w, arrow_l) + + # R <-> B loop: right arrow above, left arrow below + loop_arrow_w = Inches(1.3) + loop_x = left_x + box_w + (gap_x - loop_arrow_w) / 2 + add_arrow(slide, MSO_SHAPE.RIGHT_ARROW, + loop_x, r_y + r_h * 0.22 - arrow_w / 2, loop_arrow_w, arrow_w) + add_arrow(slide, MSO_SHAPE.LEFT_ARROW, + loop_x, r_y + r_h * 0.78 - arrow_w / 2, loop_arrow_w, arrow_w) + + print(f" Added: {verse_label}") + + +def main(): + prs = Presentation() + prs.slide_width = SLIDE_W + prs.slide_height = SLIDE_H + + for verse_label, box_a, box_b in VERSES: + add_flow_slide(prs, verse_label, box_a, box_b) + + prs.save(OUT_PATH) + print(f"\nSaved: {OUT_PATH} ({len(VERSES)} slides)") + + +if __name__ == "__main__": + main() diff --git a/songs/pray-in-faith/PrayInFaith.pdf b/songs/pray-in-faith/PrayInFaith.pdf new file mode 100644 index 0000000..7b5a99f Binary files /dev/null and b/songs/pray-in-faith/PrayInFaith.pdf differ diff --git a/songs/pray-in-faith/PrayInFaith.pptx b/songs/pray-in-faith/PrayInFaith.pptx new file mode 100644 index 0000000..7cffe58 Binary files /dev/null and b/songs/pray-in-faith/PrayInFaith.pptx differ diff --git a/songs/pray-in-faith/pray_in_faith.py b/songs/pray-in-faith/pray_in_faith.py new file mode 100644 index 0000000..1a4b514 --- /dev/null +++ b/songs/pray-in-faith/pray_in_faith.py @@ -0,0 +1,39 @@ +import fitz +from pptx import Presentation +from pptx.util import Inches +import io +import os + +HERE = os.path.dirname(os.path.abspath(__file__)) +PDF_PATH = os.path.join(HERE, "PrayInFaith.pdf") +OUT_PATH = os.path.join(HERE, "PrayInFaith.pptx") +DPI = 150 + +SLIDE_W = Inches(13.333) # widescreen landscape +SLIDE_H = Inches(7.5) + +doc = fitz.open(PDF_PATH) +prs = Presentation() +prs.slide_width = SLIDE_W +prs.slide_height = SLIDE_H +blank_layout = prs.slide_layouts[6] + +for i, page in enumerate(doc, start=1): + mat = fitz.Matrix(DPI / 72, DPI / 72) + pix = page.get_pixmap(matrix=mat, alpha=False) + img = io.BytesIO(pix.tobytes("png")) + + slide = prs.slides.add_slide(blank_layout) + aspect = pix.width / pix.height + 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, left, top, width=w, height=h) + print(f" Slide: page {i}") + +prs.save(OUT_PATH) +print(f"\nSaved: {OUT_PATH}") diff --git a/songs/search-ponder-and-pray/SearchPonderAndPray.pptx b/songs/search-ponder-and-pray/SearchPonderAndPray.pptx new file mode 100644 index 0000000..7f0b35a Binary files /dev/null and b/songs/search-ponder-and-pray/SearchPonderAndPray.pptx differ diff --git a/songs/search-ponder-and-pray/SearchPonderandPrayWithLyrics.pdf b/songs/search-ponder-and-pray/SearchPonderandPrayWithLyrics.pdf new file mode 100644 index 0000000..126ec91 Binary files /dev/null and b/songs/search-ponder-and-pray/SearchPonderandPrayWithLyrics.pdf differ diff --git a/songs/search-ponder-and-pray/search_ponder_and_pray.py b/songs/search-ponder-and-pray/search_ponder_and_pray.py new file mode 100644 index 0000000..9e1ad23 --- /dev/null +++ b/songs/search-ponder-and-pray/search_ponder_and_pray.py @@ -0,0 +1,54 @@ +import fitz +from pptx import Presentation +from pptx.util import Inches +import io + +PDF_PATH = r"C:\Users\jhodgkin\Documents\dev\primary-song-slides\songs\search-ponder-and-pray\SearchPonderandPrayWithLyrics.pdf" +OUT_PATH = r"C:\Users\jhodgkin\Documents\dev\primary-song-slides\songs\search-ponder-and-pray\SearchPonderAndPray.pptx" +DPI = 96 + +SLIDE_W = Inches(13.333) +SLIDE_H = Inches(7.5) + + +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): + 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) + + print(f" Slide {len(prs.slides):2d} (pg {page_idx+1:2d})") + + +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] + + # Lyrics are embedded in the artwork, so every page is one slide + for page_idx in range(len(doc)): + add_slide(doc, prs, blank_layout, page_idx) + + prs.save(OUT_PATH) + print(f"\nSaved: {OUT_PATH} ({len(doc)} slides)") + + +if __name__ == "__main__": + main()