← Back to Blog

ImageMagick for Favicon Sets and Brand Image Processing

ImageMagick for Favicon Sets and Brand Image Processing

I process every hero image on jwatte.com with a single ImageMagick command. One line takes a raw 2048x2048 PNG from Ideogram, crops it to 16:9, converts it to WebP at quality 82, and writes the file that gets deployed. No Photoshop. No Canva. No browser-based converter that quietly uploads your files to someone else's server.

ImageMagick does this and a lot more. This post is the complete command reference I wish I'd had when I started building out the favicon set, hero images, and social cards for this site.

Why ImageMagick

ImageMagick is free, open-source, and runs on Windows, Mac, and Linux. It handles resize, crop, format conversion, and image composition from a single CLI tool. There is no subscription. There is no GUI to click through. You type a command, you get a file.

The modern command is magick (ImageMagick 7+). If you see old tutorials using convert, that is the v6 syntax. Use magick instead.

Install it in one line:

# Windows (winget)
winget install ImageMagick.ImageMagick

# Mac (Homebrew)
brew install imagemagick

# Linux (Debian/Ubuntu)
apt install imagemagick

After install, confirm it works:

magick --version

You should see version 7.x. If you see 6.x, you're on the legacy branch and the commands below won't work as written.

The complete favicon pipeline

Start with a single 1024x1024 (or larger) source PNG. This is the image your AI tool generated, whether that's Midjourney, Ideogram, or DALL-E. Every icon in this section comes from that one file.

Step 1: Generate favicon.ico (multi-size)

magick source.png -resize 16x16 favicon-16.png
magick source.png -resize 32x32 favicon-32.png
magick source.png -resize 48x48 favicon-48.png
magick favicon-16.png favicon-32.png favicon-48.png favicon.ico

The .ico format is a container. It holds multiple sizes inside a single file, and the browser picks whichever one fits the current context. The 16px version shows in the tab. The 32px version shows in bookmarks. The 48px version shows in Windows shortcut icons. A single-size favicon.ico is a missed opportunity.

Step 2: Apple touch icon (180x180)

magick source.png -resize 180x180 apple-touch-icon.png

iOS uses this when someone adds your site to their home screen. It must be PNG, not ICO. If you skip this, iOS takes a screenshot of your page and uses that as the icon. It looks terrible.

Step 3: PWA and Android icons

magick source.png -resize 192x192 icon-192.png
magick source.png -resize 512x512 icon-512.png

Your manifest.json references these. The 192px icon is the minimum for Android's "Add to Home Screen" prompt. The 512px icon is used for the splash screen when your PWA launches. Both are required if you want the install prompt to appear.

Step 4: Full icon set for completeness

If you want every common size covered:

for size in 16 32 48 72 96 128 144 152 180 192 512; do
  magick source.png -resize ${size}x${size} icon-${size}.png
done

On Windows PowerShell, the syntax is different:

foreach ($size in 16,32,48,72,96,128,144,152,180,192,512) {
  magick source.png -resize "${size}x${size}" "icon-${size}.png"
}

Most sites only need the four from Steps 1-3. The full set is for apps that target a wide range of devices and contexts.

Step 5: SVG favicon

ImageMagick can convert PNG to SVG with magick source.png source.svg, but the result is a raster image wrapped in a vector container. It is not a true vector. The file will be large and won't scale cleanly.

For a real SVG favicon, you need to either design it in Inkscape or Figma, or trace the AI output using a vectorization tool. If you already have an SVG logo, skip the conversion entirely and reference it directly in your HTML.

Step 6: The HTML declarations

Once you have the files, add these three lines to your <head>:

<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">

The first line covers legacy browsers. The second gives modern browsers a scalable vector. The third handles iOS. Three lines, full coverage.

Hero images and blog thumbnails

This is the command I use for every blog post on this site:

magick source.png -quality 82 -resize 1600x900^ -gravity center -extent 1600x900 hero.webp

