Convert and resize SVG to PNG
Asked Answered
O

7

39

I am trying to convert SVG to PNG (or any raster format) and resize at the same time.

I thought I would use ImageMagick for this task but it seems to be converting to raster before resizing.

This results in a poor quality image.

  • Is there a way to get ImageMagick to resize the SVG before converting to raster?

  • Or is there some other tool I can use to programatically convert an SVG to a raster after resizing it?

  • Alternatively, is there some other tool I could use for this?

Currently I'm using ImageMagick via a commandline:

convert file.svg -resize 100x100 file.png

The source image "size" is unknown and the destination size is not known until run-time.

Oxbow answered 12/8, 2013 at 16:39 Comment(4)
Show us the command you are issuingHartford
@Hartford I've added the incorrect cmdlineOxbow
@MarkSetchell's answer is the correct one. You need to set the canvas size up front in the command line. For more details about ImageMagick command structure and order of its arguments, see "ImageMagick Command-Line Option Order (and Categories of Command-Line Parameters)".Constrict
#9853825Karb
C
51

This is the way I do it and it seems to work.

convert -background none -density 1000 -resize 1000x compass.svg compass.png

Here's what each part does.

  • Use -background none to make sure any transparent parts of the SVG stay transparent and not get filled with white.
  • As ImageMagick only works with raster images you need to use -density 1000 and specify the width to which you want to resize the SVG. This way when you actually call the resize command, the raster representation of the loaded SVG will already have a width of 1000, otherwise you'll end up resizing a raster up or down from whatever the original size of the SVG image is.
  • Now use -resize 1000x to give your SVG a new width, the height will be calculated automatically to keep the aspect ratio.

One pitfall of this, is that I don't really know how you could resize based on the height and let the width be calcualted since -density is applied to the width, not the height. So, you'd have to know the actual ratio of your SVG beforehand and work with the width accordingly.

Carbonization answered 18/2, 2016 at 19:7 Comment(1)
-density x was the missing piece for making it bigger than defaultPresumably
H
41

The SVG is defined as a vector, not a bitmap - which is what IM likes dealing with. When IM reads a vector in, it doesn't know the size, so when you do this:

convert compass.svg -resize 1000x1000 compassB.jpg

it creates a default sized bitmap canvas, "draws" the vector onto it, then resizes it and saves it as a JPEG. The result, if your intended size is larger than the canvas that IM "guessed" is poor quality - it cannot create information it no longer has as a result of rasterizing the image onto too small a canvas.

enter image description here

The solution is to tell IM up-front that the vector needs to be drawn onto a big canvas, before it rasterises:

convert -size 1000x1000 compass.svg compassA.jpg

enter image description here

Harney answered 13/1, 2015 at 9:45 Comment(7)
That makes a lot of sense. I'll look into it, thanksOxbow
@DJL: This is the correct answer. If you do not accept it, at least please upvote it!Constrict
@KurtPfeifle , once I've had the chance to check this out I will. The question was original asked 6 months ago. I've since moved on to other things.Oxbow
I've not been able to get this working. Possibly my version of ImageMagick is too oldOxbow
This does not work for me either, the image is saved in it's original (defined in the XML) size.Carbonization
For me with GraphicsMagick, you can specify only the longest dimension e.g. convert -size 1200 .. and it will scale up maintaining aspect ratio (if the source file has rectangular dimensions). It may be that ImageMagick behaves that way too.Dariodariole
This is a great explanation but it did not work for me. What worked for me was adjusting the density, like this: convert -density 288 input.svg output.pngAdductor
M
12

I have made svgexport for this:

svgexport file.svg file.png 100:100
Mulder answered 13/1, 2015 at 5:36 Comment(1)
This is a great tool but unfortunately I can no longer use it because it depends on PhantomJS which has been deprecated.Hailstone
O
5

So it turns out that inkscape has a commandline interface.

Unfortunately the -w and -h arguments to inkscape do not preserve the aspect ratio. However it does provide a way to query the current width and height - but only one at a time.

So the solution is to run inkscape no less than 3 times.

inkscape -f svgfile.svg -W
<read stdin into some variable>
inkscape -f svgfile.svg -H
<read stdin into some variable>
<calculate aspect ratio and apply logic to retain aspect for new size>
inkscape -f svgfile.svg -w <newwidth> -h <newheight> -e file.png

In my instance I then had to run the generated file through ImageMagick to perform additional operations.

Doing all this from C# is cumbersome to say the least so this question remains open for a better solution.

Oxbow answered 13/8, 2013 at 14:37 Comment(0)
R
3

With image magick 7 you can do the following in one line:

magick in.svg -density "%[fx:((1080/w)*72)]" -delete 0 -background none in.svg -scale 1080x out.png

This will automatically determine the correct density to get it scaled in the right resolution. Exchange the 2 '1080' values to the width you like your png.

Rote answered 1/4, 2021 at 8:31 Comment(1)
Nice. If I change the 72 to 96, I don't need the -scale 1080x step. Complete command: magick in.svg -density "%[fx:((1080/w)*96)]" -delete 0 -background none in.svg out.png.Dracaena
A
1

Some of the answers here don't work for me.

The issue has to do with the density of the rasterization, not the size of the target image. By default ImageMagick rasterizes SVGs at 72 dpi. To increase the density, you can add the -density flag, like this:

convert -density 288 input.svg output.png

I got this from this guide: https://makandracards.com/makandra/506738-imagemagick-converting-svg-to-raster-image-formats-like-png-or-jpeg

Adductor answered 9/8, 2023 at 6:9 Comment(1)
It's worth noting that ImageMagick has changed a fair bit in the past 10 years. Possibly thats why you are seeing different results.Oxbow
W
0

It's odd that ImageMagick would be rendering at one size and then rescaling the bitmap. Unless, that is, the SVG has a specific size defined in it. Check the width and height attributes of the SVG files you are using. Try changing the width and height to 100% and see if that makes a difference.

<svg width="100%" height="100%" ...etc...>

(Assuming you have control over the SVG files you are using).

Winwaloe answered 13/8, 2013 at 13:55 Comment(1)
That's an interesting solution. I haven't tried it as I've now solved the issue another way (albeit rather convoluted). Answer coming in a few minutes. Unfortunately I don't have control over the source SVGs.Oxbow

© 2022 - 2025 — McMap. All rights reserved.