Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/docx/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ def add_picture(
image_path_or_stream: str | IO[bytes],
width: int | Length | None = None,
height: int | Length | None = None,
title: str | None = None,
descr: str | None = None,
):
"""Return new picture shape added in its own paragraph at end of the document.

Expand All @@ -133,9 +135,12 @@ def add_picture(
aspect ratio of the image. The native size of the picture is calculated using
the dots-per-inch (dpi) value specified in the image file, defaulting to 72 dpi
if no value is specified, as is often the case.

`title` sets the image's alternative-text title.
`descr` sets the alternative-text description shown in Word's Alt Text pane.
"""
run = self.add_paragraph().add_run()
return run.add_picture(image_path_or_stream, width, height)
return run.add_picture(image_path_or_stream, width, height, title, descr)

def add_section(self, start_type: WD_SECTION = WD_SECTION.NEW_PAGE):
"""Return a |Section| object newly added at the end of the document.
Expand Down
10 changes: 7 additions & 3 deletions src/docx/oxml/shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,29 +77,31 @@ class CT_Inline(BaseOxmlElement):
)

@classmethod
def new(cls, cx: Length, cy: Length, shape_id: int, pic: CT_Picture) -> CT_Inline:
def new(cls, cx: Length, cy: Length, shape_id: int, pic: CT_Picture, title=None, descr=None) -> CT_Inline:
"""Return a new ``<wp:inline>`` element populated with the values passed as
parameters."""
inline = cast(CT_Inline, parse_xml(cls._inline_xml()))
inline.extent.cx = cx
inline.extent.cy = cy
inline.docPr.id = shape_id
inline.docPr.name = "Picture %d" % shape_id
if title: inline.docPr.title = title
if descr: inline.docPr.descr = descr
inline.graphic.graphicData.uri = "http://schemas.openxmlformats.org/drawingml/2006/picture"
inline.graphic.graphicData._insert_pic(pic)
return inline

@classmethod
def new_pic_inline(
cls, shape_id: int, rId: str, filename: str, cx: Length, cy: Length
cls, shape_id: int, rId: str, filename: str, cx: Length, cy: Length, title=None, descr=None
) -> CT_Inline:
"""Create `wp:inline` element containing a `pic:pic` element.

The contents of the `pic:pic` element is taken from the argument values.
"""
pic_id = 0 # Word doesn't seem to use this, but does not omit it
pic = CT_Picture.new(pic_id, filename, rId, cx, cy)
inline = cls.new(cx, cy, shape_id, pic)
inline = cls.new(cx, cy, shape_id, pic, title=title, descr=descr)
return inline

@classmethod
Expand All @@ -126,6 +128,8 @@ class CT_NonVisualDrawingProps(BaseOxmlElement):

id = RequiredAttribute("id", ST_DrawingElementId)
name = RequiredAttribute("name", XsdString)
title = OptionalAttribute('title', XsdString)
descr = OptionalAttribute('descr', XsdString)


class CT_NonVisualPictureProperties(BaseOxmlElement):
Expand Down
4 changes: 3 additions & 1 deletion src/docx/parts/story.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ def new_pic_inline(
image_descriptor: str | IO[bytes],
width: int | Length | None = None,
height: int | Length | None = None,
title: str | None = None,
descr: str | None = None,
) -> CT_Inline:
"""Return a newly-created `w:inline` element.

Expand All @@ -71,7 +73,7 @@ def new_pic_inline(
rId, image = self.get_or_add_image(image_descriptor)
cx, cy = image.scaled_dimensions(width, height)
shape_id, filename = self.next_id, image.filename
return CT_Inline.new_pic_inline(shape_id, rId, filename, cx, cy)
return CT_Inline.new_pic_inline(shape_id, rId, filename, cx, cy, title, descr)

@property
def next_id(self) -> int:
Expand Down
39 changes: 39 additions & 0 deletions src/docx/shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,42 @@ def width(self):
def width(self, cx: Length):
self._inline.extent.cx = cx
self._inline.graphic.graphicData.pic.spPr.cx = cx

@property
def alt_text(self) -> str | None:
"""Read/write alternative-text description for this inline shape.

This corresponds to the 'Description' field in Word's Alt Text pane and is
stored on the ``wp:docPr`` ``descr`` attribute.
"""
docPr = self._inline.docPr
if docPr is None:
return None
return docPr.descr

@alt_text.setter
def alt_text(self, value: str | None) -> None:
docPr = self._inline.docPr
if docPr is None:
return
# Setting to empty/None clears the attribute.
docPr.descr = value if value else None

@property
def alt_title(self) -> str | None:
"""Read/write alternative-text title for this inline shape.

This corresponds to the 'Title' field in Word's Alt Text pane and is
stored on the ``wp:docPr`` ``title`` attribute.
"""
docPr = self._inline.docPr
if docPr is None:
return None
return docPr.title

@alt_title.setter
def alt_title(self, value: str | None) -> None:
docPr = self._inline.docPr
if docPr is None:
return
docPr.title = value if value else None
7 changes: 6 additions & 1 deletion src/docx/text/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ def add_picture(
image_path_or_stream: str | IO[bytes],
width: int | Length | None = None,
height: int | Length | None = None,
title: str | None = None,
descr: str | None = None,
) -> InlineShape:
"""Return |InlineShape| containing image identified by `image_path_or_stream`.

Expand All @@ -75,8 +77,11 @@ def add_picture(
ratio of the image. The native size of the picture is calculated using the dots-
per-inch (dpi) value specified in the image file, defaulting to 72 dpi if no
value is specified, as is often the case.

`title` sets the image's alternative-text title. `descr` sets the alternative-text
description shown in Word's Alt Text pane.
"""
inline = self.part.new_pic_inline(image_path_or_stream, width, height)
inline = self.part.new_pic_inline(image_path_or_stream, width, height, title, descr)
self._r.add_drawing(inline)
return InlineShape(inline)

Expand Down