Skip to content

Dim artwork on an opaque black background keeps a translucent background square and isn't cropped, contrary to "a region that flattens to black is fully transparent" #121

Description

@matt-edmondson

What's wrong

When an input's brightest opaque pixel is below 255, the offset normalization lifts every opaque pixel by 255 - maxValue, black included. True black ends up with non-zero coverage, so the background stays partly opaque and the crop can't trim it.

Where

IconHelper/IconHelper.cs, NormalizedIntensity (around lines 263-285):

return (byte)(255 - (maxValue - pixel.R));   // pixel.R == 0 -> 255 - maxValue, not 0

The coverage and bounding-box pass (around lines 325-336) then treats those pixels as visible.

This contradicts CLAUDE.md:91 and the README: "A region that flattens to black comes out fully transparent and falls outside the crop". The existing test DropsUnlitArtworkFromTheCoverage only covers inputs where a white patch pins maxValue at 255, where the offset is 0.

Failure scenario

Reproduced with a throwaway test against the current code: an 80×80 opaque-black canvas with a 40×40 square of (80,80,80) in the middle. After the contrast filter the grey is about 105, so maxValue = 105.

Expected Actual
Output size 40×40 80×80
Corner alpha 0 150

In practice, any dark icon on a black background, including every JPEG input (no alpha channel), comes out as a translucent full square.

Suggested fix

This needs a deliberate choice, because the "offset, not scale" rationale is documented in the README:

  • Option A: keep the offset but pin true black: pixel.R == 0 ? 0 : 255 - (maxValue - pixel.R). Near-black anti-aliasing still carries the offset.
  • Option B: scale instead (pixel.R * 255 / maxValue). Black stays 0, but edge gradients are stretched.

Whichever is chosen, update the README, CLAUDE.md, gold masters and the README line about dim artwork being "translucent throughout". Add a test with dim artwork on opaque black that checks the output is cropped to the artwork and the corners are transparent.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions