FreeToolio

PNG to ICO

Drop a PNG and get a favicon back. This page draws your image at each size you tick, then writes the .ico container itself: a 6-byte header, 16 bytes of directory per entry, then the images. Transparency survives, a non-square picture is centred on a transparent square, and the largest entry is 256 px because the format cannot address more. No upload, no library, no account.

Drop a PNG here

or choose a file · one image per icon · up to 100 MP

    PNG in, ICO out · 16 to 256 px · transparency kept · no upload · no account · no watermark

    PNG to ICO: One File, Four Pictures

    Drop a PNG here, tick the sizes you need, and download a favicon. The picture is drawn again at each size you tick; the .ico container around those pictures is written by this page, byte by byte, in the tab.

    An ICO is not an image format in the way PNG is. It is a small directory of images, each stored at its own size, and the reader — a browser tab, Explorer, the taskbar — picks whichever one fits the space it has. That is why a 1,200 × 800 PNG of 158,345 bytes became a 64,394-byte icon holding four separate pictures, and why most of that file is one of them.

    A 64,394-byte ICO split into its parts: the 16 px entry is 1,128 bytes, the 32 px entry 4,264, the 48 px entry 9,640 and the 256 px entry 49,292, with a 70-byte directory listing them. The 256 px entry alone is 76.5% of the file.
    One 1,200 × 800 PNG, four entries, 64,394 bytes. Bar length is bytes: the 256 px entry takes 49,292 of them, 76.5%, while the three smaller entries together are 15,032. The directory — a 6-byte header plus 16 bytes per entry, 70 bytes in all — is too thin to draw.

    The file is a directory, not a picture

    Six bytes open the file: a zero, a one (this is an icon, not a cursor), and the number of pictures inside. Then sixteen bytes per picture, in order: its width, its height, a palette count, two reserved bytes, the colour planes, the bits per pixel, the payload's byte count and where the payload starts. Only after that directory does the image data begin.

    Four pictures therefore cost 6 + 4 × 16 = 70 bytes of directory, and the first payload starts at offset 70. The page reports that number on the card under every result, because it is the only part of the file that is not a picture.

    Two quirks live in the width byte. It is one byte, so it holds 1 to 255; 256 is written as 0 by convention. That is the whole reason an ICO cannot hold a 512 px image: there is nowhere to put the number. Height is stored in its own byte with the same rule.

    What each entry weighs

    The four default entries for the 1,200 × 800 photograph, with the encodings the page chose for each:

    Entry Payload Bytes Share of the file
    16 × 16 32-bit BMP 1,128 1.8%
    32 × 32 32-bit BMP 4,264 6.6%
    48 × 48 32-bit BMP 9,640 15.0%
    256 × 256 PNG 49,292 76.5%
    Directory — 70 0.1%
    File 64,394

    The BMP rows are arithmetic, not luck. A 32-bit entry is a 40-byte header, four bytes per pixel, and a one-bit-per-pixel mask whose rows are padded to four bytes:

    • 16 px: 40 + 1,024 + 64 = 1,128
    • 32 px: 40 + 4,096 + 128 = 4,264
    • 48 px: 40 + 9,216 + 384 = 9,640
    • 256 px: 40 + 262,144 + 8,192 = 270,376

    Parsed back out of the file, the 256 px BMP entry is exactly 270,376 bytes, and its header stores a height of 512 — double the picture's, because the format expects an XOR bitmap followed by the AND mask. Its mask alone is 8,192 bytes: 32 bytes per row across 256 rows.

    PNG or uncompressed, per entry

    The same four sizes, re-encoded as PNG payloads, came out at 526, 1,038, 2,059 and 49,292 bytes. PNG wins at every size here — by 602 bytes at 16 px, by 3,226 at 32 and by 7,581 at 48.

    Which makes the default choice a compatibility choice, not a size choice. PNG-compressed entries arrived with Windows Vista; the uncompressed BMP form predates them, and some old shells and icon editors still expect it at small sizes. The default therefore keeps BMP up to 48 px and switches to PNG at 64 and above. The measured cost of that convention on this file: 64,394 bytes against 52,985 for an all-PNG icon, 11,409 bytes more, or 21.5%. Choose "PNG in every entry" if size is what you care about.

    All four uncompressed entries would have made a 285,478-byte file. The 256 px BMP alone accounts for 270,376 of that, 94.7%.

    A wide picture cannot fill a square entry

    Every entry is square. A 3:2 photograph drawn into a 256 × 256 entry occupies 256 × 171 pixels, and the leftover 85 rows are padding: 43 above the picture, 42 below it, 21,760 transparent pixels in all.

    The same arithmetic repeats at each size, and the page's output shows it in the padding rows of each BMP entry:

    Entry Picture inside Clear rows above Clear rows below
    256 × 256 256 × 171 43 42
    48 × 48 48 × 32 8 8
    32 × 32 32 × 21 6 5
    16 × 16 16 × 11 3 2

    Padding is transparent by default, so nothing is added to the picture. Pick white or black instead and those bands fill with that colour; on the same photo, a white background shrank the 256 px PNG entry from 49,292 to 49,236 bytes because flat colour compresses better than a hard edge against transparency.

    If a square icon is what you actually want, crop the source first. Padding preserves the whole picture and shrinks its importance at 16 px, where a wide logo becomes a thin stripe.

    Transparency survives, at 32 bits per pixel

    A 512 × 512 cut-out logo with a transparent surround became a 20,708-byte icon. Its 256 px payload is a PNG of 5,606 bytes; the three BMP entries are the fixed sizes above. Parsed back, the 256 px entry has 32,535 fully clear pixels out of 65,536 — 49.6% of the square — and the colour values under them are untouched, because 32-bit BMP carries an alpha byte per pixel alongside the mask.

    At small sizes the alpha stops being binary. The 16 px entry holds 46 distinct alpha values, the 32 px entry 71, the 48 px entry 115: downscaling mixes opaque edges with clear surround, and rounding produces partial transparency. That is the correct result, not damage.

    The mask is written anyway, one bit per pixel with a set bit for anything below half opacity, because readers that ignore the alpha channel fall back to it.

    Six sizes, one file

    Ticking all six sizes produced an 81,711-byte icon: directory 102 bytes, then 1,128 + 4,264 + 9,640 + 3,298 + 13,987 + 49,292. The two middle entries, 64 and 128 px, add 17,285 bytes between them.

    Ticking 256 px on a small source does not add detail. A 64 × 64 PNG produced a 256 px PNG entry of 6,824 bytes — bigger than the four entries around it, and still a 64 px picture, enlarged. The card names the source dimensions so the mismatch is visible before the download.

    What the icon does not carry

    The PNG's own chunks do not cross over. A canvas holds pixels, so an iCCP colour profile, a gAMA chunk, text chunks and an eXIf block are simply not written into the new file; the page reports which of them the source had, in the line under the file name. What comes out is 8-bit sRGB pixels per entry, with a colour type of RGB if every pixel ended up opaque and RGBA if any transparency survived.

    Animation does not survive either. An APNG source is decoded at its first frame, and the icon built from it is still.

    Why nothing leaves the tab

    One script, already loaded with the page. During a conversion the network panel recorded 0 requests, and the same file converted with the connection switched off produced the same 64,394 bytes, SHA-256 identical to the online run.

    Everything the tool needs is in the browser: createImageBitmap decodes the PNG, a canvas redraws it at each size, canvas.toBlob produces the PNG payloads, and the BMP payloads and the container are assembled in this script.

    What each control does

    Sizes written into the file. Six boxes, 16 to 256 px. Each ticked size becomes one entry; 16, 32, 48 and 256 are ticked by default because that covers a favicon trio plus the large Windows view.

    Entry encoding. Auto keeps BMP up to 48 px and PNG above it; the other two options force one form everywhere, which is how the size differences above were measured.

    Padding colour. Transparent, white, black or any colour. It fills the square outside a non-square picture, and it flattens transparency if you choose a colour.

    When an ICO is the wrong file

    A modern browser accepts an SVG favicon and scales it perfectly at every size, which no ICO can do past 256 px. If the site needs a touch icon or a web app manifest, those want PNG files at 180, 192 and 512 px, and an ICO cannot hold them. macOS application icons are .icns, a different container again.

    Use the ICO when the destination is Windows — a shortcut, a folder, an executable's resource, or the favicon.ico that older browsers still request first.

    Quick answers

    Does one entry hold several sizes? No. Each entry is one picture at one size; the file holds the set. A 256 px entry is not a 256 px image that shrinks on demand — it is one of four separate images.

    Why does the 16 px entry look different from the 48 px one? Each is drawn separately from the source at its own size, so fine detail survives in the large entry and disappears in the small one. That is intended: a 16 px icon is a design of its own.

    Can the icon be bigger than 256 px? No. The directory stores width and height in one byte each, with 0 meaning 256, so there is no way to write 512. Larger sizes belong in PNG files referenced from the page.

    Is the transparency really kept? Yes, both ways: a 32-bit alpha channel per pixel and a mask for readers that ignore alpha. A 49.6%-transparent logo stayed 49.6% clear in the 256 px entry.

    Does the source's colour profile come along? No. An iCCP chunk in the source is reported on the card and then dropped; the output is 8-bit sRGB.

    What happens to a non-square picture? It is centred and the leftover bands are padding, transparent or filled with the colour you pick. Nothing is cropped and nothing is stretched.

    Can I drop a JPEG or a WebP? They decode, but the card can only report PNG chunks for a PNG source. For a JPEG logo the honest route is to convert it to PNG first and check it at 16 px.

    What if the connection drops mid-way? Nothing changes. The bytes are already in memory, so a dropped connection cannot interrupt the build: with the network switched off, the same file produced the same 64,394 bytes.