# Python PPTX 5 Image And Shape Manipulation

> Sub-skill of python-pptx: 5. Image and Shape Manipulation.

- Skill: `vamseeachanta/python-pptx-5-image-and-shape-manipulation` (Agent Skill)
- Install (CLI): `npx skillmds@latest add vamseeachanta/python-pptx-5-image-and-shape-manipulation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/vamseeachanta/python-pptx-5-image-and-shape-manipulation/raw
- Safety review: PASS (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: vamseeachanta (https://skillmd.com/u/vamseeachanta)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/vamseeachanta/python-pptx-5-image-and-shape-manipulation

---


# 5. Image and Shape Manipulation

## 5. Image and Shape Manipulation


```python
"""
Add and manipulate images and shapes in presentations.
"""
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.enum.shapes import MSO_SHAPE, MSO_CONNECTOR
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.dml.color import RgbColor
from pathlib import Path
from io import BytesIO
from typing import Tuple

def add_image_with_border(
    slide,
    image_path: str,
    left: float,
    top: float,
    width: float = None,
    height: float = None
) -> None:
    """Add image with optional border effect."""
    if Path(image_path).exists():
        pic = slide.shapes.add_picture(
            image_path,
            Inches(left), Inches(top),
            Inches(width) if width else None,
            Inches(height) if height else None
        )
        # Add line border
        pic.line.color.rgb = RgbColor(0, 0, 0)
        pic.line.width = Pt(1)


def create_arrow_connector(
    slide,
    start: Tuple[float, float],
    end: Tuple[float, float],
    color: str = "4472C4"
) -> None:
    """Create an arrow connector between two points."""
    connector = slide.shapes.add_connector(
        MSO_CONNECTOR.STRAIGHT,
        Inches(start[0]), Inches(start[1]),
        Inches(end[0]), Inches(end[1])
    )

    connector.line.color.rgb = RgbColor(
        int(color[0:2], 16),
        int(color[2:4], 16),
        int(color[4:6], 16)
    )
    connector.line.width = Pt(2)


def create_shape_presentation(output_path: str) -> None:
    """Create presentation with shapes and connectors."""
    prs = Presentation()

    # Slide 1: Process Flow with Shapes
    slide = prs.slides.add_slide(prs.slide_layouts[6])  # Blank

    # Add title
    title_box = slide.shapes.add_textbox(
        Inches(0.5), Inches(0.3),
        Inches(12), Inches(0.8)
    )
    tf = title_box.text_frame
    p = tf.paragraphs[0]
    p.text = "Development Process Flow"
    p.font.size = Pt(32)
    p.font.bold = True
    p.alignment = PP_ALIGN.CENTER

    # Process steps
    steps = [
        ("Requirements", "4472C4"),
        ("Design", "70AD47"),
        ("Development", "ED7D31"),
        ("Testing", "5B9BD5"),
        ("Deployment", "7030A0"),
    ]

    y_pos = 2.5
    x_positions = [1, 3.5, 6, 8.5, 11]

    for i, (step, color) in enumerate(steps):
        # Add shape
        shape = slide.shapes.add_shape(
            MSO_SHAPE.ROUNDED_RECTANGLE,
            Inches(x_positions[i]), Inches(y_pos),
            Inches(2), Inches(1)
        )

        shape.fill.solid()
        shape.fill.fore_color.rgb = RgbColor(
            int(color[0:2], 16),
            int(color[2:4], 16),
            int(color[4:6], 16)
        )

        # Add text
        tf = shape.text_frame
        p = tf.paragraphs[0]
        p.text = step
        p.font.color.rgb = RgbColor(255, 255, 255)
        p.font.bold = True
        p.font.size = Pt(14)
        p.alignment = PP_ALIGN.CENTER
        shape.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER

        # Add arrow to next step
        if i < len(steps) - 1:
            arrow = slide.shapes.add_shape(
                MSO_SHAPE.RIGHT_ARROW,
                Inches(x_positions[i] + 2.1), Inches(y_pos + 0.35),
                Inches(0.3), Inches(0.3)
            )
            arrow.fill.solid()
            arrow.fill.fore_color.rgb = RgbColor(128, 128, 128)

    # Slide 2: Organization Chart Style
    slide = prs.slides.add_slide(prs.slide_layouts[6])

    title_box = slide.shapes.add_textbox(
        Inches(0.5), Inches(0.3),
        Inches(12), Inches(0.8)
    )
    tf = title_box.text_frame
    p = tf.paragraphs[0]
    p.text = "Team Structure"
    p.font.size = Pt(32)
    p.font.bold = True
    p.alignment = PP_ALIGN.CENTER

    # CEO box
    ceo = slide.shapes.add_shape(
        MSO_SHAPE.RECTANGLE,
        Inches(5.5), Inches(1.5),
        Inches(2.5), Inches(1)
    )
    ceo.fill.solid()
    ceo.fill.fore_color.rgb = RgbColor(0x2F, 0x54, 0x96)
    ceo.text = "CEO\nJohn Smith"
    for para in ceo.text_frame.paragraphs:
        para.font.color.rgb = RgbColor(255, 255, 255)
        para.font.size = Pt(12)
        para.alignment = PP_ALIGN.CENTER

    # Department heads
    departments = [
        ("Engineering\nAlice Chen", 1.5),
        ("Marketing\nBob Wilson", 4.5),
        ("Sales\nCarol Davis", 7.5),
        ("Operations\nDave Brown", 10.5),
    ]

    for name, x_pos in departments:
        box = slide.shapes.add_shape(
            MSO_SHAPE.RECTANGLE,
            Inches(x_pos), Inches(3.5),
            Inches(2.5), Inches(1)
        )
        box.fill.solid()
        box.fill.fore_color.rgb = RgbColor(0x5B, 0x9B, 0xD5)
        box.text = name
        for para in box.text_frame.paragraphs:
            para.font.color.rgb = RgbColor(255, 255, 255)
            para.font.size = Pt(11)
            para.alignment = PP_ALIGN.CENTER

    # Slide 3: Callout Shapes
    slide = prs.slides.add_slide(prs.slide_layouts[6])

    title_box = slide.shapes.add_textbox(
        Inches(0.5), Inches(0.3),
        Inches(12), Inches(0.8)
    )
    tf = title_box.text_frame
    p = tf.paragraphs[0]
    p.text = "Key Callouts"
    p.font.size = Pt(32)
    p.font.bold = True
    p.alignment = PP_ALIGN.CENTER

*Content truncated — see parent skill for full reference.*

