Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 485
Osmond Bishop Avatar asked May 13 '13 01:05

Osmond Bishop


2 Answers

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()
like image 175
Don Kirkby Avatar answered Sep 21 '22 14:09

Don Kirkby


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
like image 27
skidzo Avatar answered Sep 23 '22 14:09

skidzo