Since Windows Vista, an image in an ICO file can be a complete, unchanged PNG file instead of a bitmap. The directory entry works the same way, its size and offset pointing at the PNG’s bytes.
Telling a PNG from a bitmap
There is no flag. A reader looks at the first bytes of the image: the eight-byte PNG
signature means a PNG, and anything else is read as a
bitmap, which normally starts with
28 00 00 00, the 40 of biSize.
89 50 4E 47 0D 0A 1A 0A
Microsoft did not use the BI_PNG compression value of a bitmap header for
this, because a value icon tools did not recognise broke them.
What is different
| Part | In a PNG image |
|---|---|
| DIB header | None: the bytes are a PNG file, from its signature to its IEND chunk. |
| Doubled height | None: the height in the PNG’s IHDR chunk is the real height. |
| AND mask | None: Windows derives the mask from the alpha channel when it needs one. |
| Colour format | 32-bit RGBA; Windows expects a 32-bit ARGB image, so this is what writers use. |
| True size and depth | Read them from the PNG’s IHDR, not the directory. |
In practice
Writers keep the smaller images as uncompressed bitmaps, so older versions of Windows can
still read them, and store only the large images, typically 256 × 256 (bWidth
and bHeight 0), as PNG. Windows before Vista cannot read a PNG image.