Convert ICO to PNG
Pull an image out of an icon file, at the largest size somebody put in it.
How it works
An icon file is a small archive. The directory at its head points at anywhere from one to a couple of dozen separate pictures, and the sizes it carries were decided by whoever built it rather than by any standard. Microsoft's App Certification Kit ships an appicon.ico holding thirteen images across five sizes, 256 down to 16 pixels, with each of the four smaller sizes stored three times over at different colour depths. The favicon generator here describes the directory's own byte layout; this page is about what those entries point at.
The payload shape that breaks extractors
The older of the two shapes is where extraction goes wrong. A pre-Vista entry holds a BITMAPINFOHEADER with the fourteen-byte file header stripped off, so the payload is not a valid BMP and no decoder will open it as one. The header also lies about its own height, declaring exactly twice the real value. Underneath the colour rows sits a second bitmap at one bit per pixel: the AND mask, which marks each pixel as opaque or transparent. The 1995 format had no alpha channel, so transparency travelled separately, and the doubled height covers both bitmaps at once.
Extract such a payload without correcting that field and the result is an image twice as tall as it should be, the picture in the top half and a band of black or speckled noise across the bottom. The band is the mask, being read as though it were part of the picture. The arithmetic is exact and worth checking against any icon you have: a 16-pixel 32-bit entry occupies 1,128 bytes, being 40 of header, 1,024 of colour and 64 of mask. A 256-pixel entry occupies 270,376 bytes, of which 8,192 go on a mask that a 32-bit payload never consults.
What the PNG payload removed
Windows Vista allowed an entry to hold a complete PNG file, signature and all. The whole legacy apparatus then disappears in one step: alpha comes from the PNG's own channel, the mask is gone, rows stop being stored bottom-up, and 256 pixels of artwork costs kilobytes instead of a quarter of a megabyte. Unity's Windows player template icon carries nine bitmap entries and weighs 562,718 bytes. OneCommander ships an icon of fifteen PNG entries, one of them a 256, in 48,089 bytes. Both figures come from reading the two directories in this session.
When the chosen entry is already a PNG, its bytes are copied out untouched, so the download is bit-for-bit what the icon's author compressed and no re-encode is spent on it. A legacy entry is rebuilt instead: the file header is restored, the doubled height corrected, and for payloads below 32 bits the mask is read back and applied as alpha, because that is the only place the transparency exists. Where one size is stored at several depths, the deepest payload wins, so a 16-pixel slot held at both 4 and 32 bits gives up the 32-bit version.
The size you get is the size somebody put in
Extraction cannot invent detail. A 16-pixel entry is 256 pixels of information in total, and no upscaler will recover a logo from it, so the largest entry present sets the ceiling. Read the result note before concluding that an icon was low resolution: it lists every size the directory declared, and a file whose first entry is 16 pixels often carries a 256-pixel PNG further down. Chrome's own createImageBitmap, handed a whole icon, decodes one entry without saying which, and on a multi-size file that is usually the 16-pixel one.
Questions
How do I get every image out rather than one?
Run it twice, once on each setting, which covers the two ends people want. A single conversion returns a single PNG on purpose: the download and the handoff to the next tool are both one image, and a tool that sometimes emits a ZIP instead cannot honestly tell the chain what it produces. The result note names every size inside the file, so you can see what a second pass would give you before spending it.
Does anything about my file reach a server?
No, and the Network panel will show it. Open developer tools, keep the panel recording, then drop the icon in. The requests listed are this page's own code fetched from this origin, including the wasm PNG encoder, and every one is a GET for a static asset. None of them carries icon bytes, because the decode and encode both happen inside a Web Worker in this tab and there is no endpoint on the other end to receive anything.
The extracted image has a solid background where it should be see-through.
That is a dropped AND mask, and it happens with 1, 4, 8 and 24-bit entries, whose colour data has no alpha channel at all. An extractor that reads only the colour rows produces an opaque rectangle filled with whatever colour sat behind the artwork, commonly black or magenta. The mask is read here and applied as alpha, and the result note says so when it did something. A 32-bit entry needs none of this and is passed through as it stands.
Will this open a .cur cursor file?
Yes. A cursor uses the same directory and the same two payload shapes, differing in a type field of 2 rather than 1, and in the two entry fields an icon spends on colour planes and bit depth: a cursor stores its hotspot coordinates there instead. The hotspot is where the click lands, so it is discarded on the way out, and the picture is extracted the same way an icon's is.