Skip to content

Add InlineShape.image — extract the picture behind a shape #124

Closed

Description

@toxicphreAK

InlineShape exposes width, height, type and description (src/docx/shape.py:299). There is no way to get at the image itself.

Extracting the pictures from a document — the obvious counterpart to add_picture() — currently means walking document.part.rels by hand, filtering on reltype, and matching parts up to shapes yourself. The shape knows its r:embed; it just does not tell anyone.

>>> shape = document.inline_shapes[0]
>>> shape.image
AttributeError

python-pptx has had Picture.image returning an Image with .blob, .ext, .content_type, .size and .dpi for years, and the ImagePart / Image classes it needs already exist here — parts/image.py and image/image.py. This is plumbing, not new machinery.

Shape

>>> shape.image.blob            # bytes
>>> shape.image.content_type    # 'image/png'
>>> shape.image.ext, shape.image.dpi, shape.image.size

for shape in document.inline_shapes:
    if shape.type == WD_INLINE_SHAPE.PICTURE:
        Path(f"{shape.image.sha1}.{shape.image.ext}").write_bytes(shape.image.blob)
  • InlineShape.image → the ImagePart's image, resolved through the r:embed on the shape's a:blip and the story part's relationships
  • The same on FloatingShape (Support floating (anchored) images with text wrapping #85), which has the identical structure under wp:anchor
  • Document.images or similar as the collection-level convenience, if it falls out cleanly

Watch out for

  • shape.type can be LINKED_PICTURE, where the blip carries r:link rather than r:embed and the bytes are not in the package at all. Return |None| or raise something specific; do not let it fail with a KeyError on the relationship lookup.
  • A shape can be a chart, a SmartArt diagram or an embedded object rather than a picture. WD_INLINE_SHAPE.NOT_IMPLEMENTED already exists for those; .image should be |None| there rather than guessing.
  • An SVG picture (2.0.0) has two blips — the SVG in an asvg:svgBlip extension and a raster fallback in the ordinary a:blip. Decide which .image returns; returning the fallback and adding .svg_image for the other is probably right, since the fallback is what every consumer can actually decode.
  • Several shapes can share one image part. Do not assume a one-to-one mapping when building any collection view.

Upstream: "feature: InlineShape.image ?", and the recurring "how do I extract the images from a docx".

Activity

  1. toxicphreAK commented on Aug 5, 2026

    @toxicphreAK
    OwnerAuthor

    Landed in #139. InlineShape.image, FloatingShape.image, .svg_image and Document.images. Each case the issue flagged is handled: a linked picture, a chart or SmartArt, and a shape with no part behind it all give None rather than a KeyError; .image returns the raster fallback of an SVG and .svg_image the vector source; several shapes sharing one image part give one entry in Document.images.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions