Skip to content

Instantly share code, notes, and snippets.

@whimo
Last active October 22, 2024 10:41
Show Gist options
  • Select an option

  • Save whimo/7e073b1bb54207bbd90afa374e1d3c4a to your computer and use it in GitHub Desktop.

Select an option

Save whimo/7e073b1bb54207bbd90afa374e1d3c4a to your computer and use it in GitHub Desktop.
python-pptx demo
"""
Download https://gist.github.com/user-attachments/assets/e39a1aeb-4d69-4913-8dcf-ce936de2669d to pebble.jpg for the demo to work.
"""
from PIL import Image
from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.util import Inches, Pt
def add_title_slide(prs, title_text, subtitle_text):
title_slide_layout = prs.slide_layouts[0]
slide = prs.slides.add_slide(title_slide_layout)
title = slide.shapes.title
subtitle = slide.placeholders[1]
title.text = title_text
subtitle.text = subtitle_text
def add_bullet_slide(prs, title_text, main_text, bullet_points):
bullet_slide_layout = prs.slide_layouts[1]
slide = prs.slides.add_slide(bullet_slide_layout)
shapes = slide.shapes
title_shape = shapes.title
body_shape = shapes.placeholders[1]
title_shape.text = title_text
tf = body_shape.text_frame
tf.text = main_text
for point in bullet_points:
p = tf.add_paragraph()
p.text = point
p.level = 1
def add_image_with_text_slide(prs, img_path, text):
blank_slide_layout = prs.slide_layouts[6]
slide = prs.slides.add_slide(blank_slide_layout)
# Open the image and get its size
with Image.open(img_path) as img:
img_width, img_height = img.size
# Calculate the scaling factor to fit the image within half of the slide width
slide_width = prs.slide_width
slide_height = prs.slide_height
width_ratio = (slide_width / 2) / img_width
height_ratio = slide_height / img_height
scale_factor = min(width_ratio, height_ratio)
# Calculate new dimensions
new_width = int(img_width * scale_factor)
new_height = int(img_height * scale_factor)
# Calculate position to left-align the image
left = Inches(0.5)
top = (slide_height - new_height) / 2
# Add the resized picture to the left side of the slide
slide.shapes.add_picture(img_path, left, top, width=new_width, height=new_height)
# Add a textbox for the text on the right side
text_left = left + new_width + Inches(0.5)
text_width = slide_width - text_left - Inches(0.5)
text_top = Inches(1)
text_height = slide_height - Inches(2)
textbox = slide.shapes.add_textbox(text_left, text_top, text_width, text_height)
text_frame = textbox.text_frame
text_frame.word_wrap = True
p = text_frame.add_paragraph()
p.text = text
p.font.size = Pt(14)
def add_two_column_slide(prs, title, left_content, right_content):
two_column_slide_layout = prs.slide_layouts[3]
slide = prs.slides.add_slide(two_column_slide_layout)
title_shape = slide.shapes.title
title_shape.text = title
left_shape = slide.placeholders[1]
left_shape.text = left_content
right_shape = slide.placeholders[2]
right_shape.text = right_content
def add_text_on_image_slide(prs, img_path, text, font_size=40, font_color=(255, 255, 255)):
blank_slide_layout = prs.slide_layouts[6]
slide = prs.slides.add_slide(blank_slide_layout)
# Open and crop the image to fit the slide
with Image.open(img_path) as img:
# Calculate the aspect ratios
img_aspect = img.width / img.height
slide_aspect = prs.slide_width / prs.slide_height
if img_aspect > slide_aspect:
# Image is wider, crop the sides
new_width = int(img.height * slide_aspect)
offset = (img.width - new_width) // 2
img = img.crop((offset, 0, offset + new_width, img.height))
else:
# Image is taller, crop the top and bottom
new_height = int(img.width / slide_aspect)
offset = (img.height - new_height) // 2
img = img.crop((0, offset, img.width, offset + new_height))
# Save the cropped image temporarily
temp_img_path = "temp_cropped_image.png"
img.save(temp_img_path)
# Add the cropped image to cover the entire slide
left = top = Inches(0)
width = prs.slide_width
height = prs.slide_height
slide.shapes.add_picture(temp_img_path, left, top, width, height)
# Add a textbox
left = Inches(1)
top = Inches(2)
width = prs.slide_width - Inches(2)
height = Inches(1)
txBox = slide.shapes.add_textbox(left, top, width, height)
# Set the text and its properties
tf = txBox.text_frame
tf.text = text
tf.paragraphs[0].alignment = 1 # Center align the text
p = tf.paragraphs[0]
p.font.size = Pt(font_size)
p.font.color.rgb = RGBColor(*font_color)
# Clean up the temporary file
import os
os.remove(temp_img_path)
def create_presentation():
# Create a new presentation
prs = Presentation()
# Add a title slide
add_title_slide(prs, "Welcome to My Presentation", "Created with python-pptx")
# Add a content slide
add_bullet_slide(
prs, "Agenda", "This is the agenda:", ["First major topic", "Second major topic"]
)
# Add a slide with an image
add_image_with_text_slide(prs, "pebble.jpg", "Image with text")
# Add a two-column slide
add_two_column_slide(prs, "Two Column Layout", "Left column content", "Right column content")
# Add a slide with text on a background image
add_text_on_image_slide(prs, "pebble.jpg", "Text on Background Image")
# Save the presentation
prs.save("example_presentation.pptx")
if __name__ == "__main__":
create_presentation()
print("Presentation created successfully!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment