Skip to content

Add SVG #351

Open
Open

Description

@mrlarssen

Is it possible to add SVG to the document? For instance an svg-string such as

< svg xmlns="http://www.w3.org/2000/svg" width="200" height="100" version="1.1">
< rect width="200" height="100" stroke="black" stroke-width="6" fill="green" />
</ svg>

would be perfect. Or just a svg file?

Activity

  1. scanny commented on Jan 21, 2017

    @scanny
    Contributor

    Can you do that from the Word application UI?

  2. mrlarssen commented on Jan 22, 2017

    @mrlarssen
    Author
  3. scanny commented on Jan 22, 2017

    @scanny
    Contributor

    I suspect it translates them into Windows Metafile Format (WMF) and stores them that way. You'd need to try it and then inspect the .docx file (it's a zip archive) and see what the image was that got included. I expect the file extension of the image file name would reliably indicate the underlying file type its stored as.

  4. mrlarssen commented on Jan 23, 2017

    @mrlarssen
    Author

    I guess the documentation is outdated, as this approach does not let me insert an svg into the word document. So I assume the limitation lays with word itself?

    Then I need to look into how I can convert svg to png in Python.

    Thanks for your response.

  5. scanny commented on Jan 23, 2017

    @scanny
    Contributor

    This page has some insights on why it might not be working for you:
    https://www.quora.com/How-would-you-insert-a-svg-file-in-PowerPoint

    It could be your PowerPoint version is not the very latest; I know mine isn't :)

    It's still not clear whether the new PowerPoint 2016 supports SVG files natively or whether they are just converted to WMF/EMF and stored that way, like it does with PDF/EPS images.

  6. reopened this on Jan 23, 2017
  7. ftomassetti commented on Jul 30, 2020

    @ftomassetti

    A PR related to this is pending #798

  8. kuri65536 commented on Aug 11, 2020

    @kuri65536

    Thank you to python-docx, this is very useful software.

    I had done to embed svg images with python-docx.

    this is a part of my
    mkdocs-theme-topdf .
    code is here

    BTW, I found the PR and this is just a sample workaround for
    the current version.

    Screenshot_20200811-153340~2

    (this preview from Word android)

    from docx.image import image
    
    def run(doc: Document):
        monkey()
        para = doc.add_paragraph()
        pic = para.add_run().add_picture("sample.svg")
        compose_asvg(pic)
    
    def compose_asvg(pic: Tag) -> None:
        embed = '{%s}embed' % (
            "http://schemas.openxmlformats.org/officeDocument/2006/relationships")
        url = "http://schemas.microsoft.com/office/drawing/2016/SVG/main"
        url14 = "http://schemas.microsoft.com/office/drawing/2010/main"
        etree.register_namespace("asvg", url)
        etree.register_namespace("a14", url14)
    
        ablip = pic._inline[-1][-1][-1][1][0]
        elst = OxmlElement('a:extLst')
        ablip.append(elst)
        embed_id = ablip.attrib.get(embed, "")
        del(ablip.attrib[embed])
    
        aext = OxmlElement('a:ext')
        elst.append(aext)
        aext.set("uri", "{28A0092B-C50C-407E-A947-70E740481C1C}")
        ldpi = etree.Element('{%s}useLocalDpi' % url14)
        aext.append(ldpi)
        ldpi.set("val", "0")
    
        aext = OxmlElement('a:ext')
        elst.append(aext)
        aext.set("uri", "{96DAC541-7B7A-43D3-8B79-37D633B846F1}")
    
        asvg = etree.Element('{%s}svgBlip' % url)
        aext.append(asvg)
        asvg.set(embed, embed_id)
    
    def monkey() -> None:
        global default_factory
        if default_factory is not None:
            return
        default_factory = image._ImageHeaderFactory
        image._ImageHeaderFactory = _ImageHeaderFactory
    
    def _ImageHeaderFactory(stream: IO[Text]) -> image.BaseImageHeader:
        stream.seek(0)
        buf = stream.read(32)
        if "<svg".encode("latin") in buf:
            stream.seek(0)
            return Svg.from_stream(stream)
        assert default_factory is not None
        return default_factory(stream)
    
    class Svg(image.BaseImageHeader):
        @classmethod
        def from_stream(cls, stream: IO[Text]) -> '_SvgParser':
            """Return a |Svg| instance having header properties parsed from image
                 in *stream*."""
            # this is dummy.
            return cls(100, 100, 96, 96)
    
        @property
        def content_type(self) -> Text:
            return "image/svg"
    
  9. scanny commented on Aug 11, 2020

    @scanny
    Contributor

    Nice, @kuri65536, thanks for posting this :)

  10. tikuma-lsuhsc commented on Apr 27, 2021

    @tikuma-lsuhsc

    @kuri65536 - Thanks for the nice workaround!

    For anyone else still waiting for the PR, @kuri65536 's code caused a small hiccup in my code. Specifically, _ImageHeaderFactory() is not accounting for valid preceding XML tags. Here is how I fixed it:

      import re
    
      def _ImageHeaderFactory(stream):
          stream.seek(0)
          buf = stream.read(32).decode("utf-8")
          while re.match(r"\s*\<\?|\s*\<\!", buf):
              m = re.match(r"(?:\s*<[\s\S]*?>\s*)+", buf)
              if m:
                  buf = buf[m.end(0) :]
              if not m or len(buf) < 4:
                  buf += stream.read(32).decode("utf-8")
          if buf.startswith("<svg"):
              stream.seek(0)
              return Svg.from_stream(stream)
          assert default_factory is not None
          return default_factory(stream)
  11. cristianocca commented on Jun 14, 2021

    @cristianocca

    It's been some time, any news or actual guide how to add an svg image to the docx template file?

  12. jfthuong commented on Mar 17, 2022

    @jfthuong

    If it might help,

    Here are 2 Word with a similar image in PNG and SVG that have been added in the same place.

    I have also extracted the files and pretty-formatted the XML files for easier comparison

    png_vs_svg.zip

  13. takis commented on Jun 24, 2022

    @takis

    Hi,

    I had a first try at implementing this, but have only tested using simple SVGs. The files open without issues in Word on my Mac Mini.

    Any feedback welcome. I haven't written any tests yet.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions