Turning a photo into a cross stitch pattern in the browser: Wu quantization, CIEDE2000 and no dithering
Cross stitch patterns are just tiny images: one square of fabric, one stitch, one color of thread. So "photo to pattern" sounds like a resize and a palette swap. It mostly is, and the parts that make it hard taught me a
Cross stitch patterns are just tiny images: one square of fabric, one stitch, one color of thread. So "photo to pattern" sounds like a resize and a palette swap. It mostly is, and the parts that make it hard taught me a few useful things about color and images. Here's how the converter I built works. It runs entirely in the browser, so the photo never leaves the user's machine.
1. One pixel per stitch
The first step is the boring one: scale the photo so that one pixel is one stitch. A pattern 140 stitches wide gets a 140-pixel-wide image. Everything after this works on that small grid, which is why the whole pipeline runs in milliseconds even on a phone.
2. Reduce the colors first, then match to thread
Embroidery floss comes in fixed colors. The DMC range has around 500, and nobody wants to buy 500 skeins, so a pattern needs to use maybe 15 to 40 of them.
The naive approach is to snap every pixel straight to its nearest DMC color. That gives you far too many colors and no control over how many. Instead:
- Reduce the photo's own colors to N using Wu's color quantizer (via the MIT-licensed
image-qlibrary). Wu's method is fast and keeps the colors that cover lots of pixels, which is what you want for stitching. - Match each of those N colors to the nearest DMC floss. Two palette colors sometimes land on the same floss, and when that happens they merge.
- Assign every stitch to the nearest color in that small floss palette.
3. "Nearest" means perceptual distance, not RGB distance
Measuring color distance in RGB is a classic trap. Two colors can be close in RGB numbers and look clearly different to a person, or the other way round. So colors are converted from sRGB to CIE Lab (D65 white point), a space designed so that distances roughly match what people see.
There are two formulas in use:
- CIEDE2000 for choosing which floss represents each palette color. It's the most accurate standard color-difference formula, and it's also expensive. That's fine here, because it runs only N Γ ~500 times.
- Plain Lab distance (CIE76) for assigning each of the tens of thousands of stitches to one of the N chosen floss. That step is fast, and with only a few dozen well-separated candidates the cheaper formula picks the same answer almost every time.
If you implement CIEDE2000 yourself, test it against the published test pairs in Sharma, Wu & Dalal (2005). The formula has several places where a sign or a hue-angle wrap goes wrong silently.
4. No dithering
In normal image work, dithering is how you hide a small palette: scatter pixels of two colors so the eye blends them. For stitching it's the worst possible choice. Every isolated pixel becomes a single stitch that needs its own start and stop of thread. So the converter deliberately does no dithering, and you accept some banding in exchange for a pattern that's pleasant to stitch.
5. Count and clean up the "confetti"
Even without dithering, photos (fur especially) produce lots of confetti: single stitches whose eight neighbors are all other colors. This is the biggest complaint stitchers have about computer-generated patterns, so the tool measures it and shows it up front:
Easy to stitch Β· 19 colors Β· <1% confetti
The count is simple: for every stitched cell, check its 8 neighbors; if none share its color, it's confetti. The percentage is confetti over stitched cells. From our own side-by-side tests, under about 5% feels calm to stitch and over about 12% means constant thread changes. These are working numbers, not science, so the raw percentage is always shown too.
The basic clean-up is one pass of a majority rule. Each confetti stitch takes the color that most of its stitched neighbors share, but only if at least 3 of them share it, and the pass reads from the old grid and writes to a new one so the result doesn't depend on scan order. Stronger levels go further: they flood-fill small same-color patches (up to 2, 3 or 5 stitches touching edge to edge) and merge each patch into the color that borders it most. Afterwards, any floss that no longer has stitches is dropped, and the remaining ones are sorted by stitch count and given chart symbols in that order.
6. Skein counts from geometry
A pattern also needs a shopping list. On fabric with count holes per inch, a stitch has side s = 2.54 / count cm. A full cross uses two diagonals on the front (2β2Β·s) and roughly two sides on the back (2Β·s). Add 50% for tails and travel between stitches. A DMC skein is 8 m of six strands, so stitched two strands at a time it gives 24 m of working thread.
That works out to about 1,830 stitches per skein on 14-count with 2 strands, within 3% of the old needlework rule of thumb "stitches per skein = 255 Γ count Γ· strands" (1,785). It's reassuring when first principles agree with decades of stitchers' experience.
Try it
The tool is The Cross Stitch Pattern Maker. Disclosure: I built it. You upload a photo, see the stitchability check before anything else, and get a symbol chart, a DMC floss list with skein counts and a printable PDF. The first PDF is free and there's no sign-up. If you only want the size and floss math, there's also a standalone cross stitch calculator.
I'd love to hear from anyone who has worked on palette reduction for physical media (beads, LEGO mosaics, knitting), because the "no dithering, fewer isolated pixels" trade-off shows up everywhere.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.