8

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.

Thomas Grainger
  • 2,271
  • 27
  • 34

5 Answers5

8

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
RJ-
  • 2,919
  • 3
  • 28
  • 35
6

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
danpalmer
  • 2,163
  • 4
  • 24
  • 41
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>
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
  • Can't you build imagemagick with librsvg support? That might reduce the number of required binaries. The use of `pngquant` seems smart. – joeyhoer Oct 03 '17 at 15:40
  • 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). – Dave Jarvis Oct 03 '17 at 15:58
  • 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: https://github.com/gerardbm/dotfiles/blob/master/bin/.local/bin/faviconer – Unix Nov 02 '19 at 23:39
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.

Thomas Grainger
  • 2,271
  • 27
  • 34
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/manual@v1.31.1/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

MXDVL
  • 348
  • 2
  • 9