简体   繁体   中英

Embed .SVG files into PDF using reportlab

I have written a script in python that produces matplotlib graphs and puts them into a pdf report using reportlab .

I am having difficulty embedding SVG image files into my PDF file. I've had no trouble using PNG images but I want to use SVG format as this produces better quality images in the PDF report.

This is the error message I am getting:

IOError: cannot identify image file

Does anyone have suggestions or have you overcome this issue before?

Yesterday I succeeded in using svglib to add a SVG Image as a reportlab Flowable.

so this drawing is an instance of reportlab Drawing, see here:

from reportlab.graphics.shapes import Drawing

a reportlab Drawing inherits Flowable:

from reportlab.platypus import Flowable

Here is a minimal example that also shows how you can scale it correctly (you must only specify path and factor):

from svglib.svglib import svg2rlg
drawing = svg2rlg(path)
sx = sy = factor
drawing.width, drawing.height = drawing.minWidth() * sx, drawing.height * sy
drawing.scale(sx, sy)
#if you want to see the box around the image
drawing._showBoundary = True

As mentioned by skidzo, you can totally do this with the svglib package, which you can find here: https://pypi.python.org/pypi/svglib/

According to the website, Svglib is a pure-Python library for reading SVG files and converting them (to a reasonable degree) to other formats using the ReportLab Open Source toolkit.

You can use pip to install svglib.

Here is a complete example script:

# svg_demo.py

from reportlab.graphics import renderPDF, renderPM
from reportlab.platypus import SimpleDocTemplate
from svglib.svglib import svg2rlg


def svg_demo(image_path, output_path):
    drawing = svg2rlg(image_path)
    renderPDF.drawToFile(drawing, output_path)

if __name__ == '__main__':
    svg_demo('/path/to/image.svg', 'svg_demo.pdf')

skidzo's answer is very helpful, but isn't a complete example of how to use an SVG file as a flowable in a reportlab PDF. Hopefully this is helpful for others trying to figure out the last few steps:

from io import BytesIO

import matplotlib.pyplot as plt
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import SimpleDocTemplate, Paragraph
from svglib.svglib import svg2rlg


def plot_data(data):
    # Plot the data using matplotlib.
    plt.plot(data)

    # Save the figure to SVG format in memory.
    svg_file = BytesIO()
    plt.savefig(svg_file, format='SVG')

    # Rewind the file for reading, and convert to a Drawing.
    svg_file.seek(0)
    drawing = svg2rlg(svg_file)

    # Scale the Drawing.
    scale = 0.75
    drawing.scale(scale, scale)
    drawing.width *= scale
    drawing.height *= scale

    return drawing


def main():
    styles = getSampleStyleSheet()
    pdf_path = 'sketch.pdf'
    doc = SimpleDocTemplate(pdf_path)

    data = [1, 3, 2]
    story = [Paragraph('Lorem ipsum!', styles['Normal']),
             plot_data(data),
             Paragraph('Dolores sit amet.', styles['Normal'])]

    doc.build(story)


main()

You need to make sure you are importing PIL (Python Imaging Library) in your code so that ReportLab can use it to handle image types like SVG. Otherwise it can only support a few basic image formats.

That said, I recall having some trouble, even when using PIL, with vector graphics. I don't know if I tried SVG but I remember having a lot of trouble with EPS.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM