/v1/digitize collapses 4-color input to single white color — multi-color quantization broken #38

Open
opened 2026-09-29 21:07:41 +00:00 by Mark · 0 comments
Owner

Bug: /v1/digitize collapses multi-color PNGs to a single white color when the white background touches all non-background pixels

Reproduction (verified 2026-09-25)

Upload pil_4color.png (200x200, 4 colored quadrants on white background):

  • Red (255,0,0) at [10,10]–[95,95]
  • Green (0,200,0) at [105,10]–[190,95]
  • Blue (0,0,255) at [10,105]–[95,190]
  • Yellow (255,255,0) at [105,105]–[190,190]
  • White (255,255,255) background

Service returned:

{
  "regions": 1,
  "stitchObjects": 1,
  "stats": {"totalStitches": 628500, "colorCount": 1, "processingMs": 8649}
}

Single stitch object: type=tatami_fill thread=#ffffff stitches=628500

The 4 colored regions were all merged into one giant white fill — color quantization didn't fire.

Expected

A real digitizer with a 4-color input should return at least 4 stitch objects (one per non-background color). On the Brother PR-10 catalog (60+ thread entries) the expected output would be:

  • Red region → thread 027 Crimson Red
  • Green region → thread 207 Christmas Green
  • Blue region → thread 006 Blue
  • Yellow region → thread 205 Lemon Yellow
  • White background → thread 001 White

Why this matters

The whole product premise is "auto-digitize a multi-color image into stitchable thread objects." If 4 colored quadrants on a white background collapse to one white fill, the front-end will:

  1. Show "1 color used" stats to the user
  2. Render a single white fill where there should be 4 distinct colored regions
  3. Save the design with colorCount: 1
  4. Export a single-color PES that ignores the input colors entirely

Comparison: same service on the project fixtures works correctly

  • simple_square.png (black 50px square on white 100x100): 2 regions, 2 stitch objects, 2 colors (black + white). ✅
  • solid_orange_box_64x64.png (orange 64x64 on white): 2 regions, 2 stitch objects, 2 colors (black + orange). ✅

The difference: the project fixtures have only one non-background color. The 4-color fixture has four. The service appears to be treating multi-color inputs as if they were single-color.

Likely cause (not verified — would need source read)

Hypothesis from symptom shape: color quantization merges everything that touches the background border into the background color. The four quadrants each share an edge with the white background, so they get absorbed into the white region. Single-color fixtures don't trigger this because the only non-background region is the inner shape, which also touches the border — but in those cases the inner color wins somehow because there's only one competing color.

Alternative hypothesis: the service is running color reduction but at a higher level than expected (e.g., posterizing to 2 colors regardless of maxColors setting). The maxColors: 10 setting was honored in the fixtures but ignored in the multi-color case.

Severity

High. This is the single most important product feature. A user uploads a logo with 4 colors, sees a single white fill, assumes the digitizer is broken, and leaves. The "auto-digitize" product is non-functional for any input with more than one non-background color.

Reproduction script

import json, urllib.request, socket
socket.setdefaulttimeout(120)
from PIL import Image, ImageDraw
img = Image.new("RGB", (200, 200), (255, 255, 255))
d = ImageDraw.Draw(img)
d.rectangle([10, 10, 95, 95], fill=(255, 0, 0))
d.rectangle([105, 10, 190, 95], fill=(0, 200, 0))
d.rectangle([10, 105, 95, 190], fill=(0, 0, 255))
d.rectangle([105, 105, 190, 190], fill=(255, 255, 0))
img.save("/tmp/test.png")
# upload /tmp/test.png via /v1/digitize with settings from tests/manual/smoke_digitize.py
# observe: colorCount == 1, only white stitch object returned

Labels

  • bug
  • triage-approved
  • back-end

Filed 2026-09-25 by user-driven bughunt session.

## Bug: /v1/digitize collapses multi-color PNGs to a single white color when the white background touches all non-background pixels ### Reproduction (verified 2026-09-25) Upload `pil_4color.png` (200x200, 4 colored quadrants on white background): - Red (255,0,0) at [10,10]–[95,95] - Green (0,200,0) at [105,10]–[190,95] - Blue (0,0,255) at [10,105]–[95,190] - Yellow (255,255,0) at [105,105]–[190,190] - White (255,255,255) background Service returned: ```json { "regions": 1, "stitchObjects": 1, "stats": {"totalStitches": 628500, "colorCount": 1, "processingMs": 8649} } ``` Single stitch object: `type=tatami_fill thread=#ffffff stitches=628500` The 4 colored regions were all merged into one giant white fill — color quantization didn't fire. ### Expected A real digitizer with a 4-color input should return at least 4 stitch objects (one per non-background color). On the Brother PR-10 catalog (60+ thread entries) the expected output would be: - Red region → thread 027 Crimson Red - Green region → thread 207 Christmas Green - Blue region → thread 006 Blue - Yellow region → thread 205 Lemon Yellow - White background → thread 001 White ### Why this matters The whole product premise is "auto-digitize a multi-color image into stitchable thread objects." If 4 colored quadrants on a white background collapse to one white fill, the front-end will: 1. Show "1 color used" stats to the user 2. Render a single white fill where there should be 4 distinct colored regions 3. Save the design with `colorCount: 1` 4. Export a single-color PES that ignores the input colors entirely ### Comparison: same service on the project fixtures works correctly - `simple_square.png` (black 50px square on white 100x100): 2 regions, 2 stitch objects, 2 colors (black + white). ✅ - `solid_orange_box_64x64.png` (orange 64x64 on white): 2 regions, 2 stitch objects, 2 colors (black + orange). ✅ The difference: the project fixtures have only **one** non-background color. The 4-color fixture has **four**. The service appears to be treating multi-color inputs as if they were single-color. ### Likely cause (not verified — would need source read) Hypothesis from symptom shape: color quantization merges everything that touches the background border into the background color. The four quadrants each share an edge with the white background, so they get absorbed into the white region. Single-color fixtures don't trigger this because the only non-background region is the inner shape, which also touches the border — but in those cases the inner color wins somehow because there's only one competing color. Alternative hypothesis: the service is running color reduction but at a higher level than expected (e.g., posterizing to 2 colors regardless of `maxColors` setting). The `maxColors: 10` setting was honored in the fixtures but ignored in the multi-color case. ### Severity **High.** This is the single most important product feature. A user uploads a logo with 4 colors, sees a single white fill, assumes the digitizer is broken, and leaves. The "auto-digitize" product is non-functional for any input with more than one non-background color. ### Reproduction script ```python import json, urllib.request, socket socket.setdefaulttimeout(120) from PIL import Image, ImageDraw img = Image.new("RGB", (200, 200), (255, 255, 255)) d = ImageDraw.Draw(img) d.rectangle([10, 10, 95, 95], fill=(255, 0, 0)) d.rectangle([105, 10, 190, 95], fill=(0, 200, 0)) d.rectangle([10, 105, 95, 190], fill=(0, 0, 255)) d.rectangle([105, 105, 190, 190], fill=(255, 255, 0)) img.save("/tmp/test.png") # upload /tmp/test.png via /v1/digitize with settings from tests/manual/smoke_digitize.py # observe: colorCount == 1, only white stitch object returned ``` ### Labels - bug - triage-approved - back-end Filed 2026-09-25 by user-driven bughunt session.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Mark/easystitch-service#38
No description provided.