That single line does four things. Here is what each flag means:

  • -quality 82 sets the WebP compression quality. 82 is a good balance between file size and visual clarity. Going higher saves almost no visible detail but doubles the file size.
  • -resize 1600x900^ resizes the image so the shortest dimension fills the target. The ^ suffix is critical. Without it, ImageMagick fits the image inside the box (letterboxing). With it, the image fills the box and overflows.
  • -gravity center anchors the crop point to the center of the image. Important subjects tend to be centered in AI-generated images, so this default works well.
  • -extent 1600x900 crops the overflow to the exact target dimensions.

The result is a 1600x900 WebP file, perfectly cropped with no letterboxing and no distortion.

Other useful variations:

# Thumbnail (400x225)
magick source.png -quality 82 -resize 400x225^ -gravity center -extent 400x225 thumb.webp

# Blog card (800x450)
magick source.png -quality 82 -resize 800x450^ -gravity center -extent 800x450 card.webp

Same pattern. Change the dimensions, keep the flags.

Social cards (OG images)

Facebook and LinkedIn use 1200x630. Twitter/X uses 1200x675 (sometimes 1200x628, but 675 is the safer bet). The commands:

# Facebook/LinkedIn OG image (1200x630)
magick source.png -quality 85 -resize 1200x630^ -gravity center -extent 1200x630 og-image.webp

# Twitter/X card (1200x675)
magick source.png -quality 85 -resize 1200x675^ -gravity center -extent 1200x675 twitter-card.webp

I bump quality to 85 for social cards because the platforms re-compress on upload. Starting at 82 plus their compression creates visible artifacts. Starting at 85 gives enough headroom.

One caveat: some social platforms still don't support WebP in OG tags. If your shared links show a broken image or a generic placeholder, convert to JPEG instead:

magick source.png -quality 85 -resize 1200x630^ -gravity center -extent 1200x630 og-image.jpg

Same command, different extension. ImageMagick picks the output format from the filename.

Format conversion reference

These are the commands I reach for most often:

# PNG to WebP
magick input.png -quality 82 output.webp

# PNG to AVIF (if your ImageMagick build supports it)
magick input.png -quality 60 output.avif

# WebP to PNG (for editing)
magick input.webp output.png

# JPEG to WebP
magick input.jpg -quality 82 output.webp

# Batch convert all PNGs in a directory to WebP
magick mogrify -format webp -quality 82 *.png

The mogrify subcommand is the batch version of magick. It processes files in place (or writes to a new format alongside the original with -format). Useful when you have a directory full of PNGs from an AI generation session.

AVIF note: not all ImageMagick builds include AVIF support. Test yours with:

magick identify -list format | grep AVIF

If nothing comes back, your build doesn't have the AVIF delegate. You can either build ImageMagick from source with libheif support, or use standalone tools like cavif or the libavif CLI utilities.

Combining it into a script

Here is a minimal Node.js script that takes a source PNG and a slug name, then generates the full set: favicon.ico, apple-touch-icon, PWA icons, hero image, and OG card.

import { execSync } from 'node:child_process';
import { unlinkSync } from 'node:fs';

const src = process.argv[2];
const slug = process.argv[3];
if (!src || !slug) {
  console.error('Usage: node make-brand-images.mjs source.png my-brand');
  process.exit(1);
}

const run = cmd => execSync(cmd, { stdio: 'pipe' });

// Favicon set (multi-size .ico)
run(`magick "${src}" -resize 16x16 favicon-16.png`);
run(`magick "${src}" -resize 32x32 favicon-32.png`);
run(`magick "${src}" -resize 48x48 favicon-48.png`);
run(`magick favicon-16.png favicon-32.png favicon-48.png favicon.ico`);
['favicon-16.png', 'favicon-32.png', 'favicon-48.png'].forEach(f => {
  try { unlinkSync(f); } catch {}
});

