How to resize svg image file using librsvg Python binding
Asked Answered
P

3

12

When rasterizing svg file, I would like to be able to set width and height for the resulting png file. With the following code, only the canvas is set to the desired width and height, the actual image content with the original svg file dimension is rendered in the top left corner on the (500, 600) canvas.

import cairo
import rsvg

WIDTH, HEIGHT  = 500, 600
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)

ctx = cairo.Context(surface)

svg = rsvg.Handle(file="test.svg")
svg.render_cairo(ctx)

surface.write_to_png("test.png")

What should I do to make the image content same size with cairo canvas? I tried

svg.set_property('width', 500)
svg.set_property('height', 500)

but got

TypeError: property 'width' is not writable

Also documents for librsvg python binding seem to be extremely rare, only some random code snippets on cairo site.

Potsdam answered 27/7, 2009 at 10:0 Comment(0)
I
5

There is a resize function in librsvg, but it is deprecated.

Set up a scale matrix in Cairo to change the size of your drawing:

  • setup a scale transformation matrix on your cairo context
  • draw your SVG with the .render_cairo() method
  • write your surface to PNG
Imputation answered 27/7, 2009 at 10:12 Comment(3)
Will rescaling the already rasterized image result in data loss of the original vector image?Potsdam
The cairo transformation matrix operates on vector data drawed after setting it. You don't scale the rasterized image but the commands issued by librsvg that produce it.Imputation
Care to post a code snippet? Documentation you linked is for C, the Python equivalent syntax is not obvious, specially when dealing with matrices and transforms. Also, scaling seems to be always by a factor, not directly to (x, y) dimension rescaleThousand
M
5

This is the code that works for me. It implements the answer by Luper above:

import rsvg
import cairo

# Load the svg data
svg_xml = open('topthree.svg', 'r')
svg = rsvg.Handle()
svg.write(svg_xml.read())
svg.close()

# Prepare the Cairo context
img = cairo.ImageSurface(cairo.FORMAT_ARGB32, 
      WIDTH, 
      HEIGHT)
ctx = cairo.Context(img)

# Scale whatever is written into this context
# in this case 2x both x and y directions
ctx.scale(2, 2)
svg.render_cairo(ctx)

# Write out into a PNG file
png_io = StringIO.StringIO()
img.write_to_png(png_io)    
with open('sample.png', 'wb') as fout:
    fout.write(png_io.getvalue())
Mastoiditis answered 1/10, 2014 at 3:30 Comment(1)
I couldn't find rsvg library to install. I have provided solution with svgutils.Butterbur
B
2

Resizing svg files programmatically is not obvious. The solution provided here by other answers may be outdated/difficult to implement. I'm using another library svgutils.

The following should work.

import svgutils.transform as sg
import sys

fig = sg.fromfile('myimage.svg')
fig.set_size(('200','200'))
fig.save('myimage2.svg')

You can install svgutils with usual -

pip install svgutils

Once you have properly resized svg file, you can use ffmpeg or any other image converter to save it into png.

Butterbur answered 18/8, 2022 at 2:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.