Last active
October 22, 2024 10:41
-
-
Save whimo/7e073b1bb54207bbd90afa374e1d3c4a to your computer and use it in GitHub Desktop.
python-pptx demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| 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