I want to convert SVG images to PNG files with transparent background and anti-aliased edges (using semi-transparent pixels). Unfortunately I can't get ImageMagick to do the anti-aliasing, the edges always look terrible. Here's what I tried:
convert +antialias -background transparent in.svg -resize 25x25 out.png
Any ideas or a different command line tool I could use?
As a side note, I found that getting transparency was a bit tricky. Instead of using transparent, I had to use none.
convert -background none in.svg out.png
Inkscape will do this:
inkscape \
--export-png=out.png --export-dpi=200 \
--export-background-opacity=0 --without-gui in.svg
Update
The terminology has changed: all the export params suppress gui, and the output parameter is now simply based on the file type. For example, a type of png
will cause a file in /path/to/picture.svg
to be exported as /path/to/picture.png
(caution: this overwrites output).
inkscape \
--export-type=png --export-dpi=200 \
--export-background-opacity=0 picture.svg
Note cited wiki has quotes on --export-type=png
, which is incorrect.
Also if don't have Inkscape command line, MacOS can access via bash directly:
/Applications/Inkscape.app/Contents/MacOS/inkscape
-background none
before the SVG filename" answer is much better because it actually uses ImageMagick, the tool asked about…: stackoverflow.com/a/18579465/1901658
Actually, reading imagemagick documentation:
-antialias Enable/Disable of the rendering of anti-aliasing pixels when drawing fonts and lines. By default, objects (e.g. text, lines, polygons, etc.) are antialiased when drawn. Use +antialias to disable the addition of antialiasing edge pixels. This will then reduce the number of colors added to an image to just the colors being directly drawn. That is, no mixed >colors are added when drawing such objects.
the +antialias will indeed disable antialiasing.
The way I learned how to do this was from the methodology found here: How to convert a .eps file to a high quality 1024x1024 .jpg?
It is the same idea as @halfer's solution with inkscape
--to jack up the DPI first--but you can accomplish the same thing in just imagemagick
using the -density
option.
convert -density 200 in.svg -resize 25x25 -transparent white out.png
-background none
solution, because white is a valid fill/stroke color that may present in many SVG's, and this turns all white pixels transparent, even those defined as being white fills/strokes.
Adding the -transparent white
option solves the problem particularly in my case because background isn't removed completely (unfortunately light shadow is present). So I'm using IMHO more clearer solution that fully removes background with ImageMagic:
convert -channel rgba -background "rgba(0,0,0,0)" in.svg out.png
It sets a fully transparent black color as the background through the RGBA channel.
-transparent
option: imagemagick.org/script/command-line-options.php#transparent
-background none
works just as well in recent IM releases, and avoids needing to supply -channel rgba
if the target is PNG
For me that works for svg to png:
convert ${src} \
-transparent white \
-background none \
-resize 345x345 \
res/drawable-xxxhdpi/${dest}
-transparent white
and -background none
, and this will negatively effect files with elements of the foreground that are supposed to be white. Only supply -background none
.
I get better, already nicely antialiased results if I replace -resize
with -scale
. Then, the antialias
flag isn't even necessary.
I add a rect as background. The embed CSS hide the background. Then I catch its color for setting the transparent attribute of ImageMagick.
SVG file:
<?xml version="1.0" ?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg
version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="500px" height="500px"
viewBox="0 0 500 500"
enable-background="new 0 0 500 500"
>
<defs>
<style>
#background { display: none; }
</style>
</defs>
<rect id="background" x="0" y="0" width="500" height="500" fill="#e8e437"/>
<!-- beginning of the sketch -->
<g fill="#000" text-anchor="middle"font-size="112">
<text y="350" x="192">OK</text>
</g>
<!-- end of the sketch -->
</svg>
bash script
#!/bin/bash
BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )
SVG_DIR="$BASE_DIR/import"
PNG_DIR="$BASE_DIR/export"
for f in `ls $SVG_DIR/*.svg`
do
g="$PNG_DIR/$(basename "$f" .svg).png"
BGCOLOR=`grep 'id="background"' $f \
| sed 's/.* fill="\([^"]*\)".*/\1/'`
convert $f -transparent "$BGCOLOR" $g
done
-background none
option to convert
.
Success story sharing
-background none
worked for me, ImageMagick 6.8.6-6 on a macconvert in.svg -background none out.png
, I found that this ordering will fail to make the background transparent; it resulted in an opaque white background! Make sure thatin.svg
andout.png
are the final two arguments in the command.-background none
is indeed correct as per the image magic color names documentation: "There is also a color called 'none' that is fully transparent. This color is shorthand forrgba(0, 0, 0, 0.0)
."