How to convert an image file from SVG to a multi-size ICO without blur (sharp)
Asked Answered
O

5

10

I've been using ImageMagick, but it produces a very blurry result.

convert -density 300 ../images/favicons/procensus.svg -background transparent -colors 256 -define icon:auto-resize favicon2.ico

It seems to be rendering the image at 300 density, then resizing that with a Gaussian filter for all the other sizes in the icon.

What I actually want it to do is re-render with shape-rendering="crispEdges" at each pixel size in the favicon.

I want ImageMagick (or whatever other tool) to re-render the SVG at each provided density of .ico.

Note that this tool should only be a tool I can use at package build time: an open-source piece of installable software for Linux.

Octal answered 31/8, 2016 at 17:55 Comment(5)
You need to put the density before the loading of the image... convert -density xyz image.svg ...Nonjuror
Yeah that's slightly less blurryOctal
You may find the best result is to use a two-step process. Render your SVG to a bitmap first, say at 256x256. Then create your icons from that.Ephesus
@PaulLeBeau although it doesn't work if you render to 256 then down-scale, as those images are still down-smapled. You need to explicitly render each one :(Octal
If it fails sudo apt install librsvg2-binEugenieeugenio
O
0

I've got it working configuring shape-rendering="crispEdges" and doing:

sudo apt install libbatik-java
rasterizer favicon.svg -d favicon-16.png -h 16 -w 16
rasterizer favicon.svg -d favicon-32.png -h 32 -w 32
rasterizer favicon.svg -d favicon-48.png -h 48 -w 48
rasterizer favicon.svg -d favicon-64.png -h 64 -w 64

convert favicon-16.png favicon-32.png favicon-48.png favicon-64.png favicon.ico

But it looks like image magick doesn't support that attribute.

I'm still looking for more elegant answers.

Octal answered 5/9, 2016 at 10:24 Comment(0)
Y
16

Try this one liner. Self-explanatory I think.

convert -density 300 -define icon:auto-resize=256,128,96,64,48,32,16 -background none input.svg out.ico
Yep answered 17/9, 2020 at 22:29 Comment(0)
S
7

Using a test SVG, I managed to get a multi-size ico file with this command - you can change the sizes as necessary.

convert procensus.svg -bordercolor white -border 0 \
      \( -clone 0 -resize 16x16 \) \
      \( -clone 0 -resize 32x32 \) \
      \( -clone 0 -resize 48x48 \) \
      \( -clone 0 -resize 64x64 \) \
      -alpha off -colors 256 favicon.ico
Sponson answered 2/9, 2016 at 12:43 Comment(3)
Sorry that's still blurry.Octal
That's missing a -delete 0 to not add the full-size svg to the icon.Stine
Add -background none as first parameter after convert to preserve transparency.Herzl
C
2

Requirements

On a UNIX-like operating system (Linux, MacOS, etc.), download and install the following:

  • ImageMagick
  • rsvg-convert
  • pngquant

Script

Save the following as build.sh:

#!/bin/bash

# Relative path to location of SVG file to make into ICO file.
ICON_PATH=../../images/edible.svg

ICON_BASE=$(basename "$ICON_PATH")
ICON_DIR=$(dirname "$ICON_PATH")
ICON_FILE="${ICON_BASE%*.}"
ICON_EXT="${ICON_BASE##*.}"

FAVICON_FILE=favicon
FAVICON_EXT=.ico

# This uses rsvg-convert to create crisp PNG icons.
for size in 16 32 64 128 150 192 512; do
  ICON_OUT=$ICON_FILE-${size}.png
  DIMENSIONS=${size}x${size}
  rsvg-convert -w $size -p 300 -d 300 $ICON_PATH > $ICON_OUT

  # Use ImageMagick to center the image and make it square.
  convert $ICON_OUT -gravity center -background transparent \
    -resize $DIMENSIONS -extent $DIMENSIONS temp-$ICON_OUT

  # Use 8-bit colour to reduce the file size.
  pngquant 256 < temp-$ICON_OUT > $FAVICON_FILE-$DIMENSIONS.png
done

# Merge the 16- and 32-pixel versions into a multi-sized ICO file.
convert \
  $FAVICON_FILE-16x16.png \
  $FAVICON_FILE-32x32.png \
  -colors 256 ../$FAVICON_FILE$FAVICON_EXT

# Create Android icons.
mv $FAVICON_FILE-192x192.png android-chrome-192x192.png
mv $FAVICON_FILE-512x512.png android-chrome-512x512.png

# Create MS tile icon.
mv $FAVICON_FILE-150x150.png mstile-150x150.png

# Clean up the temporary files.
rm ${ICON_FILE}*png temp-${ICON_FILE}*png

Edit the file and change the ICON_PATH variable to the location of the SVG file to convert, such as:

ICON_PATH=../images/favicons/procensus.svg

Run the script:

./build.sh

Various icons are created in the current directory.

Note: Be sure to backup your files before running this command as it will erase the PNG files it creates while processing.

Browser Config

Save the following file as browserconfig.xml:

<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
    <msapplication>
        <tile>
            <square150x150logo src="/mstile-150x150.png"/>
            <TileColor>#da532c</TileColor>
        </tile>
    </msapplication>
</browserconfig>
Changeable answered 3/10, 2017 at 4:5 Comment(3)
Can't you build imagemagick with librsvg support? That might reduce the number of required binaries. The use of pngquant seems smart.Smattering
Solutions that work without compiling software avoid having to track down library dependencies and other issues that plague building from source. Feel free to suggest an edit with the instructions to integrate ImageMagick and librsvg (could be some command-line parameters that do the job, as well).Changeable
Your bash script inspired me to implement my own favicon generator, so I got your code to make this similar script. It generates favicon.ico with 3 sizes (16, 32 and 48) for the root folder, puts all the other icons in a folder, and it also generates a black mask for safari. It also asks for colors. It also generates the site.webmanifest and browserconfig.xml, and then it shows you the html: github.com/gerardbm/dotfiles/blob/master/bin/.local/bin/…Rigel
O
0

I've got it working configuring shape-rendering="crispEdges" and doing:

sudo apt install libbatik-java
rasterizer favicon.svg -d favicon-16.png -h 16 -w 16
rasterizer favicon.svg -d favicon-32.png -h 32 -w 32
rasterizer favicon.svg -d favicon-48.png -h 48 -w 48
rasterizer favicon.svg -d favicon-64.png -h 64 -w 64

convert favicon-16.png favicon-32.png favicon-48.png favicon-64.png favicon.ico

But it looks like image magick doesn't support that attribute.

I'm still looking for more elegant answers.

Octal answered 5/9, 2016 at 10:24 Comment(0)
R
0

I have been a variation on the methods on this page for a long time–thanks all for contributing. ❤️


Recently, I decided to create a script which processes the images in a single step, which depends on a single binary: the Deno runtime!

# Install on shell
curl -fsSL https://deno.land/x/install/install.sh | sh
# … or see https://deno.land/[email protected]/getting_started/installation#download-and-install

It leverages the WASM ports of resvg and Image Magick, which are natively supported in that runtime. You can invoke it thusly:

deno run \
       --import-map=https://raw.githubusercontent.com/mxdvl/mxdvl/main/deno/import-map.json \
       https://raw.githubusercontent.com/mxdvl/mxdvl/main/deno/scripts/ico.ts \
       mask-icon.svg output.ico

As Deno is built on secure foundations, it will prompt for filesystem access.

enter image description here

Respectively answered 27/2, 2023 at 21:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.