// Apple touch icon + PWA icons
run(`magick "${src}" -resize 180x180 apple-touch-icon.png`);
run(`magick "${src}" -resize 192x192 icon-192.png`);
run(`magick "${src}" -resize 512x512 icon-512.png`);

// Hero image (1600x900, WebP)
run(`magick "${src}" -quality 82 -resize 1600x900^ -gravity center -extent 1600x900 ${slug}-hero.webp`);

// OG social card (1200x630, WebP)
run(`magick "${src}" -quality 82 -resize 1200x630^ -gravity center -extent 1200x630 ${slug}-og.webp`);

console.log(
  'Done. Files: favicon.ico, apple-touch-icon.png, icon-192.png, icon-512.png, '
  + slug + '-hero.webp, ' + slug + '-og.webp'
);

Save it as make-brand-images.mjs and run it:

node make-brand-images.mjs my-logo-1024.png my-brand

Six files out. One command in. That is the entire brand-image pipeline for a new site.

Common mistakes

Using convert instead of magick. The convert command is ImageMagick v6. It still works on some systems, but v7 deprecated it. Use magick.

Forgetting the ^ on -resize. Without the caret, -resize 1600x900 fits the image inside the box, leaving empty space (letterboxing). With the caret, it fills the box. You almost always want the caret when you are cropping to exact dimensions.

Using -resize 32x32! with the exclamation mark. The ! flag ignores aspect ratio and stretches the image to fit. Your icon will look squished or stretched. For square icons from a square source, it doesn't matter. For rectangular crops, it ruins the output.

Saving favicon.ico from a single size. A favicon.ico with only a 32px image looks blurry in contexts that expect 48px and pixelated in contexts that expect 16px. Always bundle at least 16, 32, and 48.

Not declaring apple-touch-icon in HTML. If you generate the file but forget the <link> tag, iOS silently falls back to a screenshot of your page. The icon will be a tiny, unreadable rendering of whatever was on screen.

Committing the raw AI PNG to the repo instead of the converted WebP. AI-generated PNGs are typically 2-8 MB. The WebP conversion at quality 82 brings that down to 80-200 KB. Committing the PNG bloats your deploy and slows page load.

Related reading

Fact-check notes and sources

  • ImageMagick command-line documentation: imagemagick.org/script/command-line-processing.php
  • Apple touch icon specification: developer.apple.com/design/human-interface-guidelines/app-icons
  • PWA icon requirements and manifest.json: web.dev/articles/add-manifest
  • WebP quality benchmarks and encoding guidance: developers.google.com/speed/webp/docs/cwebp

This post is informational, not design advice. Mentions of ImageMagick, Midjourney, and Ideogram are nominative fair use. No affiliation is implied.

The full brand-asset pipeline, from AI image generation through to a deployed site with working favicons, social cards, and hero images, is covered step by step in The $97 Launch. It is one of the practical setup chapters that most "start a website" tutorials skip entirely.

← Back to Blog

Accessibility Options

Text Size
High Contrast
Reduce Motion
Reading Guide
Link Highlighting
Accessibility Statement

J.A. Watte is committed to ensuring digital accessibility for people with disabilities. This site conforms to WCAG 2.1 and 2.2 Level AA guidelines.

Measures Taken

  • Semantic HTML with proper heading hierarchy
  • ARIA labels and roles for interactive components
  • Color contrast ratios meeting WCAG AA (4.5:1)
  • Full keyboard navigation support
  • Skip navigation link
  • Visible focus indicators (3:1 contrast)
  • 44px minimum touch/click targets
  • Dark/light theme with system preference detection
  • Responsive design for all devices
  • Reduced motion support (CSS + toggle)
  • Text size customization (14px–20px)
  • Print stylesheet

Feedback

Contact: jwatte.com/contact

Full Accessibility StatementPrivacy Policy

Last updated: April 2026