You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Saved icons have RGB 0,0,0 in every fully transparent pixel, undoing the flat colour fill, so straight-alpha filtering gives dark fringes #161
The processing step paints every pixel's RGB with the target colour, "transparent pixels included", so that filtering never blends a different colour into the edges (IconHelper.cs:392-400). CLAUDE.md and README.md:221 promise the same. However, the shared encoder throws that work away at save time:
Clear rewrites every alpha-0 pixel to transparent black. In addition, CropSquareAndResize pads the canvas with Rgba32.ParseHex("00000000") (L416), so the padding is black as well.
Reproduction
Input: a 300×200 anti-aliased white ellipse on a transparent background. Run iconhelper -i in -o out --color "#3080FF" --size 64.
Output pixel census:
alpha 255, rgb (48,128,255): 1,977 pixels
partial alpha, rgb (48,128,255): 203 pixels
alpha 0, rgb (0,0,0): 1,916 pixels
Expected: rgb (48,128,255) in every pixel.
Upscaling the output 4× with bilinear filtering and no alpha premultiplication, which is how a straight-alpha GPU texture is sampled, made 2,899 of 6,190 edge pixels darker than the target colour.
The in-memory pipeline is fine: the resize premultiplies, and alpha values survive exactly. The loss happens only in the encoder and in the padding colour.
Why it matters
These icons are meant for apps such as ImGui and game engines, which often sample textures in straight alpha with bilinear filtering or mipmaps. A black RGB in the transparent area bleeds into the edges as a dark halo, which is exactly the artefact the flat colour field was added to prevent.
Suggested fix
Set TransparentColorMode = PngTransparentColorMode.Preserve.
Pad with the target colour at alpha 0 (new Rgba32(colorR, colorG, colorB, 0)) instead of 00000000.
Regenerate the gold masters. Files may grow slightly, because the colour field no longer compresses as runs of zeros.
Acceptance: every pixel of an output PNG, including alpha-0 and padding pixels, has the target RGB. Add a test that asserts this on a sample with transparent margins and non-zero --padding.
Priority: Medium. Output icons show dark fringes when they are sampled in straight alpha (ImGui, game engines), which contradicts the flat-colour promise in README and CLAUDE.md. The fix is two lines (PngTransparentColorMode.Preserve and target-RGB padding) plus regenerated gold masters.
Area:IconHelper/IconHelper.cs: the shared PNG encoder settings (L28-33) and the CropSquareAndResize padding colour (L416).
Activity
matt-edmondson commentedon Oct 30, 2026
Triage
PngTransparentColorMode.Preserveand target-RGB padding) plus regenerated gold masters.IconHelper/IconHelper.cs: the shared PNG encoder settings (L28-33) and theCropSquareAndResizepadding colour (L416).--color) also touches colour handling, so watch for gold-master conflicts. Output PNGs keep the source's ICC profile, gAMA and EXIF orientation, so icons processed with the same --color render in different colours and rotations #126 (open; ICC/gAMA/EXIF kept in output) also concerns encoder metadata, and the two could share the encoder change.TransparentColorModeor the padding colour.Generated by Claude Code