Skip to content

Image Trace: Flat Logo traces a gray between black and white as one shape - #7451

Merged
bflatastic merged 3 commits into
storytold:mainfrom
dotCooCoo:fix/flat-logo-gray-between-black-and-white
Nov 14, 2026
Merged

bflatastic merged 3 commits into
storytold:mainfrom
dotCooCoo:fix/flat-logo-gray-between-black-and-white

Conversation

@dotCooCoo

Copy link
Copy Markdown
Contributor

What and why

With a gray among Flat Logo's colors, an anti-aliased edge pixel of black on white is also a mix of black and gray, or of gray and white. The unmixing took the mix with the smallest error, which often held the gray, so a black disc beside a gray square on white traced the gray as the square plus 8 to 24 thin slivers around the disc (colors found automatically or named exactly; grays 230 and 200, sharp and slightly soft edges, measured on main at f062dd7ed2).

  • crates/trace/src/logo/unmix.rs: when another mix of two classes also reproduces an edge pixel, the pixel takes that mix if its classes lie nearer in the flat areas within 6 pixels, and the pixel has a neighbor on each side of the left-out class along the line between the other two. A gray stroke on white has no darker neighbor and keeps its gray.
  • A pixel within a few levels of a class keeps the class when it is one of at least 13 such pixels joined together, so a one-pixel gray line between black and white stays gray.
  • A flat area whose color lies between two classes (colors named some levels off) counts as holding the classes of its mix, and so do the pixels of exactly its color joined to it.
  • Changed behavior: pixel values within a few levels of one color now count toward the 150,000-value limit when they lie outside a flat area (count_ambiguous), since unmix checks them too. A busy image can therefore be averaged down sooner than before.
  • crates/trace/src/logo/pipeline.rs: whether a hard-edged image is softened is still judged from each pixel's best mix, so the pixels that take another mix do not change that decision.
  • docs/image-trace-adjustments.md describes the behavior and its limits, and docs/target-app-parity.md has one line for it.

Limits, stated in the docs:

  • The slivers are removed around sharp edges and edges blurred by up to about half a pixel (measured at blur 0.6). An edge blurred by a pixel or more, or pixel noise of a level or more, can still leave some.
  • These now trace as black and white: a one-pixel gray line between black and white shorter than 13 pixels, or one that falls between pixels or is blurred; a soft-edged gray stroke about two pixels wide that touches black; and most or all of a soft-edged stroke about three pixels wide that touches black, 12 pixels long or less.

How it was tested

New tests in crates/trace/src/logo/tests.rs, all drawn in code: the disc and square with grays 230 and 200, sharp and blurred, colors found, named and named 52 levels off; a one-pixel gray line between black and white; gray strokes touching the disc; gray stripes beside a black disc with colors named off; thin gray strokes near black; and the disc and a mid-gray square with 2 levels of noise. Unit tests in unmix.rs cover the mix choice, the 13-pixel line and the row distances.

With the switch disabled, the touching-stroke, disc-and-square, edge-pixel and column tests fail. With the softening judged from the switched pixels instead, the noise test fails with 27 gray paths.

Focused checks on Linux, on the head 3ea1524618. The branch is one commit on main at f062dd7ed2 and merges cleanly with main at 1e4e3534f5; the merged tree was checked as well.

  • cargo test -p vectorcraft-trace: 285 + 1 + 2 + 11 passed, 0 failed, 3 ignored
  • cargo test -p vectorcraft-engine trace: 53 passed, 0 failed
  • cargo fmt --all -- --check
  • cargo clippy -p vectorcraft-trace --all-targets -- -D warnings
  • cargo check --workspace --tests
  • Merged with main at 1e4e3534f5: cargo check --workspace --tests, cargo clippy -p vectorcraft-trace --all-targets -- -D warnings, cargo test -p vectorcraft-trace (337 + 1 + 2 + 11 passed, 0 failed, 3 ignored) and cargo test -p vectorcraft-engine trace (56 passed, 0 failed)
  • cargo xtask ci runs in this pull request's CI.

Checklist

  • cargo xtask ci passes (fmt, clippy, tests, assets, brands, layers, wasm).
  • No panics in shipped code: no unwrap(), expect(), panic!, unreachable!, todo! or
    unimplemented! outside tests, and no unchecked indexing on data from files, parameters or
    messages. Errors are returned as Result and shown to the user
    (why and how).
  • Clean-room: nothing copied from Adobe products or GPL/AGPL code (AGENTS.md).
  • Every new asset has a row in ASSETS.md.

…hape

With a gray among the colors, an anti-aliased edge pixel of black on
white is also a mix of black and gray, or of gray and white, and the
unmixing took the mix with the smallest error, which often held the
gray. A black disc and a gray square on white traced the gray as the
square plus 8 to 24 slivers around the disc, with the colors found or
named exactly.

When another mix of two classes also reproduces an edge pixel, the pixel
now takes it if that mix's classes lie nearer in the flat areas around
the pixel and the pixel has a neighbor on each side of the left-out
class, along the line between the other two. Pixels within a few levels
of a class outside a flat area are checked the same way, and they now
count toward the number of pixel values that decides when a busy image
is averaged down further. A flat area that stands for no class, as with
colors named some levels off, counts as holding the classes of its mix,
and so do the pixels of exactly its color joined to it. Whether a
hard-edged image is softened is still judged from each pixel's best mix.

The slivers are removed around sharp edges and edges blurred by up to
about half a pixel; an edge blurred by a pixel or more, or pixel noise
of a level or more, can still leave some. Gray strokes two and three
pixels wide beside black stay gray, and so does a one-pixel gray line
between black and white of at least 13 joined pixels. These trace as
black and white: a shorter one-pixel line, or one that falls between
pixels or is blurred; a soft-edged gray stroke about two pixels wide
touching black; and most or all of a soft-edged stroke about three
pixels wide touching black, 12 pixels long or less.

Docs: docs/image-trace-adjustments.md, docs/target-app-parity.md.
@coderabbitai

coderabbitai Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 18 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

Run configuration

Commits

Reviewing files that changed from the base of the PR and between a47d7ee and 9f253e0.

Files selected for processing: 5

  • crates/trace/src/logo/pipeline.rs
  • crates/trace/src/logo/tests.rs
  • crates/trace/src/logo/unmix.rs
  • docs/image-trace-adjustments.md
  • docs/target-app-parity.md
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@bflatastic
bflatastic merged commit d4982ef into storytold:main Nov 14, 2026
7 checks passed
@bflatastic

Copy link
Copy Markdown
Member

Merged, thanks @dotCooCoo! It passed its CI checks.

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.

2 participants