First I note that there are many related questions, but after a day of trying pyvip and cairo and the rest none of them work for me, even after installing other software that they seem to depend on. The exception is svglib with reportlab, it comes close but doesn't quite get there! This is the best post I found and may help some.
I have all my source images in SVG files. Most app stores require you to provide a set of PNGs with specific sizes and qualities. So I need to take an SVG and produce a PNG with width w and height h and specific dpi. I want to do this programmatically in python.
I have written a function that almost works, but scaling and dpi interact with each other in weird ways. I use svglib to convert the SVG to a ReportLab drawing then use reportlab to manipulate the drawing. The install went smoothly on Windows unlike some of the other options.
pip install svglib
pip install reportlab
The code is as follows. I inspected the above libraries to get the arguments, but added stuff to get specific size.
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM
def svg_to_png(in_path,out_path,fmt="PNG",
scale=None,size=None,scale_x=1,size_x=None,scale_y=1,size_y=None,
dpi=72, bg=0xffffff):
# Convert SVG to ReportLab drawing.
drawing = svg2rlg(in_path)
# Work out scale factors
# Scale over-rides scale_x|y, ditto size
scale_x = scale if scale else scale_x
scale_y = scale if scale else scale_y
size_x = size if size else size_x
size_y = size if size else size_y
# Size over-rides scale
scaling_x = size_x/drawing.width if size_x else scale_x
scaling_y = size_y/drawing.height if size_y else scale_y
# Scale the drawing
drawing.width = drawing.minWidth() * scaling_x
drawing.height = drawing.height * scaling_y
drawing.scale(scaling_x, scaling_y)
# Render ReportLab drawing as a PNG
renderPM.drawToFile(drawing, out_path, fmt=fmt, dpi=dpi, bg=bg)
if __name__ == '__main__':
breakpoint()
in_path = 'C:\\Users\\...\\A.svg'
out_path = 'C:\\Users\\...\\A.png'
svg_to_png(in_path,out_path,scale=2,dpi=72)
The function works for resizing so long as I leave the dpi alone. The dpi=72 seems to be a universal default in reportlab and the source of the issues. I hoped that increasing the dpi would impove the quality of the PNG (reduce pixilation), but all it seems to do is expand the canvas.
The input SVG is of course pixel perfect. Here are four PNGs from the above function.
Scale 1 dpi 72 (dim 115x124 size 8.13kb), conversion with all defaults.
Scale 1 dpi 144 (dim 230x249 size 9.06kb), canvas doubled, pic in bottom-left quadrant, ignore black line bug.
Scale 2 dpi 72 (dim 230x249 size 17.5kb), scaled properly but pixelated (look at the eye)
Scale 2 dpi 144 (dim 461x497 size 19.8kb), canvas quadrupled? picture doubled.
Can someone please advise how to use reportlab properly to resize the picture to given scale or size and within that fixed size, increase the quality via the dpi.