← 返回首页
Add basic support for adding SVG pictures to docx files #1343 by takis · Pull Request #1386 · python-openxml/python-docx · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus

Add basic support for adding SVG pictures to docx files #1343 #1386

Closed
takis wants to merge 0 commit into
python-openxml:masterfrom
takis:master
Closed

Add basic support for adding SVG pictures to docx files #1343 #1386
takis wants to merge 0 commit into
python-openxml:masterfrom
takis:master

Conversation

Copy link
Copy Markdown

takis commented May 2, 2024

Copy link
Copy Markdown

Hello, Is there a target date for this code to be committed to the master ?

I really need this implementation.

Thanks for the awesome software.

Copy link
Copy Markdown
Author

takis commented Jun 21, 2024

Hi @marcuoli,

No, unfortunately not.

I do try to keep my fork in sync with the main repository.

Copy link
Copy Markdown

pank commented Oct 17, 2024

I hope this patch will be merged soon.

I'm trying to use your patch, but it doesn't appear to work with matplotlib figures since their sizes are in pt rather than pixels.

Example:

import docx from docx.shared import Inches import numpy as np import matplotlib.pyplot as plt from io import BytesIO from tempfile import mktemp x = np.linspace(-2*np.pi, 2*np.pi, 100) fig, ax = plt.subplots() ax.plot(x, np.sin(x), color="C0") ax.plot(x, np.cos(x), color="C1") buf = BytesIO() fig.savefig(buf, format="svg") w, h = (Inches(s) for s in fig.get_size_inches()) p = mktemp(suffix=".svg") fig.savefig(p) # doesn't work doc = docx.Document() doc.add_picture(buf, w, h)

Traceback:

File c:\Users\rpr\.conda\envs\funandgames\Lib\site-packages\docx\image\svg.py:43, in Svg._dimensions_from_stream(cls, stream) 40 root = ET.fromstring(data) 41 # FIXME: The width could be expressed as '4cm' 42 # See https://www.w3.org/TR/SVG11/struct.html#NewDocument ---> 43 width = int(root.attrib["width"]) 44 height = int(root.attrib["height"]) 45 return width, height

I think a pt is 1.33x a pixel in svgs. If so, it might be easy to at least handle pt. But maybe it depends on dpi?
For matplotlib at least, I think dpi is fixed at 72 (e.g. here)

An example of an mpl svg is attached.

Copy link
Copy Markdown

pank commented Oct 18, 2024

With this patch I can insert mpl figures. It's written rather verbose, as I don't really know the style of python-docx.
@takis would you consider adding this patch or something similar?

From 458df2e57c57be410e6d2486ae67e44cebbd177e Mon Sep 17 00:00:00 2001 From: Rasmus <git@pank.eu> Date: Fri, 18 Oct 2024 10:02:49 +0200 Subject: [PATCH] svg: Handle non-pixels units --- src/docx/image/svg.py | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/docx/image/svg.py b/src/docx/image/svg.py index 0247a77..4be43e1 100644 --- a/src/docx/image/svg.py +++ b/src/docx/image/svg.py @@ -33,13 +33,37 @@ class Svg(BaseImageHeader): """ return "svg" + @classmethod + def _dimension_to_px(cls, s): + """Convert SVG unit *s* to pixels. + + Based on the `table`_ on absolute length in W3 CSS Values 3. + + .. table: https://www.w3.org/TR/css-values-3/#absolute-lengths + """ + s = str(s) + unit = s.lstrip("0123456789.").casefold() + snumber = s[:-len(unit)] if len(unit) > 0 else s + number = float(snumber) + inch = 96 + cm = inch/2.54 + units = {"cm": cm, + "mm": cm/10, + "q": cm/40, # 'Q' in W3 table + "in": inch, + "pc": inch/6, + "pt": inch/72, + "px": 1} + # Unitless is pixels + number_px = number * units.get(unit, 1) + return int(number_px) + @classmethod def _dimensions_from_stream(cls, stream): stream.seek(0) data = stream.read() root = ET.fromstring(data) - # FIXME: The width could be expressed as '4cm' - # See https://www.w3.org/TR/SVG11/struct.html#NewDocument - width = int(root.attrib["width"]) - height = int(root.attrib["height"]) + # The width could be expressed as '4cm' + width = cls._dimension_to_px(root.attrib["width"]) + height = cls._dimension_to_px(root.attrib["height"]) return width, height -- 2.44.0.windows.1 ```

Copy link
Copy Markdown

lsaint left a comment
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

This PR broke a unitest which need to add xmlns:asvg="http://schemas.microsoft.com/office/drawing/2016/SVG/main
to
tests/test_files/snippets/inline.txt.

some of svg files without "width" and "height" not supported yet.
eg:
<svg viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Icons_CheckboxCrossed" overflow="hidden"><path d="M37.076 62.948 48.008 52.201 58.939 62.948 63.146 58.67 52.286 47.994 63.146 37.318 58.939 33.04 48.008 43.787 37.076 33.04 32.87 37.318 43.729 47.994 32.87 58.67 37.076 62.948Z"/><path d="M21 21 21 75 75 75 75 21ZM69 69 27 69 27 27 69 27Z"/></svg>

I have fixed them and added some unittests in my private fork

Copy link
Copy Markdown

  • Thanks to @pank 's patch, that solved the pt to px issue, now matplotlib svg images can be added, however, it only seems to work sometimes, as some other times I get a placeholder of the image instead. I attach the .svg's at the end if it is helpful.
  • The exact same thing occurs when using @lsaint 's fork (that does not solve the pt issue afaik, but supports emf images) with the same images but converted to emf via inkscape
  • Copypasting the svg files into the document works well so I think the images itself are not corrupted or something

Original svg images used





Copy link
Copy Markdown

pank commented Jul 4, 2025
edited
Loading

@sgtyfianalisisfinanciero
Could you share the MPL code of something that doesn't work? Then I will be happy to see if I can reproduce it.

AI've written an package that hotpatches python-docx to support svgs based on this thread that I use for work until svg support is merged. Would that be interesting for others?

Copy link
Copy Markdown

@pank nervermind, the problem was not with the images or the mpl code that generated it. Trying to elaborate a minimal reproducible example I catched the issue

My workflow was something like that:

  • Paste images in some table cells (works)
  • Generate some other (totally independent) tables, saving the partial document after each table generation for debugging purposes
  • Paste some other images in some table cells (placeholder shown)

Removing the saving step solves the issue. I'm clueless about why, but it's fine

On the other hand I think your hotfix package would be very interesting for a lot of people. While this get merged, everyone who needed that feature could just uv add git+... your fork, which is nicer than hardcoding your patch (which can easily get hard to find in the conversation) into the .venv folder.

Copy link
Copy Markdown

How it goes?

Copy link
Copy Markdown

ecciv commented Aug 7, 2025

This is a really important feature, what are the steps needed prior to a merge? @takis, @lsaint, @scanny

Copy link
Copy Markdown

pank commented Aug 8, 2025

@sgtyfianalisisfinanciero sorry about the delay. I wanted to add tests and read through the code, but didn't manage before my going on vacation. I still haven't managed, but have added the hotpatch package here:

https://github.com/pank/python-docx-svg

I haven't added it to PyPi, but could do so if that would be useful. It can still be installed via pip.

Copy link
Copy Markdown

And more news on this? It seems like the patch has addressed the issue, but is still waiting to be merged?

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

Footer

© 2026 GitHub, Inc.