Skip to content

Dev Pitfalls #1: Your ICO Looks Fine — Until You Inspect the BMP Frames

2026-06-03

Tags: Windows · Dev Pitfalls


This isn't a Store certification horror story. It's a quieter kind of trap — one I walked into purely out of curiosity.

I had been generating .ico files the same lazy way for years: grab a 256×256 PNG, drop it into some random online converter, and grab the output. It always looked right in Explorer, so I never thought twice.

Then one day, while building an ICO unpacking tool and testing it against other products' icon files, I found something ugly.

What I Found

An ICO file is a container. It can hold multiple images at different sizes (16×16, 32×32, 48×48, 64×64, 128×128, 256×256) so Windows can pick the right one for each context — the taskbar, the title bar, Alt+Tab, File Explorer.

In my ICO file, every single frame looked fine at a glance. But when I inspected closer:

  • The 256×256 frame (stored as PNG) — perfect. Proper alpha channel, smooth edges, no artifacts.
  • Every smaller BMP frame — transparency was completely botched. The alpha channel was either absent or contained garbage data. Semi-transparent pixels were turned into solid blocks with weird color halos.

The smaller ones looked like a bad chroma key job from the 90s.

Why Online Converters Mess This Up

Most free PNG-to-ICO converters work like this:

  1. Take your 256×256 PNG and downscale it to each required size (16, 32, 48, etc.)
  2. Save the 256×256 frame as PNG
  3. Save the smaller frames as 32-bit BMP

However, the BMP format inside ICO files is special. It doesn't use the fancy BITMAPV5HEADER — it uses the standard 40-byte BITMAPINFOHEADER, with biBitCount set to 32. Each pixel's 4th byte is the alpha channel. And here's the catch: after the color pixel data (XOR mask), there must be a 1-bit monochrome transparency mask (AND mask) for legacy compatibility. The biHeight in the header must also be set to double the actual image height to account for this AND mask.

Many online converters fail right here:

  • They declare 32-bit color but fill every pixel's alpha byte (the 4th byte) with 0x00 (fully transparent) or random garbage data
  • The AND mask they generate is completely out of sync with the alpha channel data

The result: a file that looks valid — the directory entries are correct, the sizes are right, Explorer doesn't complain — but when Windows tries to render the smaller frames, the GDI blending goes haywire. You get mysterious halos, transparent pixels that aren't actually transparent, and other rendering artifacts.

Why You Won't Notice Until It's Too Late

Windows Explorer and most apps prefer the 256×256 PNG frame for display. Since that one is untouched, the icon looks flawless in every normal view — large icons, properties dialog, even the taskbar preview.

The broken BMP frames only surface when Windows needs to downscale to a specific smaller size. For example:

ContextSize UsedLikely Frame
File Explorer (extra large)256×256PNG ✓
File Explorer (large/medium)48×48BMP ✗
Title bar / small icon16×16BMP ✗
Alt+Tab switcher32×32BMP ✗

So your app's icon might look perfect on the desktop but develop a mysterious "halo" or messed-up transparency in the title bar or task switcher. Most people blame Windows rendering. Nope — it's the ICO.

How to Check Your ICO Files

Use an ICO analyzer tool that can list all frames in an ICO file. Look for:

  • Frame format: The 256px frame should say PNG. Smaller frames should say BMP. Using PNG for all frames is technically valid per the ICO spec, but may cause compatibility issues on older Windows versions. A mix of PNG (256px) + BMP (smaller sizes) is the safest choice.
  • BMP bit depth: Smaller frames should be 32 BPP for true alpha channel support (semi-transparent blending). If a frame shows 24 BPP, it has lost per-pixel alpha data — it can still fall back to the ICO's legacy 1-bit AND mask for basic "all-or-nothing" background clipping, but all anti-aliased edges, semi-transparent gradients, and shadows will break, turning into ugly solid artifacts or thick black borders on modern systems.
  • Visual inspection: Load each frame individually. The smaller frames should have proper smooth alpha, not jagged edges or solid backgrounds.

How to Fix It

Option 1: Use a proper icon editor and test your converter

Take your source PNG and create a fresh ICO with a proper editor that handles the BMP alpha channel correctly. Before trusting any converter — whether online or offline — run a test: generate an ICO from a PNG with known semi-transparent areas (soft shadows, gradients, etc.), then inspect every frame. If any BMP frame has broken alpha, that converter is not safe to use.

Option 2: PNG-only ICO (when possible)

Some modern tools accept ICO files that use PNG compression for all frames, not just 256×256. This completely avoids the BMP alpha problem. However, this isn't universally supported by all Windows versions or applications — test before relying on it.

Key Takeaways

  • Just because an ICO looks fine in Explorer doesn't mean it is fine
  • The 256×256 PNG frame is usually correct; every smaller BMP frame could be broken
  • Broken BMP alpha is invisible in most views — it only bites you in title bars, Alt+Tab, and other small-icon contexts
  • Test your online converter with a known semi-transparent PNG before relying on it
  • Use a proper icon editor for anything you ship — it's worth the 5 minutes

This article is part of the Dev Pitfalls series.