Image Trace: presets trace at Paths 50 with new Corners and Noise

Every built-in preset other than Auto Color and Flat Logo now traces at
Paths 50. Corners is 100 in Technical Drawing, 75 in Default, Black and
White Logo, Line Art and Outline, and 50 in the others. Noise is 1 px in
Technical Drawing, 5 in High Fidelity Photo, 10 in Low Fidelity Photo, 15
in 3 Colors, 6 Colors, 16 Colors and Shades of Gray, 20 in Sketched Art,
Line Art and Outline, 25 in Default and Black and White Logo, and 90 in
Silhouettes. Palettes, color counts and the other options are unchanged.

This changes the output of every preset but Default, Auto Color and Flat
Logo. The traces take fewer anchors (High Fidelity Photo 5,494 to 3,136
and Black and White Logo 27 to 14 in crates/trace/tests/quality), and
outlines on flat art lie further from the true edge (16 Colors 0.100 to
0.123 px off on average).

Docs: docs/image-trace-adjustments.md, docs/image-trace-quality.md,
docs/target-app-parity.md.
This commit is contained in:
dotCooCoo
2026-11-13 17:13:52 -08:00
parent 0b29b2b1f6
commit 815c772a46
6 changed files with 94 additions and 16 deletions
+4 -3
View File
@@ -288,8 +288,9 @@ fn trace_library(c: &str, s: &Session, params: &mut tr::TraceParams) -> Result<V
/// The most anchor points an Image Trace may make, a guard for memory: a trace past it is refused
/// with advice instead (#525). A trace keeps about 90 bytes an anchor in the document (measured on
/// code-drawn photos of 2000 × 2000 to 6000 × 4000 pixels), so 8,000,000 anchors are about
/// 0.7 GB, with a peak of about 1 GB while tracing: a 4000 × 3000 photo at High Fidelity Photo
/// makes about 1.9 million, and even at Paths 100, Noise 1 and every tone about 7.9 million. On the
/// 0.7 GB, with a peak of about 1 GB while tracing: a 4000 × 3000 photo at Limited 64 colors, Paths
/// 90, Corners 25 and Noise 4 makes about 1.9 million, and even at Paths 100, Noise 1 and every tone
/// about 7.9 million. On the
/// web, where a page has at most 4 GB of memory, the limit stays at 2,000,000.
#[cfg(not(target_arch = "wasm32"))]
pub const MAX_TRACE_ANCHORS: usize = 8_000_000;
@@ -1135,7 +1136,7 @@ mod trace_limit_tests {
assert_eq!(w, ["Flat Logo traced the image at 946 × 710 pixels, averaged down from 16000 × 12000."]);
}
// A 4000 × 3000 photo at High Fidelity Photo makes about 1.9 million anchors, which must fit;
// A 4000 × 3000 photo at Limited 64 colors, Paths 90 and Noise 4 makes about 1.9 million anchors, which must fit;
// the limit still guards memory (about 90 bytes an anchor). Checked when the tests build.
const _: () = assert!(MAX_TRACE_ANCHORS >= 2_000_000 && MAX_TRACE_ANCHORS <= 16_000_000);
}
+12 -12
View File
@@ -241,19 +241,19 @@ pub fn preset(name: &str) -> Option<TraceParams> {
// many as its tones need where it is not.
// (Color detail 85: a colour on a hundredth of the picture is still one of its colours.)
"auto color" => TraceParams { palette: Palette::Automatic, color_detail: 85.0, ..color(6, 65.0, 60.0, 16, Method::Abutting) },
"high fidelity photo" => color(64, 90.0, 25.0, 4, Method::Overlapping),
"low fidelity photo" => color(20, 60.0, 50.0, 12, Method::Overlapping),
"3 colors" => color(3, 60.0, 60.0, 20, Method::Abutting),
"6 colors" => color(6, 65.0, 60.0, 16, Method::Abutting),
"16 colors" => color(16, 70.0, 55.0, 10, Method::Abutting),
"shades of gray" => TraceParams { mode: Mode::Grayscale, colors: 8, paths: 60.0, corners: 50.0, noise: 10, method: Method::Overlapping, ..d },
"black and white logo" => bw(128, 95.0, 80.0, 8, true),
"sketched art" => bw(150, 50.0, 50.0, 100, false),
"silhouettes" => bw(200, 40.0, 60.0, 30, false),
"line art" => bw(128, 80.0, 70.0, 10, false),
"technical drawing" => bw(128, 95.0, 90.0, 4, true),
"high fidelity photo" => color(64, 50.0, 50.0, 5, Method::Overlapping),
"low fidelity photo" => color(20, 50.0, 50.0, 10, Method::Overlapping),
"3 colors" => color(3, 50.0, 50.0, 15, Method::Abutting),
"6 colors" => color(6, 50.0, 50.0, 15, Method::Abutting),
"16 colors" => color(16, 50.0, 50.0, 15, Method::Abutting),
"shades of gray" => TraceParams { mode: Mode::Grayscale, colors: 8, paths: 50.0, corners: 50.0, noise: 15, method: Method::Overlapping, ..d },
"black and white logo" => bw(128, 50.0, 75.0, 25, true),
"sketched art" => bw(150, 50.0, 50.0, 20, false),
"silhouettes" => bw(200, 50.0, 50.0, 90, false),
"line art" => bw(128, 50.0, 75.0, 20, false),
"technical drawing" => bw(128, 50.0, 100.0, 1, true),
// Black outlines: lines as stroked centre lines, wider areas as stroked outlines.
"outline" => TraceParams { fills: false, strokes: true, ..bw(128, 80.0, 70.0, 10, false) },
"outline" => TraceParams { fills: false, strokes: true, ..bw(128, 50.0, 75.0, 20, false) },
// Flat-colour logos: colours found automatically, edges placed to a fraction of a pixel.
"flat logo" => TraceParams { mode: Mode::Logo, colors: 8, paths: 60.0, corners: 50.0, noise: 6, snap_curves_to_lines: true, ..d },
_ => return None,
+29
View File
@@ -892,6 +892,35 @@ fn presets_resolve() {
assert!(preset("nope").is_none());
}
#[test]
fn presets_have_their_paths_corners_and_noise() {
let expected: &[(&str, f64, f64, u32)] = &[
("Default", 50.0, 75.0, 25),
("High Fidelity Photo", 50.0, 50.0, 5),
("Low Fidelity Photo", 50.0, 50.0, 10),
("3 Colors", 50.0, 50.0, 15),
("6 Colors", 50.0, 50.0, 15),
("16 Colors", 50.0, 50.0, 15),
("Shades of Gray", 50.0, 50.0, 15),
("Black and White Logo", 50.0, 75.0, 25),
("Sketched Art", 50.0, 50.0, 20),
("Silhouettes", 50.0, 50.0, 90),
("Line Art", 50.0, 75.0, 20),
("Technical Drawing", 50.0, 100.0, 1),
("Outline", 50.0, 75.0, 20),
];
for &(name, paths, corners, noise) in expected {
let p = preset(name).unwrap();
assert_eq!((p.paths, p.corners, p.noise), (paths, corners, noise), "{name}");
}
// The color counts stay as they were.
let colors: Vec<u32> = ["High Fidelity Photo", "Low Fidelity Photo", "3 Colors", "6 Colors", "16 Colors", "Shades of Gray"]
.iter()
.map(|n| preset(n).unwrap().colors)
.collect();
assert_eq!(colors, [64, 20, 3, 6, 16, 8]);
}
#[test]
fn params_json_roundtrip_and_partial() {
let p = preset("6 Colors").unwrap();
+9 -1
View File
@@ -18,6 +18,13 @@ its current location. Opening the controls does not add a document undo step.
| Create | Fills / Strokes | Creates filled areas, stroked lines, or both. |
| Ignore Color | Color picker | Leaves out the selected color (white by default). |
The built-in presets other than Auto Color and Flat Logo all use Paths 50. Corners is 100 in
Technical Drawing, 75 in Default, Black and White Logo, Line Art and Outline, and 50 in the others.
Noise is 1 px in Technical Drawing, 5 in High Fidelity Photo, 10 in Low Fidelity Photo, 15 in 3 Colors,
6 Colors, 16 Colors and Shades of Gray, 20 in Sketched Art, Line Art and Outline, 25 in Default and
Black and White Logo, and 90 in Silhouettes (see
[image-trace-quality.md](image-trace-quality.md#preset-paths-corners-and-noise)).
Sliders apply on release, and their numeric fields can be edited directly. Each committed
adjustment re-traces the selected object as one undo step and changes the preset to Custom.
While dragging, the preset and Enhanced row stay in place until release so the
@@ -123,7 +130,8 @@ color is averaged down further: the factor doubles until at most 150,000 remain
most 16,384 pixels (at most six times). A trace that would
make more than 8,000,000 anchor points (2,000,000 on the web) is refused to protect memory, with advice:
raise Noise, lower Paths or Colors, or pick a lower-fidelity preset. A trace keeps
about 90 bytes an anchor; a 4000 × 3000 photo at High Fidelity Photo makes about 1.9 million.
about 90 bytes an anchor; a 4000 × 3000 photo at Limited 64 colors, Paths 90, Corners 25 and Noise 4
makes about 1.9 million.
**Tracing in the background.** On the desktop a trace runs on a thread of its own, so the window
keeps answering while a photo or a large image is traced (#3098). Make, Make and Expand, the task
bar's Image Trace and the panel's Trace and presets start it. The status bar says "Tracing the
+39
View File
@@ -82,6 +82,9 @@ gradient, texture, sensor noise):
(The last two rows were measured without a limit; they are refused now.) The 4000 × 3000 High Fidelity
Photo trace was 86,000 anchors under the old limit; a noisier scan of the same size would have been
refused. At 8,000,000 anchors a trace keeps about 0.7 GB, with a peak of about 0.9 GB while tracing.
The preset rows were measured with the earlier preset values: High Fidelity Photo at Paths 90, Corners 25
and Noise 4, Low Fidelity Photo at Paths 60, Noise 12 and 16 Colors at Paths 70, Corners 55 and Noise 10
(see [Preset Paths, Corners and Noise](#preset-paths-corners-and-noise)).
## Collapsed loops keep few segments
A small closed loop (or a piece that returns to its own junction) whose fit collapsed to a single
cubic cannot stay as one, so it kept every positioned point as a straight segment. A looser Paths
@@ -225,6 +228,42 @@ in a smooth area), `a_staircase_that_runs_on_from_a_smooth_area_into_an_edge_kee
`a_staircase_of_mixed_one_pixel_and_longer_steps_is_one_slope_without_a_notch`,
`a_run_of_two_steps_keeps_its_corners`, `a_junction_on_a_step_ends_the_staircase_there` and
`a_step_whose_cracks_read_as_an_edge_ends_the_staircase_there`.
## Preset Paths, Corners and Noise
Every built-in preset other than Auto Color and Flat Logo traces at Paths 50. Corners and Noise are:
| preset | Paths | Corners | Noise | before |
|:--|--:|--:|--:|:--|
| Default | 50 | 75 | 25 | unchanged |
| High Fidelity Photo | 50 | 50 | 5 | 90, 25, 4 |
| Low Fidelity Photo | 50 | 50 | 10 | 60, 50, 12 |
| 3 Colors | 50 | 50 | 15 | 60, 60, 20 |
| 6 Colors | 50 | 50 | 15 | 65, 60, 16 |
| 16 Colors | 50 | 50 | 15 | 70, 55, 10 |
| Shades of Gray | 50 | 50 | 15 | 60, 50, 10 |
| Black and White Logo | 50 | 75 | 25 | 95, 80, 8 |
| Sketched Art | 50 | 50 | 20 | 50, 50, 100 |
| Silhouettes | 50 | 50 | 90 | 40, 60, 30 |
| Line Art | 50 | 75 | 20 | 80, 70, 10 |
| Technical Drawing | 50 | 100 | 1 | 95, 90, 4 |
| Outline | 50 | 75 | 20 | 80, 70, 10 |
The palettes, color counts, thresholds and other options of the presets did not change.
Measured with the harness below (section 1, each preset on the inputs it is meant for), before and after:
anchors fall in 10 of the 12 changed presets, for example 5,494 to 3,136 (High Fidelity Photo), 33 to 27
(16 Colors), 27 to 14 (Black and White Logo) and 43 to 28 (Line Art); Silhouettes rises from 13 to 15 and
Sketched Art does not change. Outlines on flat art lie further from the true edge: off mean 0.100 to 0.123
px (16 Colors), 0.101 to 0.119 (6 Colors), 0.104 to 0.129 (3 Colors), 0.064 to 0.092 (Black and White Logo)
and 0.056 to 0.074 (Line Art), and off max 1.00 to 1.16 px in 6 Colors and 16 Colors. Technical Drawing
leaves 1.4 specks (was 0.5), and Outline's stroked centre lines lie 0.095 px off (was 0.086) with 2.7
anchors a stroke (was 3.0). ΔE changes by 0.01 or less except Line Art and Outline (2.62 and 2.61 to 2.66
and 2.67); edge ΔE rises in 8 of the 12, for example 4.79 to 5.25 (16 Colors), 3.98 to 4.46 (3 Colors) and 9.46 to 10.03
(Black and White Logo). On synthetic shapes and photos of 300 to 4,000 px traced outside this harness,
High Fidelity Photo makes 41% fewer anchors and 16 Colors 15% fewer; the mean pixel difference of each
trace changes by −0.23 to +0.25 of a level; 16 Colors leaves 91 staircases of steps of 2 px or more where it left 85, and High
Fidelity Photo 473 where it left 461. The tables below are the previous measurement, not a rerun.
Test: `presets_have_their_paths_corners_and_noise` in `crates/trace/src/tests.rs`.
## A simpler contour walk
`contour::trace_mask` follows each region's outline along the pixel cracks with the inside on the
right. It used to build a table of outgoing directions for every pixel corner in a raster pass and
File diff suppressed because one or more lines are too long