Osmond Bishop
Osmond Bishop

Reputation: 8190

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?

Upvotes: 10

Views: 12285

Answers (4)

Don Kirkby
Don Kirkby

Reputation: 56640

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()

Upvotes: 4

skidzo
skidzo

Reputation: 415

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

Upvotes: 11

Mike Driscoll
Mike Driscoll

Reputation: 33071

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')

Upvotes: 5

Gordon Seidoh Worley
Gordon Seidoh Worley

Reputation: 8068

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.

Upvotes: 0

Related Questions