Skip to content

Fix MMCQ bounds - #12

Open
mezz wants to merge 1 commit into
SvenWoltmann:masterfrom
mezz:master
Open

Fix MMCQ bounds#12
mezz wants to merge 1 commit into
SvenWoltmann:masterfrom
mezz:master

Conversation

@mezz

@mezz mezz commented Jul 20, 2026

Copy link
Copy Markdown

I found a minor bounds issue that could cause problems with classifying single-color images.

I decided to add some tests that cover this case, and clean up a little.
Java version is bumped up to Java 8.

Details

In MMCQ.vboxFromPixels, it builds the initial color-space box by scanning pixels and finding min/max quantized values for red, green, and blue. Before the fix, each channel did:

if (value < min) {
    min = value;
} else if (value > max) {
    max = value;
}

For the first pixel in a solid non-black image, value < min is true, so the else if never runs. If every pixel has the same value, max never gets updated from 0. A solid red image could end up with red bounds like rmin = 31, rmax = 0, which is an invalid/inverted box.
The fix was to make min and max independent checks in MMCQ.java, so a single pixel can establish both bounds.

Impact

  • Dominant color/palette extraction could return incorrect colors for uniform red, green, blue, gray, etc.
  • The bug was especially visible for one-color images because there was no later different pixel to update max.

Failing tests that are now working:

  • ignoresPixelsBelowAlphaThresholdForAbgr
    • Only the opaque blue pixel survives filtering. With one surviving pixel, bmin is set but bmax stays 0, so the VBox is invalid and the average comes back [4, 4, 128] instead of blue [0, 0, 255].
  • keepsPixelsAtAlphaThresholdForAbgr
    • Same issue, but for a single threshold-alpha red pixel. It returns [128, 4, 4] instead of red [255, 0, 0].
  • ignoresWhitePixelsWhenRequested
    • reported first White is filtered out, leaving only the red pixel. With one remaining color sample, max bounds are not set, so it returns [128, 4, 4].
  • keepsWhitePixelsWhenNotIgnored
    • reported first The first pixel is white, then red. Because min/max were mutually exclusive, parts of the bounds end up excluding the white histogram bucket, so the palette collapses to one color instead of two.

@mezz mezz changed the title Fix ColorThief MMCQ bounds Fix MMCQ bounds Jul 20, 2026
@mezz

mezz commented Jul 24, 2026

Copy link
Copy Markdown
Author

@SvenWoltmann sorry for the ping, this might be hidden since it's not an active project

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant