What happens to semi-transparent PNG pixels in small ICO frames?
A PNG to ICO conversion can preserve alpha while changing stored RGB: our same-size control kept alpha 128 but changed red from 208 to 207, and the transparent-blue background produced the same decoded pixels as the transparent-black control. These results apply only to the three saved sources and this browser run.
Convert a PNG with the tested tool, or inspect the saved files below. This experiment tests semi-transparent color and edge samples; it does not repeat the rectangular-padding measurements.
The color changed before any size reduction
The uniform source is a 64 x 64 PNG filled with RGBA [208,48,32,128]. Its saved ICO is 4,285 bytes. The center of every extracted frame reads [207,48,32,128], including the 64px frame that matches the source dimensions. Alpha stayed at 128; the red channel decreased by one. A resizing-only explanation cannot account for that same-size observation. The files establish the change, but this experiment does not isolate which browser decode, canvas or encode stage caused it.
The other two sources contain the same 30 x 30 semi-transparent red square at source coordinates x=17..46, y=17..46. Outside it, hidden-blue stores [0,0,255,0], while hidden-black stores [0,0,0,0]. Those invisible RGB values differ in the saved source PNGs. Both downloaded ICOs are 5,801 bytes. Every decoded output pixel matches between the pair at every selected size: zero differing RGBA pixels in each of the seven frame comparisons. That is a controlled result for these files, not a guarantee about all transparent images.
The left-quarter sample deliberately crosses the square's edge as the frame size changes. At 16px its coordinate is (4,8), and the pixel reads [207,48,32,96]. At 24px, (6,12) reads [209,50,33,77]. At 32px, (8,16) reads [207,48,32,64]. The 48px frame at (12,24) reads [206,49,36,21]. These are stored PNG values read after extraction, not colors estimated from a checkerboard preview. Different sample positions explain why they are not a fixed-point color history.
| Source | Decoded frame | Payload offset | Payload bytes | Center RGBA | Edge sample x,y | Edge RGBA | Alpha min..max |
|---|---|---|---|---|---|---|---|
| uniform-half | 16 x 16 | 118 | 122 | 207,48,32,128 | 4,8 | 207,48,32,128 | 128..128 |
| uniform-half | 24 x 24 | 240 | 137 | 207,48,32,128 | 6,12 | 207,48,32,128 | 128..128 |
| uniform-half | 32 x 32 | 377 | 136 | 207,48,32,128 | 8,16 | 207,48,32,128 | 128..128 |
| uniform-half | 48 x 48 | 513 | 240 | 207,48,32,128 | 12,24 | 207,48,32,128 | 128..128 |
| uniform-half | 64 x 64 | 753 | 283 | 207,48,32,128 | 16,32 | 207,48,32,128 | 128..128 |
| uniform-half | 128 x 128 | 1036 | 872 | 207,48,32,128 | 32,64 | 207,48,32,128 | 128..128 |
| uniform-half | 256 x 256 | 1908 | 2377 | 207,48,32,128 | 64,128 | 207,48,32,128 | 128..128 |
| hidden-blue | 16 x 16 | 118 | 189 | 207,48,32,128 | 4,8 | 207,48,32,96 | 0..128 |
| hidden-blue | 24 x 24 | 307 | 207 | 207,48,32,128 | 6,12 | 209,50,33,77 | 0..128 |
| hidden-blue | 32 x 32 | 514 | 200 | 207,48,32,128 | 8,16 | 207,48,32,64 | 0..128 |
| hidden-blue | 48 x 48 | 714 | 308 | 207,48,32,128 | 12,24 | 206,49,36,21 | 0..128 |
| hidden-blue | 64 x 64 | 1022 | 301 | 207,48,32,128 | 16,32 | 0,0,0,0 | 0..128 |
| hidden-blue | 128 x 128 | 1323 | 1153 | 207,48,32,128 | 32,64 | 0,0,0,0 | 0..134 |
| hidden-blue | 256 x 256 | 2476 | 3325 | 207,48,32,128 | 64,128 | 0,0,0,0 | 0..137 |
| hidden-black | 16 x 16 | 118 | 189 | 207,48,32,128 | 4,8 | 207,48,32,96 | 0..128 |
| hidden-black | 24 x 24 | 307 | 207 | 207,48,32,128 | 6,12 | 209,50,33,77 | 0..128 |
| hidden-black | 32 x 32 | 514 | 200 | 207,48,32,128 | 8,16 | 207,48,32,64 | 0..128 |
| hidden-black | 48 x 48 | 714 | 308 | 207,48,32,128 | 12,24 | 206,49,36,21 | 0..128 |
| hidden-black | 64 x 64 | 1022 | 301 | 207,48,32,128 | 16,32 | 0,0,0,0 | 0..128 |
| hidden-black | 128 x 128 | 1323 | 1153 | 207,48,32,128 | 32,64 | 0,0,0,0 | 0..134 |
| hidden-black | 256 x 256 | 2476 | 3325 | 207,48,32,128 | 64,128 | 0,0,0,0 | 0..137 |
For the uniform source, the table's equal alpha minimum and maximum show that the whole frame stayed semi-transparent. For the square sources, clear background pixels and partially covered edge pixels coexist. Merely finding a transparent corner would miss that distinction. Our decoder saved all pixels, so the pair comparison includes invisible background pixels rather than comparing only the painted area.
Take the saved pixels apart
Download the complete experiment. Source files and browser downloads remain separate, so the comparison can be checked without trusting this page's illustration.
- uniform-half: source PNG; actual downloaded ICO; extracted 16px PNG; all RGBA pixels.
- hidden-blue: source PNG; actual downloaded ICO; extracted 16px PNG; all RGBA pixels.
- hidden-black: source PNG; actual downloaded ICO; extracted 16px PNG; all RGBA pixels.
Frame measurements · Blue-versus-black comparison · Source provenance · ICO decoder · Pixel comparison script · Source generator.
Recalculate from the downloads
- Install Python with Pillow. Run make_sources.py in an empty folder to regenerate the three source PNGs, or use the original source downloads.
- Open the linked PNG to ICO tool, choose one source and keep its seven displayed frame sizes selected. Create the ICO and save it. Repeat for the other sources. No source file is sent to a conversion server.
- Run the decoder on each saved ICO. It checks the ICO header, payload ranges and PNG dimensions, then writes extracted PNGs and a compressed pixel CSV.
- Put the two decoded folders beside compare.py and run the comparison. Compare decoded RGBA, not just ICO file hashes: compression differences can change bytes without changing pixels.
python -m pip install pillow python decode_ico.py hidden-blue.ico --out decoded-hidden-blue python decode_ico.py hidden-black.ico --out decoded-hidden-black python compare.py
Answers that follow from these controls
Did the converter turn half transparency into full opacity?
No: the uniform control's decoded alpha was 128 throughout every saved frame. That observation comes from its full alpha histogram. It does not establish the treatment of a different source, an operating system's icon display, or another converter.
Did invisible blue cause a blue fringe here?
No difference appeared between the blue-background and black-background controls in the decoded output. Both source backgrounds had alpha zero; only their stored RGB differed. The downloadable comparison counts every RGBA pixel instead of relying on how the icon looks against one background.
Why can an edge pixel have a lower alpha than the center?
The saved edge samples have lower alpha than the square's center, while the uniform image does not acquire that edge. This separates a boundary effect from a global alpha reduction. The exact filtering mechanism was not isolated, so this page reports the observed coordinates and values without assigning a universal resampling rule.
Should a one-channel difference be called a failed conversion?
It is a measured difference, not proof that the file is unusable. Here the same-size control establishes that byte-for-byte source color preservation was not achieved. Whether that matters for a particular icon needs a separate display test; no Windows installation or Google favicon appearance test was performed.
What the competitor reading did and did not establish
On the measurement day we re-read the PNG-to-ICO pages at cloudconvert.com, freeconvert.com and convertio.co. They provide conversion controls or format descriptions; the latter two describe transparency. In those three inspected pages we did not find this same-source hidden-RGB control pair, downloaded per-frame RGBA records, and a script comparing every decoded pixel. This is a limited comparison of the saved pages, not a claim that their tools fail or that no other site has tested alpha.
Scope of the run
All three sources were created locally and converted with SVGtopix's existing PNG-to-ICO tool on October 30 2026. The tool requested high-quality canvas smoothing and wrote PNG-backed ICO frames. The result files, their sizes and their pixel records were read from actual browser downloads. Browser implementations and PNG encoders can differ. The source PNGs contain no color profile; profiled input, legacy bitmap ICO frames and animated input were not tested.
Known boundary: these controls verify saved PNG-backed frames, not the background composition or frame selection of an installed icon.