Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic support for adding SVG pictures to docx files #1107

Closed
wants to merge 0 commits into from

Conversation

takis
Copy link

@takis takis commented Jun 24, 2022

See issues #351, #651, #659.

@takis
Copy link
Author

takis commented Jun 24, 2022

This is the simple code I've been testing with:

import datetime

from docx import Document


SVG = """<svg version="1.1"
     width="300" height="200"
     xmlns="http://www.w3.org/2000/svg">

  <rect width="100%" height="100%" fill="red" />
  <circle cx="150" cy="100" r="80" fill="green" />
  <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
</svg>
"""
svg_filename = "drawing.svg"
with open(svg_filename, "w") as f:
    f.write(SVG)

document = Document()
now = datetime.datetime.now()
document.add_heading("Document Title", 0)
document.add_heading(f"{now}", 0)

document.add_picture(svg_filename)

document.save("demo.docx")

@liam-veitch
Copy link

liam-veitch commented Aug 3, 2022

Hi @takis thanks for the improvement - for my SVG files there are relative scalings in the width and height attributes. I had to take the data from the viewbox attribute. This is a complete 'hack' and probably does not respect SVG specification regarding pt/pixel/ppi etc.

Example svg header:
<svg baseProfile='full' height='100.000000%' version='1.1' viewBox='0.000000 0.000000 1240.000000 1753.000000' width='100.000000%' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>

in svg.py:

    @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_str = root.attrib["width"]
        height_str = root.attrib["height"]
        if width_str.endswith(r'%') and height_str.endswith(r'%'):
            vb_lims = str(root.attrib["viewBox"]).split(' ')
            width_scale = float(width_str[:-1]) * 0.01 * 72/96
            height_scale = float(height_str[:-1]) * 0.01 * 72/96
            width = int(width_scale * float(vb_lims[2]))
            height = int(height_scale * float(vb_lims[3]))
        elif width_str.endswith('pt') and height_str.endswith('pt'):
            width = int(float(width_str[:-2]))
            height = int(float(height_str[:-2]))
        else:
            width = int(width_str)
            height = int(height_str)

        return width, height

@JaverHumberto
Copy link

Hi @takis, I'm new using docx (and python), and I'm tryng to load some SVG images in a word document, looking for that I found this, but try to replicate the code you were testing with and it doesn't work for me, I get the docx.image.exceptions.UnrecognizedImageError. So it isn't "included" in docx now? if not, is there a way for using your code? thanks in advance, and sorry if it's not a place for asking this, i'll remove the comment if needed.

@Kladdy
Copy link

Kladdy commented Nov 2, 2023

This would be amazing if it could be merged into a new release. In the meantime, if somebody wants to play around with SVG files, I created a monkey patch just as was made in the case for EMF files: #196 (comment). Just add the code from the gist below to a file called docx_svg_patch.py, and at the top of your own python script you have import docx_svg_patch. I haven't tested this extensively, and I am not sure how well this plays with other image types now, but it's at least a start.

Link to gist: https://gist.github.com/Kladdy/d3bdb9bbf2c38d4f194ea9a7904fc3f2

@takis
Copy link
Author

takis commented Feb 22, 2024

I've created a new pull request for this, as there were many conflicts with the updated code base:
#1343

@takis
Copy link
Author

takis commented Feb 22, 2024

Hi @takis, I'm new using docx (and python), and I'm tryng to load some SVG images in a word document, looking for that I found this, but try to replicate the code you were testing with and it doesn't work for me, I get the docx.image.exceptions.UnrecognizedImageError. So it isn't "included" in docx now? if not, is there a way for using your code? thanks in advance, and sorry if it's not a place for asking this, i'll remove the comment if needed.

Hi @JaverHumberto, no, unfortunately, the code was not merged. I've created a new pull request and updated the code though. If you want to try it, you can use my fork for now:
https://github.com/takis/python-docx/

@takis
Copy link
Author

takis commented Feb 22, 2024

Hi @Kladdy

I've updated the pull request and I'm also still hoping that it will get merged one day.

@goomesthiago
Copy link

Do you have any updates on this?
The SVG files are still not compatible with python-docx?

@takis
Copy link
Author

takis commented Jun 19, 2024

Hi @goomesthiago

Unfortunately not, but I do try to keep my fork in sync with the main repository.

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.

5 participants