Image Trace: edges to a fraction of a pixel in Black and White, Grayscale and Color

Each crack between an inside and an outside pixel is moved to where the pixels across it say the edge is (the
blend of the two tones in the column of pixels across the crack; a thin line by the centroid and sum of its
tone; hard-edged images are read as staircases), and the outline is fitted as Flat Logo mode fits its own:
corners put back, straight runs as lines, a round outline as a circle, the rest as few curves as Paths allows.
Snap Curves To Lines straightens slightly curved runs and makes arcs. A fit that strays from its outline
gives way to a plainer one, and at last to the outline's own points.

On each preset's own inputs, all sizes and variants (docs/image-trace-quality.md):
- Default: outlines 0.313 -> 0.091 px off on average, largest 1.51 -> 1.02; edge error 17.2 -> 10.1;
  gaps between abutting paths 63.5 -> 22.2 px, overlaps 67.0 -> 22.4 px
- Black and White Logo: 0.270 -> 0.064 px off, kinks 15.3 -> 0.3, anchors 3.78 -> 2.73 times the art's
- Technical Drawing: 0.201 -> 0.086 px off; Line Art: 0.158 -> 0.093
- Worse: anchors on blurred and scanned thin lines (Line Art 25 -> 77 on average), High Fidelity Photo
  (colour error 2.30 -> 2.50, anchors 46,866 -> 81,597, 1 megapixel photo-like image 0.37 -> 1.98 s)
This commit is contained in:
bflatastic committed 2026-10-13 01:55:17 +07:00
1 parent a17e3057de
commit fcd7e3b42d
9 files changed
+826 -326

No files matched your search

+2 -1
View File
@@ -6,7 +6,7 @@
**Stage: alpha** · next: beta, ~13 points (ready for real work ~62% → ~75%, and reliable `.ai` exchange) and ~170–270 h away
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (Transform dialogs preview and the transform tools act on direct-selected anchors, #1412 and #1408; `.ai` compound path paint, #1410, overprint, #1388, and text-only PDF parts, #1387; community PRs: strokes wider than their shape, corner drags without the bounding box, pasted pictures, compound paths in `document.inspect`, MCP guide; headline numbers unchanged; community PRs: `.ai` editing-data follow-ups (gradient stops, type of objects with an appearance, short area-type frames), PDF bleed with editing data, dialog keyboard focus, art flush with an artboard, font rescan, symbol instance redraw, `--control` port check; headline numbers unchanged; Rectangular Grid and Polar Grid tool options, #1377 in part; `.ai` files with placed (linked) pictures open from their editing data, #1264; community PRs: `.ai` and PDF bleed and editing-data import, gradient shapes imported as paths, ruler origin, Align To, Live Corners corner selection; headline numbers unchanged; G2: Film Grain added; Photoshop effects 29/57; 28 filters remain; community PRs: graph designs, Graph Data worksheet and Graph Type options; Align both centres; Pen endpoint fixes; earlier: Effect › Brush Strokes landed: Photoshop-style filters 28 of 57, raster effects 40% → 48%; `.ai` gradients, meshes and artboard names from the editing data; headline numbers unchanged; `.ai` art styles and clipping fills from the editing data; headline numbers unchanged; `editingData: "always"`; headline numbers unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (Image Trace places edges to a fraction of a pixel, measured in `docs/image-trace-quality.md`, headline numbers unchanged; Transform dialogs preview and the transform tools act on direct-selected anchors, #1412 and #1408; `.ai` compound path paint, #1410, overprint, #1388, and text-only PDF parts, #1387; community PRs: strokes wider than their shape, corner drags without the bounding box, pasted pictures, compound paths in `document.inspect`, MCP guide; headline numbers unchanged; community PRs: `.ai` editing-data follow-ups (gradient stops, type of objects with an appearance, short area-type frames), PDF bleed with editing data, dialog keyboard focus, art flush with an artboard, font rescan, symbol instance redraw, `--control` port check; headline numbers unchanged; Rectangular Grid and Polar Grid tool options, #1377 in part; `.ai` files with placed (linked) pictures open from their editing data, #1264; community PRs: `.ai` and PDF bleed and editing-data import, gradient shapes imported as paths, ruler origin, Align To, Live Corners corner selection; headline numbers unchanged; G2: Film Grain added; Photoshop effects 29/57; 28 filters remain; community PRs: graph designs, Graph Data worksheet and Graph Type options; Align both centres; Pen endpoint fixes; earlier: Effect › Brush Strokes landed: Photoshop-style filters 28 of 57, raster effects 40% → 48%; `.ai` gradients, meshes and artboard names from the editing data; headline numbers unchanged; `.ai` art styles and clipping fills from the editing data; headline numbers unchanged; `editingData: "always"`; headline numbers unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
VectorCraft is a clean-room, open-source, pure-Rust reimplementation of the Adobe Illustrator workflow. It runs
on macOS, Windows, Linux, FreeBSD and the web (WASM), and agents can drive all of it over MCP, the CLI and a JSON
@@ -127,6 +127,7 @@ Ranked; detail in [docs/roadmap.md](docs/roadmap.md) and [docs/gaps.md](docs/gap
| Date | What landed |
|---|---|
| 2026-10-13 | Image Trace traces anti-aliased and blurred images to a fraction of a pixel in Black and White, Grayscale and Color, with corners put back, straight edges as lines and round outlines as circles; a harness measures every preset before and after ([`docs/image-trace-quality.md`](docs/image-trace-quality.md)): outlines 0.31 → 0.09 px off on average (Default), 0.27 → 0.06 (Black and White Logo). |
| 2026-10-12 | Effect › 3D and Materials: Extrude & Bevel (depth, twist, taper, solid or hollow caps, five bevel shapes with repeat, spacing, inside and both sides), Inflate (volume, both sides) and Rotate, with Position presets and the rotation and light gizmos; live, exported as vector faces, expandable (#1407). |
| 2026-10-12 | `convert --editing-data` (`editingData: "always"`) opens a `.ai` from its editing data even where its page, which can be older, draws differently, with a note. |
| 2026-10-12 | `.ai` import reads an object's art style (a fill and a stroke, variable widths too, with an Outer Glow or Drop Shadow) as its own appearance, paints a clipping path's own fill under what it clips and keeps a group's transparency as its PDF part draws them. |
+47 -80
View File
@@ -1,9 +1,11 @@
//! Loop → polygon → Bézier curves.
//! Loop → Bézier curves, and centre line → Bézier curves.
use vectorcraft_geom::{AnchorKind, CubicBez, ParamCurve, PathData, Point, SubPath};
use vectorcraft_geom::{Anchor, AnchorKind, CubicBez, ParamCurve, PathData, Point, SubPath};
use vectorcraft_pathops::{SimplifyOptions, simplify_with};
use crate::contour::Loop;
use crate::logo::{Cubic, Stats, Style, all_within, fit_outline, resample_closed, sample_cubics};
use crate::subpixel::{self, Crack};
#[derive(Clone, Copy, Debug)]
pub(crate) struct FitOptions {
@@ -46,91 +48,56 @@ fn rdp(pts: &[Point], a: usize, b: usize, tol: f64, keep: &mut [bool]) {
}
}
/// The polygon approximating a closed loop of pixel-corner vertices within `tol`.
pub(crate) fn polygon(loop_pts: &[(i32, i32)], tol: f64) -> Vec<Point> {
let raw: Vec<Point> = loop_pts.iter().map(|&(x, y)| Point::new(x as f64, y as f64)).collect();
if raw.len() < 4 {
return raw;
/// Fit one loop of a `w × h` image into a closed Bézier subpath (pixel coordinates): its points
/// are placed to a fraction of a pixel ([`subpixel::outline`], which explains `shift`) and fitted as
/// Flat Logo mode fits its outlines (corners restored, straight runs as lines, the rest as few
/// curves as `style.tol` allows).
pub(crate) fn fit_loop(l: &Loop, w: usize, h: usize, shift: &dyn Fn(Crack) -> f64, style: &Style) -> Option<SubPath> {
let (pts, hard) = subpixel::outline(l, w, h, shift);
let mut style = *style;
if hard {
// No anti-aliasing: the edge is only known to about half a pixel (as in Flat Logo mode).
style.tol *= 2.5;
style.line_tol *= 1.8;
style.circle_tol *= 1.8;
style.sigma = 0.9;
}
let pts = dejag(loop_pts);
let pts = if pts.len() < 3 { raw.clone() } else { pts };
let mut stats = Stats::default();
let mut segs = fit_outline(&pts, &style, &mut stats)?;
// A fit that strayed was replaced by a plain one that nothing has checked: one that strays too
// (a wild handle on a tiny or ragged loop) gives way to the outline's own points.
if stats.reverted > 0 && !all_within(&sample_cubics(&segs, 0.25), &resample_closed(&pts, 0.5).map_or_else(|| pts.clone(), |(p, _)| p), 1.5) {
segs = polygon(&pts, style.tol);
}
let n = segs.len();
// A straight piece has no handles.
let straight = |c: &Cubic| seg_dist(c[1], c[0], c[3]) < 1e-6 && seg_dist(c[2], c[0], c[3]) < 1e-6;
let mut anchors = Vec::with_capacity(n);
for (i, cur) in segs.iter().enumerate() {
let before = segs.get((i + n - 1) % n)?;
let p = cur[0];
let (h_in, h_out) = (if straight(before) { p } else { before[2] }, if straight(cur) { p } else { cur[1] });
let (vi, vo) = (p - h_in, h_out - p);
let smooth = vi.hypot() > 1e-9 && vo.hypot() > 1e-9 && vi.cross(vo).abs() < 0.07 * vi.hypot() * vo.hypot() && vi.dot(vo) > 0.0;
anchors.push(Anchor { p, h_in, h_out, kind: if smooth { AnchorKind::Smooth } else { AnchorKind::Corner } });
}
(n >= 2).then(|| SubPath::new(anchors, true))
}
/// The closed outline `pts` as straight pieces within `tol` of it (Douglas–Peucker).
fn polygon(pts: &[Point], tol: f64) -> Vec<Cubic> {
let n = pts.len();
if n < 4 {
return pts;
}
// Split the closed loop at vertex 0 and the vertex farthest from it.
let far = (1..n).max_by(|&i, &j| pts[i].distance_squared(pts[0]).total_cmp(&pts[j].distance_squared(pts[0]))).unwrap_or(n / 2);
let mut ext = pts.clone();
ext.push(pts[0]);
let Some(&first) = pts.first() else { return vec![] };
let far = (1..n).max_by(|&i, &j| pts[i].distance_squared(first).total_cmp(&pts[j].distance_squared(first))).unwrap_or(0);
let mut ext = pts.to_vec();
ext.push(first);
let mut keep = vec![false; n + 1];
keep[0] = true;
keep[far] = true;
rdp(&ext, 0, far, tol, &mut keep);
rdp(&ext, far, n, tol, &mut keep);
let mut out: Vec<Point> = (0..n).filter(|&i| keep[i]).map(|i| pts[i]).collect();
// Vertex 0 was forced; drop it when it's not needed.
if out.len() > 3 {
let (p, a, b) = (out[0], out[out.len() - 1], out[1]);
if seg_dist(p, a, b) <= tol * 0.5 {
out.remove(0);
}
}
if out.len() < 3 { raw } else { out }
}
/// Replace pixel-staircase jogs by their midpoints.
///
/// A unit-length edge whose two ends turn in opposite directions (an S-shaped step) is a jog of
/// a staircase approximating a sloped line or curve: its midpoint lies on the ideal boundary, its
/// end vertices don't. Vertices not adjacent to any jog (true corners, e.g. of rectangles, or the
/// U-turns at the end of one-pixel-wide lines) are kept.
fn dejag(v: &[(i32, i32)]) -> Vec<Point> {
let n = v.len();
let edge = |i: usize| {
let (a, b) = (v[i % n], v[(i + 1) % n]);
(b.0 - a.0, b.1 - a.1)
};
// Turn sign at vertex i (between edge i-1 and edge i).
let turn = |i: usize| {
let (a, b) = (edge((i + n - 1) % n), edge(i));
(a.0 as i64 * b.1 as i64 - a.1 as i64 * b.0 as i64).signum()
};
let jog: Vec<bool> = (0..n)
.map(|i| {
let (dx, dy) = edge(i);
dx.abs() + dy.abs() == 1 && turn(i) * turn(i + 1) < 0
})
.collect();
let mut out = Vec::with_capacity(n);
for i in 0..n {
if !jog[i] && !jog[(i + n - 1) % n] {
out.push(Point::new(v[i].0 as f64, v[i].1 as f64));
}
if jog[i] {
let (a, b) = (v[i], v[(i + 1) % n]);
out.push(Point::new((a.0 + b.0) as f64 / 2.0, (a.1 + b.1) as f64 / 2.0));
}
}
out
}
/// Fit one loop into a closed Bézier subpath (pixel coordinates).
pub(crate) fn fit_loop(l: &Loop, o: &FitOptions) -> Option<SubPath> {
let poly = polygon(&l.pts, o.polygon_tol);
if poly.len() < 3 {
return None;
}
let sp = SubPath::polyline(&poly, true);
let fitted =
simplify_with(&PathData::single(sp), &SimplifyOptions { tolerance: o.fit_tol, corner_angle_deg: o.corner_angle, straight_lines: false });
let mut sp = fitted.subpaths.into_iter().next()?;
if sp.anchors.len() < 2 {
return None;
}
if o.snap_lines {
snap_to_lines(&mut sp, (o.fit_tol * 2.0).max(1.5));
}
Some(sp)
let kept: Vec<Point> = (0..n).filter(|&i| keep[i]).map(|i| pts[i]).collect();
(0..kept.len()).map(|i| [kept[i], kept[i], kept[(i + 1) % kept.len()], kept[(i + 1) % kept.len()]]).collect()
}
/// Fit a centre line through `pts` (pixel-centre points in order) into a Bézier subpath: the
+146 -7
View File
@@ -15,11 +15,14 @@
//! outside are linked into closed loops (inside on the right, right turns at saddles, so
//! diagonal pixels stay separate, matching 4-connectivity). Outer loops run clockwise and
//! holes counter-clockwise (y down), so the result fills correctly with either fill rule.
//! 4. **Polygon**: each loop is reduced to a polygon whose vertices stay within a fidelity
//! dependent distance of the pixel boundary (Douglas–Peucker on the crack vertices, which
//! removes the staircase).
//! 5. **Curves**: the polygon is fitted with cubic Béziers (`vectorcraft_pathops::simplify_with`,
//! least squares with corner detection); optionally nearly-straight curves snap to lines.
//! 4. **Sub-pixel edges**: each crack of a loop is moved to where the image says the edge really
//! is (an anti-aliased or blurred edge pixel is part one tone, part the other), so the outline
//! is right to a fraction of a pixel before any fitting; hard-edged images are read as
//! staircases instead (see `subpixel`).
//! 5. **Curves**: the outline is fitted as Flat Logo mode fits its own (`logo::fit_outline`):
//! corners the pixels rounded are put back, straight runs become lines, a round outline a
//! true circle, and the rest as few cubic Béziers as the Paths tolerance allows; Snap Curves To
//! Lines also straightens slightly curved runs and makes arcs of parts of circles.
//!
//! With **Create: Strokes**, the parts of a colour layer no wider than the stroke width are traced
//! as stroked centre lines instead (see `centerline`); without Fills, wider parts become stroked
@@ -35,6 +38,7 @@ mod fit;
mod logo;
mod mosaic;
mod quantize;
mod subpixel;
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -44,6 +48,7 @@ use vectorcraft_geom::PathData;
pub use contour::{Component, Loop, trace_mask};
pub use mosaic::mosaic;
pub use quantize::{FULL_TONE_MAX, Quantized, TRANSPARENT, denoise, quantize};
use subpixel::Crack;
/// Errors decoding a raster.
#[derive(Debug, thiserror::Error)]
@@ -307,6 +312,27 @@ impl TraceParams {
let f = (self.paths / 100.0).clamp(0.0, 1.0);
0.2 + 1.6 * (1.0 - f)
}
/// How outlines are fitted: Paths sets how closely the curves follow the edge (0.08 px at 100,
/// 0.33 px at 50, 0.78 px at 0), Corners the turn that makes a corner (35° at 100, 90° at 0).
/// Straight edges are always lines; Snap Curves To Lines also straightens slightly curved ones
/// and makes parts of circles true arcs.
fn outline_style(&self) -> logo::Style {
// Parameters come from users and agents: a NaN or infinity must not reach the geometry.
let unit = |v: f64, default: f64| if v.is_finite() { (v / 100.0).clamp(0.0, 1.0) } else { default };
let snap = self.snap_curves_to_lines;
logo::Style {
step: 0.25,
tol: 0.08 + 0.7 * (1.0 - unit(self.paths, 0.5)).powf(1.5),
corner_deg: 90.0 - 55.0 * unit(self.corners, 0.75),
snap: true,
arcs: snap,
line_tol: if snap { 0.5 } else { 0.2 },
circle_tol: if snap { 0.3 } else { 0.15 },
restore: Some(logo::RestoreParams::default()),
check_step: 0.15,
..logo::Style::default()
}
}
/// Turn angle (degrees) above which a polygon vertex stays a corner.
fn corner_angle(&self) -> f64 {
let c = (self.corners / 100.0).clamp(0.0, 1.0);
@@ -450,6 +476,9 @@ pub fn trace_within(img: &Raster, params: &TraceParams, max_anchors: usize) -> R
q: &q,
rank: &rank,
params,
img,
bw_tones: bw_tones(img, &q),
style: params.outline_style(),
opts: fit::FitOptions {
polygon_tol: params.polygon_tolerance(),
fit_tol: params.fit_tolerance(),
@@ -472,12 +501,31 @@ pub fn trace_within(img: &Raster, params: &TraceParams, max_anchors: usize) -> R
Ok(out)
}
/// The mean luminance of the pixels labelled 0 (white) and 1 (black) of a Black and White
/// quantisation: pure white and black where a side has no pixel.
fn bw_tones(img: &Raster, q: &Quantized) -> [f64; 2] {
let (mut sum, mut n) = ([0.0f64; 2], [0.0f64; 2]);
for (p, &l) in img.rgba.as_chunks::<4>().0.iter().zip(&q.labels) {
if let (Some(s), Some(n)) = (sum.get_mut(l as usize), n.get_mut(l as usize)) {
*s += (f64::from(p[0]) * 299.0 + f64::from(p[1]) * 587.0 + f64::from(p[2]) * 114.0) / 1000.0;
*n += 1.0;
}
}
[if n[0] > 0.0 { sum[0] / n[0] } else { 255.0 }, if n[1] > 0.0 { sum[1] / n[1] } else { 0.0 }]
}
/// What tracing one colour layer needs.
struct Layers<'a> {
q: &'a Quantized,
/// Each palette entry's layer, bottom (0) up.
rank: &'a [usize],
params: &'a TraceParams,
img: &'a Raster,
/// Black and White: the mean luminance of the white pixels and of the black ones.
bw_tones: [f64; 2],
/// How outlines are fitted.
style: logo::Style,
/// How centre lines are fitted.
opts: fit::FitOptions,
w: usize,
h: usize,
@@ -487,6 +535,96 @@ struct Layers<'a> {
}
impl Layers<'_> {
/// How far the edge lies from a crack between two pixels, towards the outside one (−0.5 to 0.5).
///
/// Each pixel of the column across the crack is read as a blend of the tones on its two sides
/// (the two pixels' palette colours; in Black and White the mean luminance of the black and of
/// the white pixels). The edge is where the blends, summed, put it: as far out as there is
/// inside tone in the outside pixels, less the outside tone in the inside ones (two pixels each
/// way, while they are on the same side and no more blended than the pixel before: more would be
/// another edge's doing).
///
/// Where the inside is at most three pixels deep with the outside's colour behind it (a thin
/// line), its two edges share those pixels and cannot be read apart; the inside tone of the
/// whole column gives the line's middle (its centroid) and width (its sum) instead. A thin gap
/// between two parts of the inside is read the same way, with the tones swapped.
///
/// Black and White then moves the edge to where the luminance crosses the threshold: by the
/// threshold's distance from the middle tone, over how steep the edge is (nothing for a
/// threshold in the middle, more the softer the edge).
fn shift(&self, c: Crack) -> f64 {
let label = |k: i32| c.at(k).and_then(|i| self.q.labels.get(i).copied()).filter(|&l| l != TRANSPARENT);
let (Some(la), Some(lb)) = (label(0), label(1)) else { return 0.0 };
if la == lb {
return 0.0;
}
let bw = self.params.mode == Mode::BlackAndWhite;
let (ca, cb) = if bw {
let tone = |l: u16| [self.bw_tones[usize::from(l == 1)]; 3];
(tone(la), tone(lb))
} else {
let (Some(ca), Some(cb)) = (self.q.palette.get(la as usize), self.q.palette.get(lb as usize)) else { return 0.0 };
(ca.map(f64::from), cb.map(f64::from))
};
let d = [0, 1, 2].map(|k| cb[k] - ca[k]);
let len2: f64 = d.iter().map(|v| v * v).sum();
if len2 <= 0.0 {
return 0.0;
}
// How much of the inside tone (0 to 1) the pixel `k` steps out has; none off the image.
let inside = |k: i32| {
let Some(p) = c.at(k).and_then(|i| self.img.rgba.get(i * 4..i * 4 + 3)) else { return 0.0 };
let p = [f64::from(p[0]), f64::from(p[1]), f64::from(p[2])];
let p = if bw { [(p[0] * 299.0 + p[1] * 587.0 + p[2] * 114.0) / 1000.0; 3] } else { p };
1.0 - ((0..3).map(|k| (p[k] - ca[k]) * d[k]).sum::<f64>() / len2).clamp(0.0, 1.0)
};
// The edge from a thin run of `n` pixels starting at pixel `from` and going `dir`, by the
// amounts `tone` of the run's own tone in it and in the two pixels at either end of it.
// Returns the run's middle and width, measured from the crack towards the outside.
let thin = |from: i32, dir: i32, n: i32, tone: &dyn Fn(i32) -> f64| {
let (near, far) = (from - dir, from + n * dir);
let mut cells: Vec<(i32, f64)> = (0..n).map(|j| from + j * dir).chain([near, far]).map(|k| (k, tone(k))).collect();
for (edge, out) in [(near, -dir), (far, dir)] {
if label(edge + out) == label(edge) {
cells.push((edge + out, tone(edge + out).min(tone(edge))));
}
}
let width: f64 = cells.iter().map(|c| c.1).sum();
// Pixel `k`'s centre is `k - 0.5` from the crack.
(width > 1e-6).then(|| (cells.iter().map(|c| c.1 * (f64::from(c.0) - 0.5)).sum::<f64>() / width, width))
};
// How deep each side is here: up to three pixels of its own label, then the other's.
let depth = |dir: i32, own: u16, other: u16| {
let start = if dir < 0 { 0 } else { 1 };
let n = (1..=3).take_while(|j| label(start + j * dir) == Some(own)).count() as i32 + 1;
(n <= 3 && label(start + n * dir) == Some(other)).then_some(n)
};
let mut steep = 1.0;
let mut shift = if let Some((middle, width)) = depth(-1, la, lb).and_then(|n| thin(0, -1, n, &inside)) {
middle + width / 2.0
} else if let Some((middle, width)) = depth(1, lb, la).and_then(|n| thin(1, 1, n, &|k| 1.0 - inside(k))) {
middle - width / 2.0
} else {
let (a1, b1) = (1.0 - inside(0), inside(1));
let a2 = (label(-1) == Some(la)).then(|| (1.0 - inside(-1)).min(a1));
let b2 = (label(2) == Some(lb)).then(|| inside(2).min(b1));
// The edge's steepness per pixel: the square of the change over two pixels (1 for an
// anti-aliased edge, less for a blurred one).
let change = [a2.map(|v| 1.0 - v - b1), b2.map(|v| 1.0 - a1 - v)].into_iter().flatten().fold(f64::NAN, f64::max);
if !change.is_nan() {
steep = (change * change).clamp(0.35, 1.0);
}
b1 + b2.unwrap_or(0.0) - a1 - a2.unwrap_or(0.0)
};
if bw {
// The share of black at which a pixel turns black.
let (white, black) = (self.bw_tones[0], self.bw_tones[1]);
let turn = ((white - f64::from(self.params.threshold)) / (white - black).max(1.0)).clamp(0.02, 0.98);
shift += if la == 1 { 1.0 } else { -1.0 } * (0.5 - turn) / steep;
}
shift
}
/// The paths of layer `r` (palette entry `ci`), or `None` once the anchors made pass the
/// maximum.
fn layer(&self, r: usize, ci: usize) -> Option<Vec<TracedPath>> {
@@ -524,13 +662,14 @@ impl Layers<'_> {
true
};
for comp in trace_mask(&mask, w, h) {
let Some(outer) = fit::fit_loop(&comp.outer, opts) else { continue };
let fit = |l: &Loop| fit::fit_loop(l, w, h, &|c| self.shift(c), &self.style);
let Some(outer) = fit(&comp.outer) else { continue };
let mut subs = vec![outer];
for hole in &comp.holes {
if hole.area2.abs() / 2 < min_hole && params.noise > 0 {
continue;
}
subs.extend(fit::fit_loop(hole, opts));
subs.extend(fit(hole));
}
if !add(PathData::new(subs), comp.pixels, area_stroke) {
return None;
+3
View File
@@ -24,4 +24,7 @@ mod tests;
mod testutil;
mod unmix;
pub(crate) use geom::{Cubic, all_within, resample_closed, sample_cubics};
pub(crate) use outline::{Stats, Style, fit_outline};
pub(crate) use pipeline::trace_logo;
pub(crate) use restore::RestoreParams;
+19 -4
View File
@@ -14,11 +14,15 @@ pub(crate) struct Style {
pub corner_win: f64,
pub tol: f64,
pub snap: bool,
/// With `snap`: parts of circles become true arcs too.
pub arcs: bool,
pub line_tol: f64,
pub circle_tol: f64,
pub restore: Option<RestoreParams>,
/// An outline whose fit strays farther than this from the raw contour is fitted plainly.
pub max_dev: f64,
/// Spacing of the points of the fit that this check looks at.
pub check_step: f64,
}
impl Default for Style {
@@ -30,10 +34,12 @@ impl Default for Style {
corner_win: 0.7,
tol: 0.12,
snap: true,
arcs: true,
line_tol: 0.22,
circle_tol: 0.25,
restore: Some(RestoreParams::default()),
max_dev: 1.4,
check_step: 0.03,
}
}
}
@@ -161,6 +167,7 @@ fn styled_fit(p: &[Point], st: &Style, stats: &mut Stats) -> Option<Vec<Cubic>>
}
}
if st.snap
&& st.arcs
&& sm.len() > 12
&& len > 1.0
&& let Some(c) = circle_fit(&sm)
@@ -198,10 +205,18 @@ pub(crate) fn fit_outline(p: &[Point], st: &Style, stats: &mut Stats) -> Option<
}
let mut local = Stats::default();
// The reference is the raw outline, densified so the check never depends on how sparse it is.
let reference = resample_closed(p, 0.1).map_or_else(|| p.to_vec(), |(d, _)| d);
let fitted = styled_fit(p, st, &mut local).filter(|s| sane(s)).filter(|s| {
let samples = sample_cubics(s, 0.03);
all_within(&samples, &reference, st.max_dev) && all_within(&reference, &samples, st.max_dev)
let reference = resample_closed(p, st.check_step / 0.3).map_or_else(|| p.to_vec(), |(d, _)| d);
let checked = |st: &Style, local: &mut Stats| {
styled_fit(p, st, local).filter(|s| sane(s)).filter(|s| {
let samples = sample_cubics(s, st.check_step);
all_within(&samples, &reference, st.max_dev) && all_within(&reference, &samples, st.max_dev)
})
};
// A fit that strays is tried again without the clever parts before the plain fit, which
// nothing checks.
let fitted = checked(st, &mut local).or_else(|| {
local = Stats::default();
checked(&Style { snap: false, restore: None, ..*st }, &mut local)
});
match fitted {
Some(segs) => {
+184
View File
@@ -0,0 +1,184 @@
//! Outlines placed to a fraction of a pixel.
//!
//! A boundary loop runs along the cracks between pixels, so on its own it is a staircase that is
//! right only to half a pixel. But an anti-aliased or slightly blurred image says where the edge
//! really is: the pixels beside it are part one colour and part the other. Each crack between an
//! inside and an outside pixel is moved along its normal by what the four pixels across it say (see
//! [`Crack`]), which gives one point per crack; a corner of the loop that is a true corner of the
//! shape (not a step of a staircase) is kept, moved with the two edges that meet there. The same
//! crack gives the same point from either side, so two regions that touch get the same points along
//! their shared edge.
//!
//! An image with hard edges (a GIF, a 1-bit scan) says nothing more than the cracks do: every crack
//! moves by the same amount. There the staircase is read the classic way: a one-pixel step between
//! two runs is a point of a sloped edge (its middle is on the edge, the corners beside it are not).
use kurbo::Vec2;
use vectorcraft_geom::Point;
use crate::contour::Loop;
/// One straight run of a loop, from one of its vertices to the next.
struct Edge {
dir: (i32, i32),
len: usize,
/// Index of its first crack's shift.
first: usize,
}
/// A crack between an inside and an outside pixel of a `w × h` image, with the column of pixels
/// across it. Read across the edge, the column says where the edge lies: a straight edge that
/// crosses it leaves in its pixels, summed, exactly as much of the inside colour as its distance
/// along the column (which is how anti-aliasing draws it).
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct Crack {
inside: (i32, i32),
/// From the inside pixel to the outside one.
step: (i32, i32),
w: usize,
h: usize,
}
impl Crack {
/// The index of the pixel `k` steps out from the inside pixel (0: the inside pixel, 1: the
/// outside one, −1: the one behind the inside pixel), if the image has it.
pub fn at(&self, k: i32) -> Option<usize> {
pixel((self.inside.0 + k * self.step.0, self.inside.1 + k * self.step.1), self.w, self.h)
}
}
fn pixel(p: (i32, i32), w: usize, h: usize) -> Option<usize> {
let (x, y) = (usize::try_from(p.0).ok()?, usize::try_from(p.1).ok()?);
(x < w && y < h).then(|| y * w + x)
}
/// The outline of `l` (a loop of a `w × h` image) as points, and whether its edge is hard.
///
/// `shift` says how far (in pixels, −0.5 to 0.5, positive towards the outside pixel) the edge lies
/// from a crack.
pub(crate) fn outline(l: &Loop, w: usize, h: usize, shift: &dyn Fn(Crack) -> f64) -> (Vec<Point>, bool) {
let v = &l.pts;
let n = v.len();
let at = |i: usize| Point::new(f64::from(v[i % n].0), f64::from(v[i % n].1));
let raw = || (0..n).map(at).collect::<Vec<_>>();
if n < 4 {
return (raw(), true);
}
let mut edges = Vec::with_capacity(n);
let mut shifts: Vec<f64> = Vec::new();
for i in 0..n {
let (a, b) = (v[i], v[(i + 1) % n]);
let (dx, dy) = (b.0 - a.0, b.1 - a.1);
let dir = (dx.signum(), dy.signum());
let len = dx.unsigned_abs().max(dy.unsigned_abs());
edges.push(Edge { dir, len: len as usize, first: shifts.len() });
for k in 0..len as i32 {
// The crack starts at corner `s`; the inside pixel is on its right (y down).
let (sx, sy) = (a.0 + dir.0 * k, a.1 + dir.1 * k);
let (inside, outside) = match dir {
(1, 0) => ((sx, sy), (sx, sy - 1)),
(0, 1) => ((sx - 1, sy), (sx, sy)),
(-1, 0) => ((sx - 1, sy - 1), (sx - 1, sy)),
_ => ((sx, sy - 1), (sx - 1, sy - 1)),
};
let crack = Crack { inside, step: (outside.0 - inside.0, outside.1 - inside.1), w, h };
let s = match crack.at(1) {
Some(_) => shift(crack),
// The edge of the image is where it is.
_ => 0.0,
};
shifts.push(if s.is_finite() { s.clamp(-0.5, 0.5) } else { 0.0 });
}
}
// A hard edge: nearly every crack moves by the same amount.
let mut sorted = shifts.clone();
let mid = sorted.len() / 2;
let median = if sorted.is_empty() { 0.0 } else { *sorted.select_nth_unstable_by(mid, f64::total_cmp).1 };
let hard = shifts.iter().filter(|s| (*s - median).abs() > 0.03).count() * 4 < shifts.len();
// Which way the loop turns at vertex `i`, and whether edge `i` is a step of a staircase: one
// pixel long, turning one way where it starts and the other where it ends.
let turn = |i: usize| {
let (a, b) = (edges[(i + n - 1) % n].dir, edges[i % n].dir);
(a.0 * b.1 - a.1 * b.0).signum()
};
let step: Vec<bool> = (0..n).map(|i| edges[i].len == 1 && turn(i) * turn(i + 1) < 0).collect();
let outward = |d: (i32, i32)| Vec2::new(f64::from(d.1), f64::from(-d.0));
let shift_of = |e: &Edge, k: usize| shifts.get(e.first + k).copied().unwrap_or(0.0);
let mut out = Vec::with_capacity(if hard { n } else { shifts.len() + n });
for i in 0..n {
let (before, e) = (&edges[(i + n - 1) % n], &edges[i]);
if !step[i] && !step[(i + n - 1) % n] {
// A true corner: where its two edges, each moved by its own shift, meet.
out.push(at(i) + outward(before.dir) * shift_of(before, before.len.saturating_sub(1)) + outward(e.dir) * shift_of(e, 0));
}
if step[i] || !hard {
let along = Vec2::new(f64::from(e.dir.0), f64::from(e.dir.1));
out.extend((0..e.len).map(|k| at(i) + along * (k as f64 + 0.5) + outward(e.dir) * shift_of(e, k)));
}
}
if out.len() < 3 { (raw(), hard) } else { (out, hard) }
}
#[cfg(test)]
mod tests {
use super::*;
use crate::contour::trace_mask;
fn loop_of(mask: &[bool], w: usize, h: usize) -> Loop {
trace_mask(mask, w, h).remove(0).outer
}
#[test]
fn a_hard_rectangle_keeps_its_four_corners() {
let (w, h) = (8, 6);
let mask: Vec<bool> = (0..w * h).map(|i| (2..6).contains(&(i % w)) && (1..5).contains(&(i / w))).collect();
let (pts, hard) = outline(&loop_of(&mask, w, h), w, h, &|_| 0.0);
assert!(hard);
assert_eq!(pts, [(2.0, 1.0), (6.0, 1.0), (6.0, 5.0), (2.0, 5.0)].map(Point::from));
}
#[test]
fn a_hard_staircase_becomes_the_sloped_line_through_its_steps() {
// Below the line y = x / 4 + 2: treads four pixels long.
let (w, h) = (16, 8);
let mask: Vec<bool> = (0..w * h).map(|i| (i / w) as f64 + 0.5 > (i % w) as f64 / 4.0 + 2.0).collect();
let (pts, hard) = outline(&loop_of(&mask, w, h), w, h, &|_| 0.0);
assert!(hard);
// Every step's middle lies on one line, a quarter of a pixel's rise per pixel.
let steps: Vec<Point> = pts.iter().copied().filter(|p| p.y.fract() == 0.5 && p.x > 0.0 && p.x < w as f64).collect();
assert_eq!(steps.len(), 4, "{pts:?}");
assert!(steps.windows(2).all(|s| ((s[1].y - s[0].y) / (s[1].x - s[0].x) - 0.25).abs() < 1e-9), "{steps:?}");
}
#[test]
fn a_soft_edge_moves_each_crack_by_its_shift() {
let (w, h) = (6, 4);
// The left half is inside; its right edge really lies 0.3 px further right.
let mask: Vec<bool> = (0..w * h).map(|i| i % w < 3).collect();
let shift = |c: Crack| if c.at(0).is_some_and(|i| i % w == 2) && c.at(1).is_some_and(|i| i % w == 3) { 0.3 } else { 0.0 };
let l = loop_of(&mask, w, h);
let (pts, hard) = outline(&l, w, h, &shift);
assert!(!hard);
// Each crack comes with the column of pixels across it.
outline(&l, w, h, &|c| {
let (a, b) = (c.at(0).unwrap(), c.at(1).unwrap());
assert_eq!((c.at(-1), c.at(2)), (Some(a - 1), Some(b + 1)));
assert_eq!((c.at(-3), c.at(4)), (None, None));
0.0
});
let right: Vec<&Point> = pts.iter().filter(|p| p.x > 2.5).collect();
// The four cracks' middles and the two corners, all at x = 3.3.
assert_eq!(right.len(), 6);
assert!(right.iter().all(|p| (p.x - 3.3).abs() < 1e-12), "{right:?}");
}
#[test]
fn a_shift_that_is_not_a_number_moves_nothing() {
let mask = [true, true, false, false, true, true, false, false];
let (pts, _) = outline(&loop_of(&mask, 4, 2), 4, 2, &|_| f64::NAN);
assert_eq!(pts.len(), 4);
assert!(pts.iter().all(|p| p.x.is_finite() && p.y.is_finite()));
}
}
+132 -2
View File
@@ -242,8 +242,11 @@ fn fidelity_changes_anchor_count() {
#[test]
fn snap_curves_to_lines_straightens_near_lines() {
// A slightly jagged, almost straight edge.
let img = Raster::from_fn(200, 100, |x, y| if y as f64 > 30.0 + (x as f64 * 0.05) + if x % 37 < 2 { 1.0 } else { 0.0 } { BLACK } else { WHITE });
// A slightly jagged, almost straight edge. (Hard pixels place it to half a pixel only, and its
// ends sit on staircase treads: jags far along it would be more than "slightly" off the line.)
let img = Raster::from_fn(200, 100, |x, y| {
if y as f64 > 30.0 + (x as f64 * 0.05) + if (5..7).contains(&(x % 37)) && x < 120 { 1.0 } else { 0.0 } { BLACK } else { WHITE }
});
let res = trace(&img, &TraceParams { snap_curves_to_lines: true, ..bw() });
let sp = &res.paths[0].path.subpaths[0];
let curves = (0..sp.segment_count()).filter(|&i| !sp.segment_is_line(i)).count();
@@ -729,3 +732,130 @@ fn more_noise_removal_never_gives_more_paths() {
}
}
}
/// A shape drawn anti-aliased: each pixel's ink is the share of its 8 × 8 samples that `inside` holds.
fn soft(w: u32, h: u32, inside: impl Fn(f64, f64) -> bool) -> Raster {
Raster::from_fn(w, h, |x, y| {
let n = (0..64).filter(|i| inside(f64::from(x) + (f64::from(i % 8) + 0.5) / 8.0, f64::from(y) + (f64::from(i / 8) + 0.5) / 8.0)).count();
let v = (255.0 * (1.0 - n as f64 / 64.0)).round() as u8;
[v, v, v, 255]
})
}
/// Points along every curve of `p`.
fn along(p: &vectorcraft_geom::PathData) -> Vec<Point> {
use vectorcraft_geom::ParamCurve;
p.subpaths
.iter()
.flat_map(|sp| (0..sp.segment_count()).flat_map(move |i| (0..16).map(move |k| sp.segment(i).eval(f64::from(k) / 16.0))))
.collect()
}
#[test]
fn an_anti_aliased_disc_is_traced_to_a_fraction_of_a_pixel() {
let (c, r) = (Point::new(60.3, 59.6), 40.4);
let res = trace(&soft(120, 120, |x, y| Point::new(x, y).distance(c) <= r), &bw());
assert_eq!(res.paths.len(), 1);
let off = along(&res.paths[0].path).iter().map(|p| (p.distance(c) - r).abs()).fold(0.0, f64::max);
assert!(off < 0.12, "{off} px off the circle");
// Smooth all the way round, with a handful of anchors.
assert!(res.paths[0].path.anchor_count() <= 8, "{} anchors", res.paths[0].path.anchor_count());
assert!(res.paths[0].path.subpaths[0].anchors.iter().all(|a| a.kind == vectorcraft_geom::AnchorKind::Smooth));
}
#[test]
fn an_anti_aliased_square_has_four_corners_and_straight_sides() {
// Edges between pixel rows and columns, turned a little so that none follows the grid.
let (c, half, turn) = (Point::new(50.3, 49.7), 30.2, 0.2f64);
let inside = |x: f64, y: f64| {
let (dx, dy) = (x - c.x, y - c.y);
(dx * turn.cos() + dy * turn.sin()).abs() <= half && (dy * turn.cos() - dx * turn.sin()).abs() <= half
};
let res = trace(&soft(100, 100, inside), &bw());
let sp = &res.paths[0].path.subpaths[0];
assert_eq!(sp.anchors.len(), 4, "{sp:?}");
assert!((0..4).all(|i| sp.segment_is_line(i)));
for a in &sp.anchors {
let (dx, dy) = (a.p.x - c.x, a.p.y - c.y);
let (u, v) = (dx * turn.cos() + dy * turn.sin(), dy * turn.cos() - dx * turn.sin());
assert!((u.abs() - half).abs() < 0.15 && (v.abs() - half).abs() < 0.15, "corner {:?} is off", a.p);
}
}
#[test]
fn a_thin_anti_aliased_line_keeps_its_place_and_width() {
// 1.2 px wide, lying across two pixel rows.
let res = trace(&soft(60, 20, |x, y| (5.0..55.0).contains(&x) && (9.7..10.9).contains(&y)), &bw());
assert_eq!(res.paths.len(), 1);
let b = res.paths[0].path.bounds().unwrap();
assert!((b.y0 - 9.7).abs() < 0.1 && (b.y1 - 10.9).abs() < 0.1, "{b:?}");
assert!((b.x0 - 5.0).abs() < 0.1 && (b.x1 - 55.0).abs() < 0.1, "{b:?}");
}
#[test]
fn touching_colours_get_the_same_edge() {
// Red left of a slanted edge, blue right of it: where the paths meet, each lies on the edge.
let edge = |y: f64| 30.3 + 0.2 * y;
let img = Raster::from_fn(60, 40, |x, y| {
let t = (edge(f64::from(y) + 0.5) - f64::from(x)).clamp(0.0, 1.0);
[(200.0 * t + 30.0 * (1.0 - t)) as u8, (40.0 * t + 90.0 * (1.0 - t)) as u8, (50.0 * t + 200.0 * (1.0 - t)) as u8, 255]
});
let res = trace(&img, &TraceParams { mode: Mode::Color, colors: 2, ..TraceParams::default() });
assert_eq!(res.paths.len(), 2);
for p in &res.paths {
let inner: Vec<Point> = along(&p.path).into_iter().filter(|q| q.x > 1.0 && q.x < 59.0 && q.y > 1.0 && q.y < 39.0).collect();
assert!(!inner.is_empty());
let off = inner.iter().map(|q| (q.x - edge(q.y)).abs()).fold(0.0, f64::max);
assert!(off < 0.12, "{off} px off the shared edge");
}
}
#[test]
fn a_hard_edged_disc_is_still_round() {
let res = trace(&disc(120, 60.0, 60.0, 40.0), &bw());
let c = Point::new(60.0, 60.0);
let off = along(&res.paths[0].path).iter().map(|p| (p.distance(c) - 40.0).abs()).fold(0.0, f64::max);
assert!(off < 0.75, "{off} px off the circle");
assert!(res.paths[0].path.anchor_count() <= 12, "{} anchors", res.paths[0].path.anchor_count());
}
#[test]
fn a_higher_threshold_widens_a_blurred_shape_smoothly() {
// A soft-edged disc: its luminance ramps over six pixels.
let img = Raster::from_fn(100, 100, |x, y| {
let d = Point::new(f64::from(x) + 0.5, f64::from(y) + 0.5).distance(Point::new(50.0, 50.0));
let v = (255.0 * ((d - 27.0) / 6.0).clamp(0.0, 1.0)) as u8;
[v, v, v, 255]
});
let radius = |threshold: u8| {
let res = trace(&img, &TraceParams { threshold, ..bw() });
let r: Vec<f64> = along(&res.paths[0].path).iter().map(|p| p.distance(Point::new(50.0, 50.0))).collect();
(r.iter().copied().fold(f64::MAX, f64::min), r.iter().copied().fold(0.0, f64::max))
};
let (low, high) = (radius(64), radius(192));
// Luminance 64 is 1.5 px into the ramp and 192 4.5 px.
assert!((low.0 - 28.5).abs() < 0.6 && (low.1 - 28.5).abs() < 0.6, "{low:?}");
assert!((high.0 - 31.5).abs() < 0.6 && (high.1 - 31.5).abs() < 0.6, "{high:?}");
}
#[test]
fn no_path_of_a_noisy_picture_leaves_the_picture() {
// Texture and noise: thousands of small ragged regions, where a fit is most likely to stray.
let img = Raster::from_fn(160, 120, |x, y| {
let mut v = x.wrapping_mul(0x9E37_79B1) ^ y.wrapping_mul(0x85EB_CA77);
v ^= v >> 15;
v = v.wrapping_mul(0x2C1B_3C6D);
v ^= v >> 12;
let wave = 60.0 * ((f64::from(x) * 0.31).sin() * (f64::from(y) * 0.23).cos());
let c = |k: u32| (128.0 + wave + f64::from((v >> (8 * k)) & 63) + f64::from(x + 2 * y) * 0.2 * f64::from(k)).clamp(0.0, 255.0) as u8;
[c(0), c(1), c(2), 255]
});
for name in PRESET_NAMES {
let res = trace(&img, &preset(name).unwrap());
for p in &res.paths {
// A fit may bulge past the picture's border by its tolerance, never by more.
let Some(b) = p.path.bounds() else { continue };
assert!(b.x0 > -2.0 && b.y0 > -2.0 && b.x1 < 162.0 && b.y1 < 122.0, "{name}: a path reaches {b:?}");
}
}
}
+290 -231
View File
@@ -1,6 +1,6 @@
# Image Trace quality
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-12 · **Change:** new (the harness and the baseline numbers)
> **Last reviewed:** 2026-10-13 · **Last updated:** 2026-10-13 · **Change:** minor (sub-pixel edges in every mode: outlines 0.31 to 0.09 px off for Default, 0.27 to 0.06 for Black and White Logo)
What Image Trace (`crates/trace`) makes of images whose right answer is known, measured by a harness and
compared with the numbers before each change. Nothing here is a judgement by eye, and nothing is compared
@@ -16,7 +16,8 @@ TRACE_QUALITY_REPORT=report.md cargo test --release -p vectorcraft-trace --test
```
**Inputs** (drawn anti-aliased at 128, 256 and 512 px, and at 256 px also blurred, with compression-like
noise, and as a scan of ink on cream paper with uneven light and grain):
noise, as a scan of ink on cream paper with uneven light and grain, and aliased: one hard sample per pixel, no
anti-aliasing):
| kind | inputs |
|:--|:--|
@@ -44,158 +45,212 @@ The letters are drawn by hand from lines and curves: the repository has no font
| odd colours, odd px | paths (and their area) in a colour the art doesn't have: slivers along anti-aliased edges |
| gap px, overlap px | area no path covers, and area covered twice (abutting traces with a white background only) |
| specks | paths under 6 px of area |
| outside px | how far the trace reaches outside the image: a curve that strays |
Black-and-white presets trace black: on the scanned variant their ΔE includes the paper's and ink's own
colours. `–` means the measure does not apply; `all` that nothing was traced.
**These are the baseline numbers:** measured on main at `baf9693f`, before any change to the tracer.
## Baseline and now
Each preset on the inputs it is meant for, all sizes and variants.
### Baseline (before any change, main at `baf9693f`)
| preset | inputs | ΔE | edge ΔE | off mean | off max | missed max | paths | anchors | × art | lines % | corners % | kinks | odd colours | odd px | gap px | overlap px | specks | outside px |
|:--|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| Default | circle, ellipses, badge with a hole, letter D, polygons, star, letter A | 2.79 | 17.15 | 0.313 | 1.51 | 2.52 | 1.9 | 14 | 1.45 | 34 | 76 | 1.4 | – | – | 63.5 | 67.0 | 0.0 | 0.0 |
| High Fidelity Photo | gradient, photo-like | 2.30 | 2.63 | – | – | – | 3652.6 | 46866 | – | 84 | – | – | – | – | 0.0 | – | 1169.4 | 0.3 |
| Low Fidelity Photo | gradient, photo-like | 2.61 | 2.94 | – | – | – | 128.3 | 3867 | – | 42 | – | – | – | – | 0.0 | – | 0.0 | 0.7 |
| 3 Colors | two touching halves | 4.93 | 11.38 | 0.482 | 2.35 | 89.09 | 2.1 | 14 | 2.31 | 12 | 29 | 2.1 | 1.6 | 15418 | 118.0 | 87.3 | 0.0 | 0.0 |
| 6 Colors | two touching halves, four-colour badge | 0.78 | 8.82 | 4.383 | 83.10 | 30.11 | 21.2 | 270 | 30.18 | 51 | 98 | 213.8 | 2.4 | 272 | 198.8 | 194.6 | 0.0 | 0.3 |
| 16 Colors | two touching halves, four-colour badge | 0.74 | 9.02 | 5.115 | 86.21 | 4.32 | 69.9 | 923 | 102.80 | 58 | 100 | 765.9 | 5.9 | 670 | 293.7 | 329.9 | 0.0 | 0.5 |
| Shades of Gray | gradient, photo-like | 9.29 | 9.16 | – | – | – | 90.8 | 1921 | – | 42 | – | – | – | – | 0.0 | – | 0.2 | 0.5 |
| Black and White Logo | circle, ellipses, badge with a hole, letter D, polygons, star, letter A | 2.76 | 15.96 | 0.270 | 1.76 | 2.53 | 1.4 | 31 | 3.78 | 90 | 81 | 15.3 | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | circle, ellipses, badge with a hole, letter D, lines | 2.85 | 17.04 | 0.302 | 1.63 | 105.63 | 1.8 | 14 | 1.34 | 28 | 18 | 1.4 | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | circle, ellipses, badge with a hole, letter D | 3.04 | 21.41 | 0.573 | 2.88 | 2.89 | 1.2 | 10 | 1.16 | 9 | 86 | 1.4 | – | – | – | – | 0.0 | 0.0 |
| Line Art | lines | 2.77 | 12.51 | 0.158 | 1.13 | 105.76 | 5.4 | 25 | 1.27 | 90 | – | – | – | – | – | – | 0.0 | 0.0 |
| Technical Drawing | polygons, star, letter A, lines | 2.66 | 13.45 | 0.201 | 1.37 | 105.76 | 4.8 | 32 | 2.23 | 100 | 85 | 5.9 | – | – | – | – | 0.1 | 0.0 |
| Flat Logo | two touching halves, four-colour badge | 0.43 | 3.53 | 3.106 | 88.50 | 0.78 | 69.9 | 352 | 38.92 | 38 | 80 | 237.0 | 0.0 | 0 | 13.8 | – | 59.1 | 0.2 |
### Now (sub-pixel edges)
| preset | inputs | ΔE | edge ΔE | off mean | off max | missed max | paths | anchors | × art | lines % | corners % | kinks | odd colours | odd px | gap px | overlap px | specks | outside px |
|:--|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| Default | circle, ellipses, badge with a hole, letter D, polygons, star, letter A | 2.60 | 10.12 | 0.091 | 1.02 | 2.17 | 1.9 | 18 | 1.81 | 29 | 68 | 0.4 | – | – | 22.2 | 22.4 | 0.0 | 0.0 |
| High Fidelity Photo | gradient, photo-like | 2.50 | 2.81 | – | – | – | 3636.4 | 81597 | – | 25 | – | – | – | – | 0.0 | – | 995.3 | 1.3 |
| Low Fidelity Photo | gradient, photo-like | 2.59 | 2.87 | – | – | – | 128.3 | 7277 | – | 37 | – | – | – | – | 0.0 | – | 0.1 | 0.4 |
| 3 Colors | two touching halves | 4.86 | 8.48 | 0.332 | 2.02 | 89.49 | 2.1 | 38 | 6.33 | 11 | 29 | 2.6 | 1.6 | 15527 | 50.3 | 40.4 | 0.0 | 0.0 |
| 6 Colors | two touching halves, four-colour badge | 0.61 | 4.88 | 4.442 | 83.47 | 30.03 | 21.2 | 473 | 53.89 | 45 | 95 | 344.2 | 2.4 | 279 | 68.6 | 79.0 | 0.0 | 0.2 |
| 16 Colors | two touching halves, four-colour badge | 0.60 | 5.32 | 5.084 | 85.85 | 4.16 | 69.9 | 1743 | 196.62 | 49 | 98 | 1376.4 | 5.9 | 612 | 152.8 | 141.8 | 0.2 | 0.6 |
| Shades of Gray | gradient, photo-like | 9.29 | 9.12 | – | – | – | 90.7 | 3183 | – | 51 | – | – | – | – | 0.0 | – | 5.3 | 0.8 |
| Black and White Logo | circle, ellipses, badge with a hole, letter D, polygons, star, letter A | 2.58 | 9.39 | 0.064 | 1.00 | 2.18 | 1.4 | 27 | 2.73 | 40 | 67 | 0.3 | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | circle, ellipses, badge with a hole, letter D, lines | 2.71 | 12.11 | 0.195 | 1.00 | 105.54 | 1.8 | 17 | 1.49 | 16 | 86 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | circle, ellipses, badge with a hole, letter D | 2.98 | 19.28 | 0.532 | 2.24 | 2.24 | 1.2 | 14 | 1.65 | 12 | 79 | 0.1 | – | – | – | – | 0.0 | 0.0 |
| Line Art | lines | 2.65 | 9.87 | 0.093 | 0.89 | 105.71 | 5.4 | 77 | 3.86 | 37 | – | – | – | – | – | – | 0.1 | 0.0 |
| Technical Drawing | polygons, star, letter A, lines | 2.53 | 9.47 | 0.086 | 0.99 | 105.85 | 4.8 | 57 | 3.73 | 69 | 74 | 0.7 | – | – | – | – | 0.3 | 0.0 |
| Flat Logo | two touching halves, four-colour badge | 0.43 | 3.53 | 3.106 | 88.50 | 0.78 | 69.9 | 352 | 38.92 | 38 | 80 | 237.0 | 0.0 | 0 | 13.8 | – | 59.1 | 0.2 |
The sections below are the numbers now (sub-pixel edges).
## 1. Each preset on the inputs it is meant for
All sizes and variants (clean, blurred, noisy, scanned) of those inputs.
All sizes and variants (clean, aliased, blurred, noisy, scanned) of those inputs.
| preset | inputs | ΔE | edge ΔE | off mean | off max | missed max | paths | anchors | × art | lines % | corners % | kinks | odd colours | odd px | gap px | overlap px | specks |
|:--|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| Default | circle, ellipses, badge with a hole, letter D, polygons, star, letter A | 3.18 | 16.26 | 0.317 | 1.51 | 2.52 | 1.9 | 14 | 1.47 | 33 | 72 | 1.5 | – | – | 65.2 | 68.3 | 0.0 |
| High Fidelity Photo | gradient, photo-like | 2.29 | 2.61 | – | – | – | 3810.7 | 48993 | – | 83 | – | – | – | – | 0.0 | – | 1245.8 |
| Low Fidelity Photo | gradient, photo-like | 2.61 | 2.93 | – | – | – | 128.8 | 4013 | – | 42 | – | – | – | – | 0.0 | – | 0.0 |
| 3 Colors | two touching halves | 5.72 | 11.69 | 0.517 | 2.35 | 89.09 | 2.2 | 14 | 2.42 | 7 | 17 | 2.5 | 1.8 | 17987 | 118.3 | 93.3 | 0.0 |
| 6 Colors | two touching halves, four-colour badge | 0.86 | 8.60 | 5.062 | 83.10 | 30.11 | 24.2 | 310 | 34.87 | 53 | 98 | 249.0 | 2.8 | 318 | 213.4 | 206.7 | 0.0 |
| 16 Colors | two touching halves, four-colour badge | 0.81 | 8.70 | 5.914 | 86.21 | 4.32 | 81.1 | 1071 | 119.54 | 61 | 100 | 893.2 | 6.9 | 782 | 324.1 | 365.3 | 0.0 |
| Shades of Gray | gradient, photo-like | 9.22 | 9.08 | – | – | – | 92.6 | 1990 | – | 41 | – | – | – | – | 0.0 | – | 0.2 |
| Black and White Logo | circle, ellipses, badge with a hole, letter D, polygons, star, letter A | 3.15 | 14.98 | 0.276 | 1.76 | 2.53 | 1.4 | 32 | 3.80 | 90 | 79 | 15.2 | – | – | – | – | 0.0 |
| Sketched Art | circle, ellipses, badge with a hole, letter D, lines | 3.23 | 16.14 | 0.306 | 1.63 | 105.61 | 1.8 | 14 | 1.34 | 28 | 21 | 1.4 | – | – | – | – | 0.0 |
| Silhouettes | circle, ellipses, badge with a hole, letter D | 3.46 | 20.78 | 0.611 | 2.88 | 2.89 | 1.2 | 10 | 1.18 | 9 | 83 | 1.4 | – | – | – | – | 0.0 |
| Line Art | lines | 3.12 | 12.24 | 0.161 | 1.13 | 105.76 | 4.0 | 20 | 0.98 | 89 | – | – | – | – | – | – | 0.0 |
| Technical Drawing | polygons, star, letter A, lines | 3.04 | 12.82 | 0.203 | 1.37 | 105.76 | 4.5 | 31 | 2.19 | 100 | 83 | 6.4 | – | – | – | – | 0.2 |
| Flat Logo | two touching halves, four-colour badge | 0.48 | 3.14 | 3.588 | 88.50 | 0.78 | 81.0 | 405 | 45.08 | 37 | 85 | 276.5 | 0.0 | 0 | 15.2 | – | 69.0 |
| preset | inputs | ΔE | edge ΔE | off mean | off max | missed max | paths | anchors | × art | lines % | corners % | kinks | odd colours | odd px | gap px | overlap px | specks | outside px |
|:--|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| Default | circle, ellipses, badge with a hole, letter D, polygons, star, letter A | 2.60 | 10.12 | 0.091 | 1.02 | 2.17 | 1.9 | 18 | 1.81 | 29 | 68 | 0.4 | – | – | 22.2 | 22.4 | 0.0 | 0.0 |
| High Fidelity Photo | gradient, photo-like | 2.50 | 2.81 | – | – | – | 3636.4 | 81597 | – | 25 | – | – | – | – | 0.0 | – | 995.3 | 1.3 |
| Low Fidelity Photo | gradient, photo-like | 2.59 | 2.87 | – | – | – | 128.3 | 7277 | – | 37 | – | – | – | – | 0.0 | – | 0.1 | 0.4 |
| 3 Colors | two touching halves | 4.86 | 8.48 | 0.332 | 2.02 | 89.49 | 2.1 | 38 | 6.33 | 11 | 29 | 2.6 | 1.6 | 15527 | 50.3 | 40.4 | 0.0 | 0.0 |
| 6 Colors | two touching halves, four-colour badge | 0.61 | 4.88 | 4.442 | 83.47 | 30.03 | 21.2 | 473 | 53.89 | 45 | 95 | 344.2 | 2.4 | 279 | 68.6 | 79.0 | 0.0 | 0.2 |
| 16 Colors | two touching halves, four-colour badge | 0.60 | 5.32 | 5.084 | 85.85 | 4.16 | 69.9 | 1743 | 196.62 | 49 | 98 | 1376.4 | 5.9 | 612 | 152.8 | 141.8 | 0.2 | 0.6 |
| Shades of Gray | gradient, photo-like | 9.29 | 9.12 | – | – | – | 90.7 | 3183 | – | 51 | – | – | – | – | 0.0 | – | 5.3 | 0.8 |
| Black and White Logo | circle, ellipses, badge with a hole, letter D, polygons, star, letter A | 2.58 | 9.39 | 0.064 | 1.00 | 2.18 | 1.4 | 27 | 2.73 | 40 | 67 | 0.3 | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | circle, ellipses, badge with a hole, letter D, lines | 2.71 | 12.11 | 0.195 | 1.00 | 105.54 | 1.8 | 17 | 1.49 | 16 | 86 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | circle, ellipses, badge with a hole, letter D | 2.98 | 19.28 | 0.532 | 2.24 | 2.24 | 1.2 | 14 | 1.65 | 12 | 79 | 0.1 | – | – | – | – | 0.0 | 0.0 |
| Line Art | lines | 2.65 | 9.87 | 0.093 | 0.89 | 105.71 | 5.4 | 77 | 3.86 | 37 | – | – | – | – | – | – | 0.1 | 0.0 |
| Technical Drawing | polygons, star, letter A, lines | 2.53 | 9.47 | 0.086 | 0.99 | 105.85 | 4.8 | 57 | 3.73 | 69 | 74 | 0.7 | – | – | – | – | 0.3 | 0.0 |
| Flat Logo | two touching halves, four-colour badge | 0.43 | 3.53 | 3.106 | 88.50 | 0.78 | 69.9 | 352 | 38.92 | 38 | 80 | 237.0 | 0.0 | 0 | 13.8 | – | 59.1 | 0.2 |
## 2. Each preset on each kind of input (clean, three sizes)
| preset | inputs | ΔE | edge ΔE | off mean | off max | missed max | paths | anchors | × art | lines % | corners % | kinks | odd colours | odd px | gap px | overlap px | specks |
|:--|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| Default | curved shapes | 0.38 | 16.26 | 0.310 | 1.51 | 1.08 | 1.8 | 13 | 1.54 | 11 | 100 | 1.6 | – | – | 91.2 | 104.1 | 0.0 |
| Default | polygons | 0.37 | 14.70 | 0.281 | 1.34 | 1.68 | 2.0 | 14 | 1.26 | 79 | 91 | 0.3 | – | – | 14.1 | 19.4 | 0.0 |
| Default | thin lines | 0.80 | 10.48 | 0.180 | 1.09 | 105.61 | 3.3 | 15 | 0.73 | 90 | – | – | – | – | 89.4 | 26.0 | 0.0 |
| Default | flat colour art | 20.03 | 22.55 | 0.396 | 1.23 | 178.71 | 1.5 | 15 | 1.08 | 7 | 0 | 2.0 | – | – | 130.9 | 133.5 | 0.0 |
| Default | gradient, photo | 39.23 | 38.90 | – | – | – | 3.2 | 350 | – | 65 | – | – | – | – | 83.6 | 29.9 | 0.0 |
| High Fidelity Photo | curved shapes | 0.30 | 13.87 | 0.387 | 1.34 | 1.34 | 9.9 | 65 | 8.17 | 41 | 100 | 21.9 | 8.7 | 296 | 0.0 | – | 3.6 |
| High Fidelity Photo | polygons | 0.42 | 15.98 | 0.364 | 1.34 | 3.10 | 3.3 | 26 | 2.44 | 96 | 61 | 7.2 | 1.7 | 78 | 0.0 | – | 0.0 |
| High Fidelity Photo | thin lines | 1.11 | 17.32 | 0.341 | 0.97 | 45.35 | 13.0 | 49 | 2.43 | 89 | – | – | 6.7 | 532 | 0.0 | – | 3.0 |
| High Fidelity Photo | flat colour art | 0.21 | 6.75 | 0.420 | 1.33 | 1.33 | 48.2 | 219 | 17.76 | 66 | 100 | 108.7 | 23.2 | 1111 | 0.0 | – | 15.0 |
| High Fidelity Photo | gradient, photo | 2.38 | 2.72 | – | – | – | 2936.7 | 47288 | – | 87 | – | – | – | – | 0.0 | – | 898.7 |
| Low Fidelity Photo | curved shapes | 0.39 | 16.85 | 0.440 | 1.77 | 1.77 | 5.0 | 31 | 3.38 | 30 | 100 | 8.1 | 3.8 | 268 | 0.0 | – | 0.0 |
| Low Fidelity Photo | polygons | 0.51 | 18.23 | 0.411 | 1.54 | 3.10 | 3.3 | 23 | 2.13 | 71 | 55 | 4.8 | 1.7 | 79 | 0.0 | – | 0.0 |
| Low Fidelity Photo | thin lines | 1.13 | 17.25 | 0.363 | 1.03 | 45.35 | 5.0 | 24 | 1.22 | 100 | – | – | 1.3 | 498 | 0.0 | – | 0.0 |
| Low Fidelity Photo | flat colour art | 0.27 | 8.33 | 0.462 | 1.87 | 1.87 | 20.0 | 97 | 6.23 | 64 | 100 | 48.8 | 7.0 | 1033 | 0.0 | – | 0.0 |
| Low Fidelity Photo | gradient, photo | 2.70 | 3.06 | – | – | – | 96.2 | 4529 | – | 47 | – | – | – | – | 0.0 | – | 0.0 |
| 3 Colors | curved shapes | 0.80 | 18.57 | 0.400 | 1.65 | 1.54 | 2.8 | 21 | 2.27 | 21 | 100 | 4.8 | 1.0 | 107 | 103.0 | 93.3 | 0.0 |
| 3 Colors | polygons | 0.93 | 16.07 | 0.315 | 1.75 | 2.43 | 2.4 | 17 | 1.59 | 71 | 60 | 2.0 | 0.4 | 23 | 38.3 | 35.3 | 0.0 |
| 3 Colors | thin lines | 0.96 | 12.66 | 0.238 | 0.95 | 45.30 | 5.0 | 22 | 1.08 | 96 | – | – | 3.7 | 1109 | 54.9 | 65.7 | 0.0 |
| 3 Colors | flat colour art | 3.98 | 12.80 | 0.371 | 1.11 | 89.09 | 2.3 | 24 | 1.70 | 30 | 67 | 2.2 | 1.5 | 15185 | 126.7 | 107.6 | 0.0 |
| 3 Colors | gradient, photo | 7.87 | 7.94 | – | – | – | 4.3 | 222 | – | 51 | – | – | – | – | 101.7 | 66.6 | 0.0 |
| 6 Colors | curved shapes | 0.46 | 17.68 | 0.428 | 1.78 | 1.39 | 3.6 | 28 | 3.07 | 26 | 100 | 6.2 | 1.8 | 169 | 101.5 | 165.6 | 0.0 |
| 6 Colors | polygons | 0.45 | 16.94 | 0.369 | 1.56 | 2.44 | 3.1 | 22 | 2.08 | 61 | 48 | 3.4 | 1.1 | 51 | 82.6 | 36.0 | 0.0 |
| 6 Colors | thin lines | 1.18 | 16.03 | 0.314 | 0.95 | 45.35 | 4.0 | 18 | 0.88 | 78 | – | – | 1.7 | 458 | 68.8 | 20.0 | 0.0 |
| 6 Colors | flat colour art | 0.44 | 10.13 | 0.421 | 1.61 | 1.12 | 5.0 | 35 | 2.66 | 56 | 100 | 8.3 | 1.5 | 198 | 165.2 | 178.1 | 0.0 |
| 6 Colors | gradient, photo | 5.55 | 5.80 | – | – | – | 15.5 | 649 | – | 52 | – | – | – | – | 137.7 | 92.2 | 0.0 |
| 16 Colors | curved shapes | 0.48 | 17.72 | 0.431 | 1.40 | 1.39 | 4.2 | 32 | 3.68 | 30 | 100 | 8.4 | 2.5 | 170 | 101.1 | 166.8 | 0.0 |
| 16 Colors | polygons | 0.47 | 17.47 | 0.379 | 1.46 | 3.10 | 3.1 | 24 | 2.18 | 80 | 56 | 5.9 | 1.1 | 51 | 58.9 | 34.0 | 0.0 |
| 16 Colors | thin lines | 1.13 | 17.11 | 0.340 | 1.13 | 45.35 | 4.0 | 20 | 1.00 | 90 | – | – | 1.3 | 365 | 34.1 | 25.2 | 0.0 |
| 16 Colors | flat colour art | 0.37 | 9.54 | 0.453 | 1.35 | 1.26 | 7.5 | 57 | 4.29 | 61 | 100 | 13.0 | 3.0 | 382 | 206.1 | 288.5 | 0.0 |
| 16 Colors | gradient, photo | 3.30 | 3.71 | – | – | – | 72.0 | 2665 | – | 49 | – | – | – | – | 385.4 | 245.8 | 0.0 |
| Shades of Gray | curved shapes | 0.32 | 14.15 | 0.381 | 1.78 | 1.78 | 5.1 | 33 | 3.66 | 31 | 100 | 9.8 | 3.8 | 275 | 0.0 | – | 0.0 |
| Shades of Gray | polygons | 0.44 | 16.95 | 0.387 | 1.44 | 2.33 | 3.3 | 27 | 2.46 | 82 | 57 | 7.7 | 1.7 | 79 | 0.0 | – | 0.0 |
| Shades of Gray | thin lines | 1.11 | 16.92 | 0.354 | 1.03 | 45.35 | 5.0 | 25 | 1.23 | 100 | – | – | 1.3 | 499 | 0.0 | – | 0.0 |
| Shades of Gray | flat colour art | 7.36 | 13.20 | 0.394 | 1.60 | 178.73 | 13.3 | 66 | 4.35 | 41 | 50 | 29.3 | 12.7 | 38774 | 0.0 | – | 0.0 |
| Shades of Gray | gradient, photo | 9.74 | 9.66 | – | – | – | 82.2 | 1950 | – | 46 | – | – | – | – | 0.0 | – | 0.0 |
| Black and White Logo | curved shapes | 0.43 | 16.76 | 0.339 | 1.76 | 1.76 | 1.2 | 39 | 5.15 | 84 | 100 | 21.1 | – | – | – | – | 0.0 |
| Black and White Logo | polygons | 0.27 | 10.59 | 0.202 | 1.34 | 1.68 | 1.7 | 19 | 1.70 | 100 | 95 | 3.0 | – | – | – | – | 0.0 |
| Black and White Logo | thin lines | 0.70 | 8.44 | 0.160 | 0.82 | 77.30 | 10.3 | 45 | 2.23 | 100 | – | – | – | – | – | – | 0.0 |
| Black and White Logo | flat colour art | 19.99 | 20.78 | 0.428 | 1.66 | 178.38 | 1.0 | 40 | 3.92 | 88 | 0 | 24.7 | – | – | – | – | 0.0 |
| Black and White Logo | gradient, photo | 39.20 | 38.88 | – | – | – | 9.0 | 304 | – | 95 | – | – | – | – | – | – | 0.8 |
| Sketched Art | curved shapes | 0.36 | 15.95 | 0.305 | 1.32 | 1.32 | 1.2 | 12 | 1.42 | 11 | 33 | 1.3 | – | – | – | – | 0.0 |
| Sketched Art | polygons | 0.33 | 13.09 | 0.249 | 1.09 | 1.28 | 1.7 | 13 | 1.19 | 83 | 88 | 1.1 | – | – | – | – | 0.0 |
| Sketched Art | thin lines | 0.73 | 9.90 | 0.206 | 0.62 | 52.42 | 4.3 | 19 | 0.95 | 100 | – | – | – | – | – | – | 0.0 |
| Sketched Art | flat colour art | 20.35 | 23.39 | 0.392 | 1.51 | 179.03 | 1.5 | 13 | 0.94 | 7 | 0 | 2.0 | – | – | – | – | 0.0 |
| Sketched Art | gradient, photo | 45.68 | 45.57 | – | – | – | 1.0 | 115 | – | 35 | – | – | – | – | – | – | 0.0 |
| Silhouettes | curved shapes | 0.42 | 17.79 | 0.345 | 1.34 | 1.34 | 1.2 | 10 | 1.17 | 10 | 100 | 1.2 | – | – | – | – | 0.0 |
| Silhouettes | polygons | 0.47 | 17.79 | 0.353 | 1.62 | 2.53 | 1.7 | 12 | 1.10 | 51 | 66 | 0.6 | – | – | – | – | 0.0 |
| Silhouettes | thin lines | 1.20 | 16.32 | 0.316 | 0.89 | 18.29 | 5.0 | 29 | 1.47 | 87 | – | – | – | – | – | – | 0.0 |
| Silhouettes | flat colour art | 23.77 | 31.89 | 0.378 | 1.22 | 187.69 | 1.0 | 8 | 0.65 | 9 | 0 | 1.0 | – | – | – | – | 0.0 |
| Silhouettes | gradient, photo | 61.64 | 61.45 | – | – | – | 0.2 | 1 | – | 18 | – | – | – | – | – | – | 0.0 |
| Line Art | curved shapes | 0.33 | 13.45 | 0.259 | 1.05 | 1.05 | 1.2 | 21 | 2.77 | 22 | 100 | 2.1 | – | – | – | – | 0.0 |
| Line Art | polygons | 0.33 | 12.57 | 0.239 | 1.34 | 1.68 | 1.7 | 16 | 1.44 | 74 | 83 | 0.6 | – | – | – | – | 0.0 |
| Line Art | thin lines | 0.78 | 9.82 | 0.175 | 0.82 | 105.63 | 3.3 | 16 | 0.80 | 89 | – | – | – | – | – | – | 0.0 |
| Line Art | flat colour art | 19.97 | 20.23 | 0.352 | 1.06 | 178.81 | 1.0 | 23 | 1.94 | 21 | 0 | 4.2 | – | – | – | – | 0.0 |
| Line Art | gradient, photo | 39.20 | 38.81 | – | – | – | 7.7 | 260 | – | 65 | – | – | – | – | – | – | 0.0 |
| Technical Drawing | curved shapes | 0.43 | 16.76 | 0.339 | 1.76 | 1.76 | 1.2 | 39 | 5.15 | 84 | 100 | 21.1 | – | – | – | – | 0.0 |
| Technical Drawing | polygons | 0.28 | 10.79 | 0.206 | 1.34 | 1.68 | 1.7 | 19 | 1.69 | 100 | 95 | 3.0 | – | – | – | – | 0.0 |
| Technical Drawing | thin lines | 0.64 | 8.26 | 0.171 | 0.82 | 55.59 | 15.3 | 65 | 3.23 | 100 | – | – | – | – | – | – | 0.0 |
| Technical Drawing | flat colour art | 19.99 | 20.78 | 0.428 | 1.66 | 178.38 | 1.0 | 40 | 3.92 | 88 | 0 | 24.7 | – | – | – | – | 0.0 |
| Technical Drawing | gradient, photo | 39.19 | 38.87 | – | – | – | 20.0 | 360 | – | 96 | – | – | – | – | – | – | 9.0 |
| Flat Logo | curved shapes | 0.06 | 2.14 | 0.036 | 0.25 | 0.25 | 1.8 | 31 | 3.38 | 19 | 100 | 0.0 | 0.0 | 0 | 6.8 | – | 0.0 |
| Flat Logo | polygons | 0.09 | 3.44 | 0.060 | 0.35 | 1.03 | 2.0 | 35 | 3.17 | 67 | 94 | 0.0 | 0.0 | 0 | 6.8 | – | 0.0 |
| Flat Logo | thin lines | 1.17 | 11.78 | 0.050 | 0.49 | all | 3.0 | 189 | 9.45 | 28 | – | – | 0.0 | 0 | 5467.1 | – | 0.0 |
| Flat Logo | flat colour art | 0.07 | 1.53 | 0.065 | 0.31 | 0.27 | 3.0 | 36 | 3.51 | 47 | 100 | 0.0 | 0.0 | 0 | 6.8 | – | 0.0 |
| Flat Logo | gradient, photo | refused | | | | | | | | | | | | | | | |
| preset | inputs | ΔE | edge ΔE | off mean | off max | missed max | paths | anchors | × art | lines % | corners % | kinks | odd colours | odd px | gap px | overlap px | specks | outside px |
|:--|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| Default | curved shapes | 0.08 | 3.24 | 0.057 | 0.51 | 0.59 | 1.8 | 16 | 1.72 | 15 | 83 | 0.0 | – | – | 22.7 | 21.1 | 0.0 | 0.0 |
| Default | polygons | 0.05 | 2.11 | 0.036 | 0.46 | 1.23 | 2.0 | 14 | 1.24 | 89 | 90 | 0.0 | – | – | 3.1 | 3.3 | 0.0 | 0.0 |
| Default | thin lines | 0.56 | 4.77 | 0.059 | 0.48 | 105.57 | 3.3 | 22 | 1.12 | 42 | – | – | – | – | 49.1 | 34.0 | 0.0 | 0.0 |
| Default | flat colour art | 19.95 | 18.92 | 0.197 | 0.64 | 179.52 | 1.5 | 22 | 1.32 | 15 | 0 | 0.0 | – | – | 24.3 | 23.0 | 0.0 | 0.0 |
| Default | gradient, photo | 39.13 | 38.78 | – | – | – | 3.2 | 698 | – | 57 | – | – | – | – | 31.2 | 40.7 | 0.0 | 0.3 |
| High Fidelity Photo | curved shapes | 0.08 | 3.65 | 0.243 | 1.07 | 0.58 | 9.9 | 187 | 24.84 | 28 | 50 | 0.3 | 8.7 | 299 | 0.0 | – | 3.8 | 0.0 |
| High Fidelity Photo | polygons | 0.13 | 4.80 | 0.160 | 1.14 | 2.43 | 3.3 | 173 | 16.11 | 29 | 78 | 0.1 | 1.7 | 87 | 0.0 | – | 0.0 | 0.0 |
| High Fidelity Photo | thin lines | 0.73 | 8.66 | 0.218 | 0.93 | 45.32 | 13.0 | 498 | 24.90 | 37 | – | – | 6.7 | 532 | 0.0 | – | 7.0 | 0.0 |
| High Fidelity Photo | flat colour art | 0.09 | 2.56 | 0.351 | 1.08 | 0.62 | 48.2 | 497 | 41.54 | 53 | 83 | 9.0 | 23.2 | 1119 | 0.0 | – | 19.2 | 0.0 |
| High Fidelity Photo | gradient, photo | 2.58 | 2.90 | – | – | – | 2926.5 | 87619 | – | 27 | – | – | – | – | 0.0 | – | 792.5 | 0.9 |
| Low Fidelity Photo | curved shapes | 0.09 | 4.45 | 0.219 | 1.02 | 0.50 | 5.0 | 55 | 6.69 | 34 | 100 | 6.7 | 3.8 | 261 | 0.0 | – | 0.0 | 0.0 |
| Low Fidelity Photo | polygons | 0.15 | 5.82 | 0.172 | 0.97 | 2.43 | 3.3 | 55 | 5.12 | 33 | 80 | 0.2 | 1.7 | 81 | 0.0 | – | 0.0 | 0.0 |
| Low Fidelity Photo | thin lines | 0.80 | 9.43 | 0.238 | 0.82 | 45.33 | 5.0 | 182 | 9.08 | 48 | – | – | 1.3 | 497 | 0.0 | – | 0.0 | 0.0 |
| Low Fidelity Photo | flat colour art | 0.11 | 3.30 | 0.323 | 1.04 | 0.56 | 20.0 | 142 | 10.37 | 61 | 100 | 35.7 | 7.0 | 940 | 0.0 | – | 0.0 | 0.0 |
| Low Fidelity Photo | gradient, photo | 2.67 | 2.97 | – | – | – | 96.2 | 8623 | – | 36 | – | – | – | – | 0.0 | – | 0.0 | 0.4 |
| 3 Colors | curved shapes | 0.47 | 4.85 | 0.128 | 1.06 | 0.52 | 2.8 | 30 | 3.42 | 20 | 100 | 1.7 | 1.0 | 86 | 35.0 | 41.9 | 0.0 | 0.0 |
| 3 Colors | polygons | 0.62 | 4.45 | 0.080 | 1.03 | 1.50 | 2.4 | 28 | 2.58 | 43 | 81 | 0.0 | 0.4 | 16 | 10.9 | 13.4 | 0.0 | 0.0 |
| 3 Colors | thin lines | 0.74 | 7.45 | 0.129 | 1.06 | 45.26 | 5.0 | 60 | 3.00 | 37 | – | – | 3.7 | 1123 | 84.3 | 53.1 | 0.0 | 0.0 |
| 3 Colors | flat colour art | 3.77 | 6.61 | 0.191 | 1.35 | 89.46 | 2.3 | 26 | 1.90 | 34 | 38 | 0.3 | 1.5 | 15138 | 35.8 | 28.5 | 0.2 | 0.0 |
| 3 Colors | gradient, photo | 7.85 | 7.91 | – | – | – | 4.3 | 611 | – | 47 | – | – | – | – | 23.6 | 30.1 | 0.0 | 0.2 |
| 6 Colors | curved shapes | 0.11 | 4.81 | 0.186 | 0.96 | 0.50 | 3.6 | 56 | 6.76 | 25 | 100 | 2.8 | 1.8 | 155 | 30.9 | 29.4 | 0.0 | 0.0 |
| 6 Colors | polygons | 0.12 | 4.81 | 0.128 | 0.80 | 1.51 | 3.1 | 56 | 5.23 | 35 | 81 | 0.2 | 1.1 | 47 | 22.2 | 20.6 | 0.0 | 0.0 |
| 6 Colors | thin lines | 0.91 | 9.26 | 0.160 | 0.86 | 45.36 | 4.0 | 132 | 6.60 | 40 | – | – | 1.7 | 409 | 53.6 | 44.0 | 0.0 | 0.0 |
| 6 Colors | flat colour art | 0.19 | 2.98 | 0.216 | 1.29 | 0.51 | 5.0 | 60 | 5.27 | 56 | 100 | 3.0 | 1.5 | 170 | 27.9 | 39.3 | 0.0 | 0.0 |
| 6 Colors | gradient, photo | 5.50 | 5.70 | – | – | – | 15.5 | 1421 | – | 38 | – | – | – | – | 54.3 | 75.6 | 0.0 | 0.2 |
| 16 Colors | curved shapes | 0.09 | 4.14 | 0.200 | 0.97 | 0.50 | 4.2 | 91 | 11.37 | 29 | 100 | 5.3 | 2.5 | 168 | 21.8 | 21.7 | 0.0 | 0.0 |
| 16 Colors | polygons | 0.13 | 5.20 | 0.138 | 0.97 | 2.43 | 3.1 | 81 | 7.53 | 33 | 81 | 0.3 | 1.1 | 52 | 15.3 | 18.5 | 0.0 | 0.0 |
| 16 Colors | thin lines | 0.79 | 9.20 | 0.187 | 0.82 | 45.35 | 4.0 | 287 | 14.35 | 35 | – | – | 1.3 | 362 | 24.9 | 22.6 | 0.0 | 0.0 |
| 16 Colors | flat colour art | 0.12 | 3.16 | 0.279 | 0.99 | 0.45 | 7.5 | 127 | 10.37 | 61 | 100 | 7.5 | 3.0 | 321 | 59.9 | 31.8 | 0.0 | 0.0 |
| 16 Colors | gradient, photo | 3.23 | 3.58 | – | – | – | 72.0 | 4652 | – | 30 | – | – | – | – | 165.5 | 258.6 | 0.0 | 0.8 |
| Shades of Gray | curved shapes | 0.11 | 4.71 | 0.216 | 1.00 | 0.59 | 5.1 | 49 | 6.02 | 30 | 100 | 5.9 | 3.8 | 252 | 0.0 | – | 0.0 | 0.0 |
| Shades of Gray | polygons | 0.11 | 4.32 | 0.147 | 0.80 | 1.39 | 3.3 | 45 | 4.09 | 36 | 82 | 0.0 | 1.7 | 76 | 0.0 | – | 0.0 | 0.0 |
| Shades of Gray | thin lines | 0.81 | 8.80 | 0.239 | 0.70 | 45.31 | 5.0 | 141 | 7.03 | 44 | – | – | 1.3 | 499 | 0.0 | – | 0.0 | 0.0 |
| Shades of Gray | flat colour art | 7.35 | 10.90 | 0.357 | 1.42 | 179.46 | 13.3 | 121 | 10.08 | 42 | 50 | 30.8 | 12.7 | 39181 | 0.0 | – | 0.0 | 0.0 |
| Shades of Gray | gradient, photo | 9.73 | 9.60 | – | – | – | 82.0 | 3181 | – | 51 | – | – | – | – | 0.0 | – | 2.2 | 0.8 |
| Black and White Logo | curved shapes | 0.04 | 1.52 | 0.024 | 0.50 | 0.60 | 1.2 | 21 | 2.25 | 21 | 75 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Black and White Logo | polygons | 0.04 | 1.83 | 0.030 | 0.45 | 1.23 | 1.7 | 15 | 1.34 | 89 | 90 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Black and White Logo | thin lines | 0.50 | 4.22 | 0.065 | 0.50 | 77.21 | 10.3 | 66 | 3.30 | 65 | – | – | – | – | – | – | 0.0 | 0.0 |
| Black and White Logo | flat colour art | 19.94 | 18.72 | 0.192 | 0.31 | 179.52 | 1.0 | 19 | 1.18 | 24 | 0 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Black and White Logo | gradient, photo | 39.11 | 38.71 | – | – | – | 9.0 | 676 | – | 72 | – | – | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | curved shapes | 0.13 | 5.54 | 0.107 | 0.41 | 0.41 | 1.2 | 13 | 1.43 | 17 | 100 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | polygons | 0.13 | 5.00 | 0.092 | 0.51 | 1.07 | 1.7 | 14 | 1.24 | 82 | 86 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | thin lines | 0.38 | 4.99 | 0.102 | 0.80 | 52.57 | 4.3 | 37 | 1.87 | 35 | – | – | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | flat colour art | 20.32 | 20.95 | 0.175 | 0.89 | 179.64 | 1.5 | 22 | 1.34 | 18 | 0 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | gradient, photo | 45.53 | 45.37 | – | – | – | 1.0 | 251 | – | 47 | – | – | – | – | – | – | 0.0 | 0.3 |
| Silhouettes | curved shapes | 0.34 | 14.15 | 0.274 | 0.66 | 0.66 | 1.2 | 12 | 1.36 | 17 | 100 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | polygons | 0.35 | 14.03 | 0.263 | 0.67 | 0.70 | 1.7 | 14 | 1.26 | 76 | 85 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | thin lines | 1.05 | 16.01 | 0.308 | 1.09 | 18.10 | 5.0 | 42 | 2.08 | 40 | – | – | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | flat colour art | 23.86 | 34.06 | 0.226 | 0.77 | 188.38 | 1.0 | 10 | 0.76 | 26 | 0 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | gradient, photo | 61.56 | 61.35 | – | – | – | 0.2 | 2 | – | 47 | – | – | – | – | – | – | 0.0 | 0.6 |
| Line Art | curved shapes | 0.05 | 1.93 | 0.033 | 0.53 | 0.63 | 1.2 | 17 | 1.86 | 19 | 75 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Line Art | polygons | 0.05 | 1.87 | 0.031 | 0.46 | 1.23 | 1.7 | 14 | 1.27 | 89 | 90 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Line Art | thin lines | 0.54 | 4.38 | 0.049 | 0.47 | 105.71 | 3.3 | 33 | 1.67 | 42 | – | – | – | – | – | – | 0.0 | 0.0 |
| Line Art | flat colour art | 19.94 | 18.69 | 0.192 | 0.49 | 179.52 | 1.0 | 46 | 2.55 | 23 | 0 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Line Art | gradient, photo | 39.11 | 38.71 | – | – | – | 7.7 | 490 | – | 59 | – | – | – | – | – | – | 0.0 | 0.1 |
| Technical Drawing | curved shapes | 0.04 | 1.52 | 0.024 | 0.50 | 0.60 | 1.2 | 21 | 2.25 | 21 | 75 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Technical Drawing | polygons | 0.04 | 1.83 | 0.030 | 0.45 | 1.23 | 1.7 | 15 | 1.34 | 89 | 90 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Technical Drawing | thin lines | 0.39 | 3.88 | 0.075 | 0.50 | 55.75 | 15.3 | 81 | 4.05 | 76 | – | – | – | – | – | – | 0.3 | 0.0 |
| Technical Drawing | flat colour art | 19.94 | 18.72 | 0.192 | 0.31 | 179.52 | 1.0 | 19 | 1.18 | 24 | 0 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Technical Drawing | gradient, photo | 39.08 | 38.69 | – | – | – | 20.0 | 964 | – | 79 | – | – | – | – | – | – | 2.0 | 0.1 |
| Flat Logo | curved shapes | 0.06 | 2.14 | 0.036 | 0.25 | 0.25 | 1.8 | 31 | 3.38 | 19 | 100 | 0.0 | 0.0 | 0 | 6.8 | – | 0.0 | 0.0 |
| Flat Logo | polygons | 0.09 | 3.44 | 0.060 | 0.35 | 1.03 | 2.0 | 35 | 3.17 | 67 | 94 | 0.0 | 0.0 | 0 | 6.8 | – | 0.0 | 0.0 |
| Flat Logo | thin lines | 1.17 | 11.78 | 0.050 | 0.49 | all | 3.0 | 189 | 9.45 | 28 | – | – | 0.0 | 0 | 5467.1 | – | 0.0 | 0.0 |
| Flat Logo | flat colour art | 0.07 | 1.53 | 0.065 | 0.31 | 0.27 | 3.0 | 36 | 3.51 | 47 | 100 | 0.0 | 0.0 | 0 | 6.8 | – | 0.0 | 0.0 |
| Flat Logo | gradient, photo | refused | | | | | | | | | | | | | | | | |
## 3. Each preset on its inputs, by variant (256 px)
| preset | variant | ΔE | edge ΔE | off mean | off max | missed max | paths | anchors | × art | lines % | corners % | kinks | odd colours | odd px | gap px | overlap px | specks |
|:--|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| Default | clean | 0.37 | 15.59 | 0.297 | 1.51 | 1.68 | 1.9 | 14 | 1.42 | 40 | 93 | 1.0 | – | – | 58.1 | 67.8 | 0.0 |
| Default | blurred | 0.90 | 18.86 | 0.363 | 1.41 | 2.23 | 1.9 | 16 | 1.56 | 25 | 38 | 3.0 | – | – | 72.1 | 85.2 | 0.0 |
| Default | noisy | 1.97 | 10.79 | 0.293 | 1.48 | 1.68 | 1.9 | 13 | 1.35 | 33 | 83 | 0.7 | – | – | 67.2 | 61.8 | 0.0 |
| Default | scanned | 15.12 | 21.14 | 0.354 | 1.41 | 2.52 | 1.9 | 16 | 1.68 | 19 | 32 | 2.4 | – | – | 77.2 | 59.3 | 0.0 |
| High Fidelity Photo | clean | 2.38 | 2.72 | – | – | – | 2936.7 | 47288 | – | 87 | – | – | – | – | 0.0 | – | 898.7 |
| High Fidelity Photo | blurred | 1.98 | 2.47 | – | – | – | 1486.5 | 19972 | – | 88 | – | – | – | – | 0.0 | – | 274.5 |
| High Fidelity Photo | noisy | 2.78 | 3.04 | – | – | – | 7340.0 | 70154 | – | 74 | – | – | – | – | 0.0 | – | 2494.5 |
| High Fidelity Photo | scanned | 1.84 | 2.01 | – | – | – | 5227.5 | 61967 | – | 76 | – | – | – | – | 0.0 | – | 2009.5 |
| Low Fidelity Photo | clean | 2.70 | 3.06 | – | – | – | 96.2 | 4529 | – | 47 | – | – | – | – | 0.0 | – | 0.0 |
| Low Fidelity Photo | blurred | 2.68 | 3.17 | – | – | – | 151.5 | 2258 | – | 47 | – | – | – | – | 0.0 | – | 0.0 |
| Low Fidelity Photo | noisy | 2.78 | 2.99 | – | – | – | 106.5 | 3818 | – | 30 | – | – | – | – | 0.0 | – | 0.0 |
| Low Fidelity Photo | scanned | 2.08 | 2.21 | – | – | – | 226.0 | 4414 | – | 31 | – | – | – | – | 0.0 | – | 0.0 |
| 3 Colors | clean | 4.71 | 12.75 | 0.362 | 1.11 | 89.09 | 1.3 | 9 | 1.50 | 13 | 33 | 0.0 | 0.7 | 10502 | 112.5 | 95.5 | 0.0 |
| 3 Colors | blurred | 6.97 | 11.97 | 0.858 | 2.35 | 87.85 | 4.0 | 22 | 3.67 | 1 | 0 | 8.0 | 4.0 | 25530 | 134.6 | 100.1 | 0.0 |
| 3 Colors | noisy | 7.30 | 12.66 | 0.395 | 0.95 | 89.02 | 1.0 | 8 | 1.33 | 0 | 0 | 0.0 | 1.0 | 25239 | 71.4 | 60.4 | 0.0 |
| 3 Colors | scanned | 5.92 | 7.24 | 0.761 | 1.75 | 88.20 | 4.0 | 30 | 5.00 | 1 | 0 | 7.0 | 4.0 | 25648 | 166.3 | 112.5 | 0.0 |
| 6 Colors | clean | 0.44 | 10.13 | 0.421 | 1.61 | 1.12 | 5.0 | 35 | 2.66 | 56 | 100 | 8.3 | 1.5 | 198 | 165.2 | 178.1 | 0.0 |
| 6 Colors | blurred | 0.89 | 9.39 | 0.695 | 2.33 | 1.98 | 10.0 | 108 | 9.68 | 41 | 100 | 26.5 | 6.0 | 800 | 125.1 | 197.9 | 0.0 |
| 6 Colors | noisy | 1.39 | 6.91 | 19.919 | 79.80 | 30.11 | 99.0 | 1218 | 146.12 | 55 | 100 | 1124.5 | 3.0 | 363 | 445.5 | 296.0 | 0.0 |
| 6 Colors | scanned | 1.53 | 4.87 | 8.493 | 83.10 | 1.39 | 21.5 | 428 | 45.40 | 53 | 88 | 318.0 | 3.0 | 148 | 214.3 | 212.0 | 0.0 |
| 16 Colors | clean | 0.37 | 9.54 | 0.453 | 1.35 | 1.26 | 7.5 | 57 | 4.29 | 61 | 100 | 13.0 | 3.0 | 382 | 206.1 | 288.5 | 0.0 |
| 16 Colors | blurred | 0.66 | 10.88 | 1.030 | 2.74 | 2.36 | 26.5 | 182 | 15.72 | 86 | 100 | 117.0 | 10.0 | 1168 | 177.5 | 323.7 | 0.0 |
| 16 Colors | noisy | 1.50 | 8.23 | 16.918 | 81.85 | 4.32 | 238.5 | 2540 | 312.41 | 45 | 100 | 2187.0 | 4.5 | 770 | 596.1 | 426.6 | 0.0 |
| 16 Colors | scanned | 1.59 | 4.44 | 16.175 | 86.21 | 3.61 | 199.0 | 3534 | 376.23 | 51 | 100 | 3016.0 | 18.0 | 1609 | 552.9 | 575.6 | 0.0 |
| Shades of Gray | clean | 9.74 | 9.66 | – | – | – | 82.2 | 1950 | – | 46 | – | – | – | – | 0.0 | – | 0.0 |
| Shades of Gray | blurred | 9.69 | 9.42 | – | – | – | 62.0 | 1002 | – | 46 | – | – | – | – | 0.0 | – | 0.0 |
| Shades of Gray | noisy | 9.79 | 9.54 | – | – | – | 132.0 | 2312 | – | 34 | – | – | – | – | 0.0 | – | 1.5 |
| Shades of Gray | scanned | 6.63 | 6.56 | – | – | – | 115.0 | 2778 | – | 29 | – | – | – | – | 0.0 | – | 0.0 |
| Black and White Logo | clean | 0.36 | 14.11 | 0.280 | 1.76 | 1.76 | 1.4 | 30 | 3.67 | 91 | 97 | 13.3 | – | – | – | – | 0.0 |
| Black and White Logo | blurred | 0.87 | 17.99 | 0.317 | 1.43 | 2.23 | 1.4 | 32 | 3.85 | 86 | 40 | 17.0 | – | – | – | – | 0.0 |
| Black and White Logo | noisy | 1.92 | 9.17 | 0.233 | 1.55 | 1.68 | 1.4 | 32 | 3.87 | 92 | 96 | 14.3 | – | – | – | – | 0.0 |
| Black and White Logo | scanned | 15.07 | 20.40 | 0.265 | 1.65 | 2.53 | 1.4 | 36 | 4.09 | 89 | 47 | 20.0 | – | – | – | – | 0.0 |
| Sketched Art | clean | 0.43 | 14.74 | 0.285 | 1.32 | 52.42 | 1.9 | 14 | 1.33 | 29 | 33 | 1.3 | – | – | – | – | 0.0 |
| Sketched Art | blurred | 1.06 | 19.54 | 0.312 | 1.29 | 105.61 | 1.6 | 14 | 1.30 | 26 | 0 | 1.5 | – | – | – | – | 0.0 |
| Sketched Art | noisy | 2.00 | 11.50 | 0.309 | 1.06 | 1.06 | 2.0 | 13 | 1.26 | 27 | 25 | 1.5 | – | – | – | – | 0.0 |
| Sketched Art | scanned | 15.05 | 21.60 | 0.361 | 1.63 | 105.46 | 1.6 | 15 | 1.53 | 27 | 0 | 1.2 | – | – | – | – | 0.0 |
| Silhouettes | clean | 0.42 | 17.79 | 0.345 | 1.34 | 1.34 | 1.2 | 10 | 1.17 | 10 | 100 | 1.2 | – | – | – | – | 0.0 |
| Silhouettes | blurred | 1.23 | 28.03 | 0.754 | 1.87 | 1.90 | 1.2 | 8 | 0.97 | 7 | 50 | 1.5 | – | – | – | – | 0.0 |
| Silhouettes | noisy | 2.23 | 13.42 | 0.384 | 1.17 | 1.17 | 1.2 | 9 | 1.09 | 7 | 100 | 1.5 | – | – | – | – | 0.0 |
| Silhouettes | scanned | 16.06 | 29.87 | 1.494 | 2.88 | 2.89 | 1.2 | 12 | 1.52 | 12 | 50 | 2.0 | – | – | – | – | 0.0 |
| Line Art | clean | 0.78 | 9.82 | 0.175 | 0.82 | 105.63 | 3.3 | 16 | 0.80 | 89 | – | – | – | – | – | – | 0.0 |
| Line Art | blurred | 1.59 | 16.64 | 0.128 | 1.13 | 105.76 | 3.0 | 17 | 0.85 | 94 | – | – | – | – | – | – | 0.0 |
| Line Art | noisy | 1.22 | 7.62 | 0.137 | 0.91 | 56.14 | 8.0 | 36 | 1.80 | 97 | – | – | – | – | – | – | 0.0 |
| Line Art | scanned | 13.55 | 19.72 | 0.173 | 1.13 | 105.76 | 3.0 | 17 | 0.85 | 78 | – | – | – | – | – | – | 0.0 |
| Technical Drawing | clean | 0.37 | 10.16 | 0.197 | 1.34 | 55.59 | 5.1 | 30 | 2.07 | 100 | 95 | 3.0 | – | – | – | – | 0.0 |
| Technical Drawing | blurred | 1.07 | 17.47 | 0.202 | 1.37 | 105.76 | 2.0 | 24 | 1.98 | 100 | 54 | 13.7 | – | – | – | – | 0.0 |
| Technical Drawing | noisy | 1.58 | 8.47 | 0.195 | 1.23 | 31.30 | 7.8 | 43 | 2.79 | 100 | 94 | 2.7 | – | – | – | – | 1.0 |
| Technical Drawing | scanned | 14.47 | 20.51 | 0.228 | 1.36 | 105.76 | 2.0 | 26 | 2.17 | 100 | 62 | 13.3 | – | – | – | – | 0.0 |
| Flat Logo | clean | 0.07 | 1.53 | 0.065 | 0.31 | 0.27 | 3.0 | 36 | 3.51 | 47 | 100 | 0.0 | 0.0 | 0 | 6.8 | – | 0.0 |
| Flat Logo | blurred | 0.54 | 8.33 | 0.052 | 0.62 | 0.78 | 3.0 | 28 | 1.78 | 43 | 50 | 0.0 | 0.0 | 0 | 5.8 | – | 0.0 |
| Flat Logo | noisy | 0.81 | 1.77 | 0.076 | 0.39 | 0.32 | 3.5 | 44 | 2.63 | 31 | 100 | 1.0 | 0.0 | 0 | 6.9 | – | 0.5 |
| Flat Logo | scanned | 1.31 | 4.15 | 21.204 | 88.50 | 0.66 | 470.5 | 2251 | 255.53 | 11 | 62 | 1658.0 | 0.0 | 0 | 58.0 | – | 413.5 |
| preset | variant | ΔE | edge ΔE | off mean | off max | missed max | paths | anchors | × art | lines % | corners % | kinks | odd colours | odd px | gap px | overlap px | specks | outside px |
|:--|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| Default | clean | 0.07 | 2.76 | 0.048 | 0.51 | 1.23 | 1.9 | 15 | 1.52 | 46 | 88 | 0.0 | – | – | 14.3 | 13.5 | 0.0 | 0.0 |
| Default | aliased | 0.39 | 21.13 | 0.229 | 1.02 | 1.34 | 1.9 | 14 | 1.42 | 21 | 98 | 0.0 | – | – | 52.7 | 52.9 | 0.0 | 0.0 |
| Default | blurred | 0.82 | 16.65 | 0.078 | 0.86 | 2.17 | 1.9 | 26 | 2.50 | 7 | 19 | 1.6 | – | – | 23.0 | 23.6 | 0.0 | 0.0 |
| Default | noisy | 1.74 | 4.55 | 0.052 | 0.57 | 1.23 | 1.9 | 16 | 1.64 | 38 | 67 | 0.0 | – | – | 16.2 | 15.1 | 0.0 | 0.0 |
| Default | scanned | 15.06 | 20.24 | 0.134 | 0.87 | 2.17 | 1.9 | 26 | 2.53 | 0 | 25 | 1.0 | – | – | 20.8 | 24.7 | 0.0 | 0.0 |
| High Fidelity Photo | clean | 2.58 | 2.90 | – | – | – | 2926.5 | 87619 | – | 27 | – | – | – | – | 0.0 | – | 792.5 | 0.9 |
| High Fidelity Photo | aliased | 2.55 | 2.88 | – | – | – | 2686.0 | 56883 | – | 22 | – | – | – | – | 0.0 | – | 695.5 | 0.9 |
| High Fidelity Photo | blurred | 2.05 | 2.50 | – | – | – | 1486.5 | 37982 | – | 22 | – | – | – | – | 0.0 | – | 205.5 | 1.3 |
| High Fidelity Photo | noisy | 3.10 | 3.37 | – | – | – | 7294.5 | 118138 | – | 26 | – | – | – | – | 0.0 | – | 2051.5 | 0.6 |
| High Fidelity Photo | scanned | 2.04 | 2.22 | – | – | – | 5208.5 | 95324 | – | 24 | – | – | – | – | 0.0 | – | 1637.0 | 0.4 |
| Low Fidelity Photo | clean | 2.67 | 2.97 | – | – | – | 96.2 | 8623 | – | 36 | – | – | – | – | 0.0 | – | 0.0 | 0.4 |
| Low Fidelity Photo | aliased | 2.62 | 2.91 | – | – | – | 125.5 | 5195 | – | 34 | – | – | – | – | 0.0 | – | 0.0 | 0.2 |
| Low Fidelity Photo | blurred | 2.67 | 3.13 | – | – | – | 151.5 | 4525 | – | 33 | – | – | – | – | 0.0 | – | 0.0 | 0.2 |
| Low Fidelity Photo | noisy | 2.75 | 2.94 | – | – | – | 106.5 | 7104 | – | 39 | – | – | – | – | 0.0 | – | 0.0 | 0.2 |
| Low Fidelity Photo | scanned | 2.07 | 2.19 | – | – | – | 226.0 | 8249 | – | 40 | – | – | – | – | 0.0 | – | 0.5 | 0.2 |
| 3 Colors | clean | 4.62 | 7.50 | 0.106 | 0.35 | 89.46 | 1.3 | 11 | 1.78 | 13 | 33 | 0.0 | 0.7 | 10577 | 33.4 | 32.3 | 0.0 | 0.0 |
| 3 Colors | aliased | 0.18 | 9.81 | 0.236 | 0.74 | 0.56 | 2.0 | 7 | 1.17 | 39 | 100 | 0.0 | 0.0 | 0 | 123.2 | 82.4 | 0.0 | 0.0 |
| 3 Colors | blurred | 6.92 | 10.46 | 0.848 | 2.02 | 87.75 | 4.0 | 122 | 20.33 | 0 | 0 | 10.0 | 4.0 | 25697 | 51.3 | 37.6 | 0.0 | 0.0 |
| 3 Colors | noisy | 7.21 | 9.91 | 0.112 | 0.31 | 89.49 | 1.0 | 12 | 2.00 | 0 | 0 | 0.0 | 1.0 | 25398 | 37.8 | 18.2 | 0.0 | 0.0 |
| 3 Colors | scanned | 5.86 | 6.64 | 0.814 | 1.49 | 88.54 | 4.0 | 93 | 15.50 | 0 | 0 | 8.0 | 4.0 | 25863 | 39.3 | 47.4 | 0.0 | 0.0 |
| 6 Colors | clean | 0.19 | 2.98 | 0.216 | 1.29 | 0.51 | 5.0 | 60 | 5.27 | 56 | 100 | 3.0 | 1.5 | 170 | 27.9 | 39.3 | 0.0 | 0.0 |
| 6 Colors | aliased | 0.31 | 10.53 | 0.291 | 1.00 | 1.00 | 3.0 | 26 | 1.91 | 42 | 100 | 0.0 | 0.0 | 0 | 82.6 | 74.0 | 0.0 | 0.0 |
| 6 Colors | blurred | 0.76 | 6.94 | 0.685 | 1.52 | 1.02 | 10.0 | 204 | 22.77 | 43 | 100 | 23.5 | 6.0 | 976 | 49.1 | 39.8 | 0.0 | 0.0 |
| 6 Colors | noisy | 1.20 | 3.58 | 20.366 | 79.78 | 30.03 | 99.0 | 2064 | 245.68 | 30 | 100 | 1822.5 | 3.0 | 297 | 191.1 | 209.1 | 0.0 | 0.2 |
| 6 Colors | scanned | 1.47 | 4.15 | 9.100 | 83.47 | 0.94 | 21.5 | 835 | 91.04 | 30 | 62 | 554.5 | 3.0 | 172 | 73.9 | 112.0 | 0.0 | 0.2 |
| 16 Colors | clean | 0.12 | 3.16 | 0.279 | 0.99 | 0.45 | 7.5 | 127 | 10.37 | 61 | 100 | 7.5 | 3.0 | 321 | 59.9 | 31.8 | 0.0 | 0.0 |
| 16 Colors | aliased | 0.30 | 10.39 | 0.274 | 1.00 | 1.00 | 3.0 | 34 | 2.34 | 43 | 100 | 0.0 | 0.0 | 0 | 77.3 | 51.7 | 0.0 | 0.0 |
| 16 Colors | blurred | 0.59 | 8.94 | 0.949 | 2.58 | 1.73 | 26.5 | 421 | 35.52 | 57 | 100 | 102.5 | 10.0 | 1155 | 149.8 | 121.6 | 0.0 | 0.0 |
| 16 Colors | noisy | 1.31 | 4.52 | 17.093 | 82.18 | 4.16 | 238.5 | 4758 | 593.71 | 29 | 100 | 4008.5 | 4.5 | 607 | 313.9 | 328.8 | 0.0 | 0.2 |
| 16 Colors | scanned | 1.63 | 3.93 | 16.438 | 85.85 | 3.01 | 199.0 | 6606 | 713.67 | 29 | 88 | 5501.0 | 18.0 | 1561 | 349.0 | 394.9 | 1.5 | 0.6 |
| Shades of Gray | clean | 9.73 | 9.60 | – | – | – | 82.0 | 3181 | – | 51 | – | – | – | – | 0.0 | – | 2.2 | 0.8 |
| Shades of Gray | aliased | 9.73 | 9.58 | – | – | – | 80.0 | 2438 | – | 54 | – | – | – | – | 0.0 | – | 3.0 | 0.8 |
| Shades of Gray | blurred | 9.69 | 9.39 | – | – | – | 62.0 | 1652 | – | 50 | – | – | – | – | 0.0 | – | 1.0 | 0.7 |
| Shades of Gray | noisy | 9.79 | 9.52 | – | – | – | 132.0 | 3813 | – | 51 | – | – | – | – | 0.0 | – | 9.0 | 0.8 |
| Shades of Gray | scanned | 6.64 | 6.56 | – | – | – | 115.0 | 4832 | – | 48 | – | – | – | – | 0.0 | – | 17.5 | 0.5 |
| Black and White Logo | clean | 0.04 | 1.65 | 0.027 | 0.50 | 1.23 | 1.4 | 18 | 1.86 | 50 | 86 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Black and White Logo | aliased | 0.39 | 20.41 | 0.176 | 1.00 | 1.34 | 1.4 | 24 | 2.47 | 53 | 98 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Black and White Logo | blurred | 0.81 | 16.37 | 0.047 | 0.80 | 2.18 | 1.4 | 39 | 3.78 | 23 | 19 | 1.0 | – | – | – | – | 0.0 | 0.0 |
| Black and White Logo | noisy | 1.72 | 3.90 | 0.028 | 0.50 | 1.23 | 1.4 | 21 | 2.14 | 41 | 67 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Black and White Logo | scanned | 15.05 | 20.10 | 0.116 | 0.82 | 2.17 | 1.4 | 53 | 5.13 | 11 | 25 | 0.9 | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | clean | 0.18 | 5.43 | 0.106 | 0.80 | 52.57 | 1.9 | 18 | 1.52 | 20 | 100 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | aliased | 0.49 | 20.73 | 0.237 | 1.00 | 105.54 | 1.6 | 10 | 1.02 | 27 | 100 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | blurred | 1.07 | 19.51 | 0.264 | 0.66 | 105.48 | 1.6 | 18 | 1.57 | 13 | 50 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | noisy | 1.75 | 5.86 | 0.108 | 0.95 | 1.03 | 2.0 | 18 | 1.53 | 13 | 100 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Sketched Art | scanned | 15.11 | 22.41 | 0.438 | 0.85 | 105.28 | 1.6 | 20 | 1.73 | 1 | 50 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | clean | 0.34 | 14.15 | 0.274 | 0.66 | 0.66 | 1.2 | 12 | 1.36 | 17 | 100 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | aliased | 0.42 | 23.04 | 0.353 | 1.03 | 1.03 | 1.2 | 9 | 1.05 | 9 | 100 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | blurred | 1.23 | 28.51 | 0.803 | 1.42 | 1.84 | 1.2 | 17 | 1.91 | 13 | 50 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | noisy | 2.10 | 10.67 | 0.274 | 0.64 | 0.64 | 1.2 | 12 | 1.34 | 7 | 100 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Silhouettes | scanned | 16.05 | 30.27 | 1.472 | 2.24 | 2.24 | 1.2 | 23 | 3.15 | 3 | 0 | 1.0 | – | – | – | – | 0.0 | 0.0 |
| Line Art | clean | 0.54 | 4.38 | 0.049 | 0.47 | 105.71 | 3.3 | 33 | 1.67 | 42 | – | – | – | – | – | – | 0.0 | 0.0 |
| Line Art | aliased | 0.66 | 14.39 | 0.110 | 0.74 | 55.44 | 14.0 | 60 | 3.00 | 87 | – | – | – | – | – | – | 0.0 | 0.0 |
| Line Art | blurred | 1.63 | 17.25 | 0.137 | 0.89 | 105.61 | 3.0 | 139 | 6.95 | 3 | – | – | – | – | – | – | 0.0 | 0.0 |
| Line Art | noisy | 1.03 | 4.27 | 0.043 | 0.48 | 56.06 | 8.0 | 56 | 2.80 | 41 | – | – | – | – | – | – | 1.0 | 0.0 |
| Line Art | scanned | 13.60 | 20.04 | 0.212 | 0.84 | 105.58 | 3.0 | 186 | 9.30 | 0 | – | – | – | – | – | – | 0.0 | 0.0 |
| Technical Drawing | clean | 0.13 | 2.34 | 0.041 | 0.50 | 55.75 | 5.1 | 32 | 2.02 | 86 | 90 | 0.0 | – | – | – | – | 0.1 | 0.0 |
| Technical Drawing | aliased | 0.43 | 18.55 | 0.206 | 0.99 | 55.44 | 6.8 | 34 | 2.08 | 95 | 97 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| Technical Drawing | blurred | 1.05 | 16.72 | 0.088 | 0.95 | 105.75 | 2.0 | 97 | 6.62 | 28 | 25 | 2.7 | – | – | – | – | 0.0 | 0.0 |
| Technical Drawing | noisy | 1.39 | 3.88 | 0.042 | 0.50 | 31.23 | 7.8 | 46 | 2.76 | 81 | 90 | 0.0 | – | – | – | – | 1.8 | 0.0 |
| Technical Drawing | scanned | 14.45 | 20.15 | 0.145 | 0.92 | 105.85 | 2.0 | 126 | 8.57 | 22 | 36 | 2.3 | – | – | – | – | 0.0 | 0.0 |
| Flat Logo | clean | 0.07 | 1.53 | 0.065 | 0.31 | 0.27 | 3.0 | 36 | 3.51 | 47 | 100 | 0.0 | 0.0 | 0 | 6.8 | – | 0.0 | 0.0 |
| Flat Logo | aliased | 0.13 | 5.87 | 0.218 | 0.65 | 0.65 | 3.0 | 31 | 1.96 | 44 | 50 | 0.0 | 0.0 | 0 | 5.8 | – | 0.0 | 0.0 |
| Flat Logo | blurred | 0.54 | 8.33 | 0.052 | 0.62 | 0.78 | 3.0 | 28 | 1.78 | 43 | 50 | 0.0 | 0.0 | 0 | 5.8 | – | 0.0 | 0.0 |
| Flat Logo | noisy | 0.81 | 1.77 | 0.076 | 0.39 | 0.32 | 3.5 | 44 | 2.63 | 31 | 100 | 1.0 | 0.0 | 0 | 6.9 | – | 0.5 | 0.0 |
| Flat Logo | scanned | 1.31 | 4.15 | 21.204 | 88.50 | 0.66 | 470.5 | 2251 | 255.53 | 11 | 62 | 1658.0 | 0.0 | 0 | 58.0 | – | 413.5 | 0.2 |
## 4. Yardstick
@@ -203,20 +258,23 @@ Inkscape 1.4.2's Trace Bitmap, run as a black box through its `object-trace` act
removed, its other settings as they come) on the same one-colour drawings, and its SVG output measured by
the same code. Compare with the black-and-white presets on the same kinds of input in section 2 and 3.
| inputs | variant | ΔE | edge ΔE | off mean | off max | missed max | paths | anchors | × art | lines % | corners % | kinks | odd colours | odd px | gap px | overlap px | specks |
|:--|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| curved shapes | clean | 0.25 | 11.05 | 0.198 | 0.97 | 0.97 | 1.0 | 15 | 1.98 | 11 | 83 | 1.8 | – | – | – | – | 0.0 |
| curved shapes | blurred | 0.79 | 16.57 | 0.182 | 0.86 | 1.14 | 1.0 | 15 | 1.84 | 6 | 0 | 1.8 | – | – | – | – | 0.0 |
| curved shapes | noisy | 2.01 | 8.14 | 0.191 | 0.93 | 0.93 | 1.0 | 17 | 2.06 | 10 | 75 | 2.8 | – | – | – | – | 0.0 |
| curved shapes | scanned | 15.31 | 20.22 | 0.191 | 0.97 | 1.14 | 1.0 | 16 | 1.98 | 7 | 0 | 2.0 | – | – | – | – | 0.0 |
| polygons | clean | 0.16 | 6.45 | 0.124 | 1.26 | 2.36 | 1.0 | 21 | 1.93 | 27 | 34 | 0.0 | – | – | – | – | 0.0 |
| polygons | blurred | 0.90 | 17.54 | 0.190 | 1.20 | 2.56 | 1.0 | 19 | 1.75 | 0 | 0 | 0.0 | – | – | – | – | 0.0 |
| polygons | noisy | 1.62 | 6.05 | 0.119 | 1.22 | 2.32 | 1.0 | 22 | 2.01 | 29 | 19 | 0.0 | – | – | – | – | 0.0 |
| polygons | scanned | 14.75 | 20.30 | 0.170 | 1.49 | 2.55 | 1.0 | 21 | 1.90 | 4 | 3 | 0.0 | – | – | – | – | 0.0 |
| thin lines | clean | 0.44 | 6.05 | 0.109 | 0.98 | 76.81 | 1.0 | 34 | 1.72 | 2 | – | – | – | – | – | – | 0.0 |
| thin lines | blurred | 1.72 | 18.80 | 0.254 | 0.81 | 106.00 | 1.0 | 18 | 0.90 | 0 | – | – | – | – | – | – | 0.0 |
| thin lines | noisy | 1.02 | 6.25 | 0.112 | 1.00 | 37.89 | 1.0 | 25 | 1.25 | 0 | – | – | – | – | – | – | 0.0 |
| thin lines | scanned | 28.94 | 46.83 | 12.147 | 43.11 | 20.79 | 1.0 | 2763 | 138.15 | 2 | – | – | – | – | – | – | 0.0 |
| inputs | variant | ΔE | edge ΔE | off mean | off max | missed max | paths | anchors | × art | lines % | corners % | kinks | odd colours | odd px | gap px | overlap px | specks | outside px |
|:--|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| curved shapes | clean | 0.25 | 11.05 | 0.198 | 0.97 | 0.97 | 1.0 | 15 | 1.98 | 11 | 83 | 1.8 | – | – | – | – | 0.0 | 0.0 |
| curved shapes | aliased | 0.38 | 20.79 | 0.192 | 0.88 | 0.88 | 1.0 | 16 | 1.88 | 14 | 50 | 1.8 | – | – | – | – | 0.0 | 0.0 |
| curved shapes | blurred | 0.79 | 16.57 | 0.182 | 0.86 | 1.14 | 1.0 | 15 | 1.84 | 6 | 0 | 1.8 | – | – | – | – | 0.0 | 0.0 |
| curved shapes | noisy | 2.01 | 8.14 | 0.191 | 0.93 | 0.93 | 1.0 | 17 | 2.06 | 10 | 75 | 2.8 | – | – | – | – | 0.0 | 0.0 |
| curved shapes | scanned | 15.31 | 20.22 | 0.191 | 0.97 | 1.14 | 1.0 | 16 | 1.98 | 7 | 0 | 2.0 | – | – | – | – | 0.0 | 0.0 |
| polygons | clean | 0.16 | 6.45 | 0.124 | 1.26 | 2.36 | 1.0 | 21 | 1.93 | 27 | 34 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| polygons | aliased | 0.35 | 18.33 | 0.150 | 1.22 | 2.35 | 1.0 | 20 | 1.81 | 20 | 28 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| polygons | blurred | 0.90 | 17.54 | 0.190 | 1.20 | 2.56 | 1.0 | 19 | 1.75 | 0 | 0 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| polygons | noisy | 1.62 | 6.05 | 0.119 | 1.22 | 2.32 | 1.0 | 22 | 2.01 | 29 | 19 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| polygons | scanned | 14.75 | 20.30 | 0.170 | 1.49 | 2.55 | 1.0 | 21 | 1.90 | 4 | 3 | 0.0 | – | – | – | – | 0.0 | 0.0 |
| thin lines | clean | 0.44 | 6.05 | 0.109 | 0.98 | 76.81 | 1.0 | 34 | 1.72 | 2 | – | – | – | – | – | – | 0.0 | 0.0 |
| thin lines | aliased | 0.74 | 16.37 | 0.099 | 1.17 | 55.97 | 1.0 | 22 | 1.10 | 6 | – | – | – | – | – | – | 0.0 | 0.0 |
| thin lines | blurred | 1.72 | 18.80 | 0.254 | 0.81 | 106.00 | 1.0 | 18 | 0.90 | 0 | – | – | – | – | – | – | 0.0 | 0.0 |
| thin lines | noisy | 1.02 | 6.25 | 0.112 | 1.00 | 37.89 | 1.0 | 25 | 1.25 | 0 | – | – | – | – | – | – | 0.0 | 0.0 |
| thin lines | scanned | 28.94 | 46.83 | 12.147 | 43.11 | 20.79 | 1.0 | 2763 | 138.15 | 2 | – | – | – | – | – | – | 0.0 | 0.1 |
## 5. Cost
@@ -224,87 +282,88 @@ One trace at a time on this machine (all cores); memory is the peak allocated ab
| preset | image | megapixels | result |
|:--|:--|--:|:--|
| Default | photo-like | 1 | 0.05 s, 29 paths, 3831 anchors, 15 MB |
| Default | four-colour badge | 1 | 0.03 s, 3 paths, 70 anchors, 15 MB |
| High Fidelity Photo | photo-like | 1 | 0.48 s, 51389 paths, 745118 anchors, 195 MB |
| High Fidelity Photo | four-colour badge | 1 | 0.05 s, 147 paths, 657 anchors, 81 MB |
| Low Fidelity Photo | photo-like | 1 | 0.08 s, 612 paths, 47559 anchors, 135 MB |
| Low Fidelity Photo | four-colour badge | 1 | 0.06 s, 85 paths, 354 anchors, 93 MB |
| 3 Colors | photo-like | 1 | 0.05 s, 9 paths, 2481 anchors, 22 MB |
| 3 Colors | four-colour badge | 1 | 0.04 s, 6 paths, 87 anchors, 21 MB |
| 6 Colors | photo-like | 1 | 0.05 s, 53 paths, 7197 anchors, 38 MB |
| 6 Colors | four-colour badge | 1 | 0.04 s, 7 paths, 112 anchors, 39 MB |
| 16 Colors | photo-like | 1 | 0.07 s, 398 paths, 28412 anchors, 99 MB |
| 16 Colors | four-colour badge | 1 | 0.04 s, 16 paths, 170 anchors, 90 MB |
| Shades of Gray | photo-like | 1 | 0.06 s, 449 paths, 18285 anchors, 55 MB |
| Shades of Gray | four-colour badge | 1 | 0.04 s, 36 paths, 168 anchors, 50 MB |
| Black and White Logo | photo-like | 1 | 0.03 s, 71 paths, 3032 anchors, 9 MB |
| Black and White Logo | four-colour badge | 1 | 0.02 s, 1 paths, 83 anchors, 8 MB |
| Sketched Art | photo-like | 1 | 0.03 s, 5 paths, 1411 anchors, 9 MB |
| Sketched Art | four-colour badge | 1 | 0.02 s, 2 paths, 40 anchors, 8 MB |
| Silhouettes | photo-like | 1 | 0.03 s, 2 paths, 391 anchors, 11 MB |
| Silhouettes | four-colour badge | 1 | 0.02 s, 1 paths, 23 anchors, 9 MB |
| Line Art | photo-like | 1 | 0.03 s, 54 paths, 2545 anchors, 9 MB |
| Line Art | four-colour badge | 1 | 0.02 s, 1 paths, 56 anchors, 8 MB |
| Technical Drawing | photo-like | 1 | 0.03 s, 221 paths, 4083 anchors, 9 MB |
| Technical Drawing | four-colour badge | 1 | 0.02 s, 1 paths, 83 anchors, 8 MB |
| Default | photo-like | 1 | 0.08 s, 29 paths, 7947 anchors, 15 MB |
| Default | four-colour badge | 1 | 0.03 s, 3 paths, 106 anchors, 15 MB |
| High Fidelity Photo | photo-like | 1 | 2.05 s, 51279 paths, 1476202 anchors, 209 MB |
| High Fidelity Photo | four-colour badge | 1 | 0.06 s, 147 paths, 1700 anchors, 111 MB |
| Low Fidelity Photo | photo-like | 1 | 0.19 s, 612 paths, 91647 anchors, 133 MB |
| Low Fidelity Photo | four-colour badge | 1 | 0.05 s, 85 paths, 548 anchors, 86 MB |
| 3 Colors | photo-like | 1 | 0.05 s, 9 paths, 5249 anchors, 22 MB |
| 3 Colors | four-colour badge | 1 | 0.04 s, 6 paths, 128 anchors, 21 MB |
| 6 Colors | photo-like | 1 | 0.05 s, 53 paths, 13454 anchors, 38 MB |
| 6 Colors | four-colour badge | 1 | 0.04 s, 7 paths, 153 anchors, 39 MB |
| 16 Colors | photo-like | 1 | 0.13 s, 398 paths, 49771 anchors, 89 MB |
| 16 Colors | four-colour badge | 1 | 0.05 s, 16 paths, 527 anchors, 89 MB |
| Shades of Gray | photo-like | 1 | 0.10 s, 447 paths, 31068 anchors, 52 MB |
| Shades of Gray | four-colour badge | 1 | 0.04 s, 36 paths, 400 anchors, 52 MB |
| Black and White Logo | photo-like | 1 | 0.06 s, 71 paths, 9067 anchors, 9 MB |
| Black and White Logo | four-colour badge | 1 | 0.02 s, 1 paths, 58 anchors, 8 MB |
| Sketched Art | photo-like | 1 | 0.06 s, 5 paths, 3207 anchors, 9 MB |
| Sketched Art | four-colour badge | 1 | 0.03 s, 2 paths, 145 anchors, 8 MB |
| Silhouettes | photo-like | 1 | 0.05 s, 2 paths, 851 anchors, 11 MB |
| Silhouettes | four-colour badge | 1 | 0.03 s, 1 paths, 29 anchors, 9 MB |
| Line Art | photo-like | 1 | 0.07 s, 54 paths, 4751 anchors, 9 MB |
| Line Art | four-colour badge | 1 | 0.03 s, 1 paths, 243 anchors, 8 MB |
| Technical Drawing | photo-like | 1 | 0.07 s, 221 paths, 10646 anchors, 9 MB |
| Technical Drawing | four-colour badge | 1 | 0.02 s, 1 paths, 58 anchors, 8 MB |
| Flat Logo | photo-like | 1 | refused after 0.10 s (not flat art), 40 MB |
| Flat Logo | four-colour badge | 1 | 0.66 s, 5 paths, 78 anchors, 146 MB |
| Default | photo-like | 4 | 0.17 s, 48 paths, 10545 anchors, 60 MB |
| Default | four-colour badge | 4 | 0.08 s, 3 paths, 77 anchors, 64 MB |
| High Fidelity Photo | photo-like | 4 | refused after 1.24 s (over 2,000,000 anchors), 859 MB |
| High Fidelity Photo | four-colour badge | 4 | 0.21 s, 225 paths, 991 anchors, 529 MB |
| Low Fidelity Photo | photo-like | 4 | 0.25 s, 1499 paths, 100595 anchors, 485 MB |
| Low Fidelity Photo | four-colour badge | 4 | 0.21 s, 88 paths, 408 anchors, 361 MB |
| 3 Colors | photo-like | 4 | 0.18 s, 22 paths, 7209 anchors, 88 MB |
| 3 Colors | four-colour badge | 4 | 0.12 s, 5 paths, 101 anchors, 84 MB |
| 6 Colors | photo-like | 4 | 0.15 s, 100 paths, 18024 anchors, 152 MB |
| 6 Colors | four-colour badge | 4 | 0.12 s, 7 paths, 127 anchors, 152 MB |
| 16 Colors | photo-like | 4 | 0.18 s, 1236 paths, 75609 anchors, 390 MB |
| 16 Colors | four-colour badge | 4 | 0.15 s, 17 paths, 220 anchors, 315 MB |
| Shades of Gray | photo-like | 4 | 0.19 s, 1289 paths, 48985 anchors, 208 MB |
| Shades of Gray | four-colour badge | 4 | 0.18 s, 41 paths, 211 anchors, 200 MB |
| Black and White Logo | photo-like | 4 | 0.18 s, 208 paths, 9008 anchors, 36 MB |
| Black and White Logo | four-colour badge | 4 | 0.09 s, 1 paths, 142 anchors, 36 MB |
| Sketched Art | photo-like | 4 | 0.17 s, 9 paths, 3366 anchors, 36 MB |
| Sketched Art | four-colour badge | 4 | 0.08 s, 2 paths, 45 anchors, 36 MB |
| Silhouettes | photo-like | 4 | 0.20 s, 2 paths, 1041 anchors, 44 MB |
| Silhouettes | four-colour badge | 4 | 0.08 s, 1 paths, 28 anchors, 36 MB |
| Line Art | photo-like | 4 | 0.16 s, 127 paths, 7334 anchors, 36 MB |
| Line Art | four-colour badge | 4 | 0.08 s, 1 paths, 73 anchors, 36 MB |
| Technical Drawing | photo-like | 4 | 0.15 s, 931 paths, 14515 anchors, 36 MB |
| Technical Drawing | four-colour badge | 4 | 0.08 s, 1 paths, 142 anchors, 36 MB |
| Flat Logo | photo-like | 4 | refused after 0.10 s (not flat art), 40 MB |
| Flat Logo | four-colour badge | 4 | 0.66 s, 5 paths, 69 anchors, 146 MB |
| Default | photo-like | 16 | 1.00 s, 127 paths, 26017 anchors, 256 MB |
| Default | four-colour badge | 16 | 0.44 s, 3 paths, 88 anchors, 240 MB |
| High Fidelity Photo | photo-like | 16 | refused after 3.22 s (over 2,000,000 anchors), 3326 MB |
| High Fidelity Photo | four-colour badge | 16 | 1.10 s, 438 paths, 1733 anchors, 2392 MB |
| Low Fidelity Photo | photo-like | 16 | 1.18 s, 8558 paths, 345957 anchors, 1873 MB |
| Low Fidelity Photo | four-colour badge | 16 | 1.07 s, 105 paths, 449 anchors, 1540 MB |
| 3 Colors | photo-like | 16 | 1.05 s, 87 paths, 18248 anchors, 352 MB |
| 3 Colors | four-colour badge | 16 | 0.65 s, 6 paths, 110 anchors, 336 MB |
| 6 Colors | photo-like | 16 | 0.90 s, 476 paths, 47937 anchors, 600 MB |
| 6 Colors | four-colour badge | 16 | 0.63 s, 11 paths, 160 anchors, 588 MB |
| 16 Colors | photo-like | 16 | 0.86 s, 7432 paths, 236585 anchors, 1574 MB |
| 16 Colors | four-colour badge | 16 | 0.83 s, 23 paths, 231 anchors, 1348 MB |
| Shades of Gray | photo-like | 16 | 0.93 s, 6007 paths, 147606 anchors, 805 MB |
| Shades of Gray | four-colour badge | 16 | 0.97 s, 41 paths, 224 anchors, 676 MB |
| Black and White Logo | photo-like | 16 | 0.99 s, 1128 paths, 30289 anchors, 144 MB |
| Black and White Logo | four-colour badge | 16 | 0.43 s, 1 paths, 193 anchors, 128 MB |
| Sketched Art | photo-like | 16 | 1.02 s, 15 paths, 8027 anchors, 144 MB |
| Sketched Art | four-colour badge | 16 | 0.42 s, 2 paths, 52 anchors, 128 MB |
| Silhouettes | photo-like | 16 | 1.29 s, 3 paths, 2442 anchors, 176 MB |
| Silhouettes | four-colour badge | 16 | 0.50 s, 1 paths, 29 anchors, 144 MB |
| Line Art | photo-like | 16 | 0.99 s, 713 paths, 23577 anchors, 144 MB |
| Line Art | four-colour badge | 16 | 0.41 s, 1 paths, 81 anchors, 128 MB |
| Technical Drawing | photo-like | 16 | 1.02 s, 4578 paths, 55463 anchors, 144 MB |
| Technical Drawing | four-colour badge | 16 | 0.43 s, 1 paths, 193 anchors, 128 MB |
| Flat Logo | photo-like | 16 | refused after 0.12 s (not flat art), 40 MB |
| Flat Logo | four-colour badge | 16 | 0.68 s, 5 paths, 67 anchors, 146 MB |
| Flat Logo | four-colour badge | 1 | 0.76 s, 5 paths, 78 anchors, 146 MB |
| Default | photo-like | 4 | 0.22 s, 48 paths, 20717 anchors, 60 MB |
| Default | four-colour badge | 4 | 0.12 s, 3 paths, 148 anchors, 64 MB |
| High Fidelity Photo | photo-like | 4 | refused after 3.98 s (over 2,000,000 anchors), 818 MB |
| High Fidelity Photo | four-colour badge | 4 | 0.22 s, 225 paths, 2758 anchors, 530 MB |
| Low Fidelity Photo | photo-like | 4 | 0.52 s, 1499 paths, 196617 anchors, 493 MB |
| Low Fidelity Photo | four-colour badge | 4 | 0.19 s, 88 paths, 780 anchors, 352 MB |
| 3 Colors | photo-like | 4 | 0.20 s, 22 paths, 13682 anchors, 88 MB |
| 3 Colors | four-colour badge | 4 | 0.14 s, 5 paths, 153 anchors, 84 MB |
| 6 Colors | photo-like | 4 | 0.21 s, 100 paths, 32737 anchors, 152 MB |
| 6 Colors | four-colour badge | 4 | 0.15 s, 7 paths, 191 anchors, 152 MB |
| 16 Colors | photo-like | 4 | 0.40 s, 1236 paths, 130559 anchors, 393 MB |
| 16 Colors | four-colour badge | 4 | 0.22 s, 17 paths, 917 anchors, 324 MB |
| Shades of Gray | photo-like | 4 | 0.37 s, 1289 paths, 83191 anchors, 199 MB |
| Shades of Gray | four-colour badge | 4 | 0.19 s, 41 paths, 450 anchors, 197 MB |
| Black and White Logo | photo-like | 4 | 0.26 s, 208 paths, 25916 anchors, 36 MB |
| Black and White Logo | four-colour badge | 4 | 0.10 s, 1 paths, 64 anchors, 36 MB |
| Sketched Art | photo-like | 4 | 0.26 s, 9 paths, 6875 anchors, 36 MB |
| Sketched Art | four-colour badge | 4 | 0.10 s, 2 paths, 279 anchors, 36 MB |
| Silhouettes | photo-like | 4 | 0.20 s, 2 paths, 2133 anchors, 44 MB |
| Silhouettes | four-colour badge | 4 | 0.10 s, 1 paths, 32 anchors, 36 MB |
| Line Art | photo-like | 4 | 0.23 s, 127 paths, 12595 anchors, 36 MB |
| Line Art | four-colour badge | 4 | 0.09 s, 1 paths, 465 anchors, 36 MB |
| Technical Drawing | photo-like | 4 | 0.23 s, 931 paths, 33946 anchors, 36 MB |
| Technical Drawing | four-colour badge | 4 | 0.10 s, 1 paths, 64 anchors, 36 MB |
| Flat Logo | photo-like | 4 | refused after 0.12 s (not flat art), 40 MB |
| Flat Logo | four-colour badge | 4 | 0.73 s, 5 paths, 69 anchors, 146 MB |
| Default | photo-like | 16 | 1.19 s, 127 paths, 46199 anchors, 256 MB |
| Default | four-colour badge | 16 | 0.50 s, 3 paths, 284 anchors, 240 MB |
| High Fidelity Photo | photo-like | 16 | refused after 8.58 s (over 2,000,000 anchors), 3320 MB |
| High Fidelity Photo | four-colour badge | 16 | 1.11 s, 438 paths, 4419 anchors, 2404 MB |
| Low Fidelity Photo | photo-like | 16 | 2.12 s, 8558 paths, 699119 anchors, 1910 MB |
| Low Fidelity Photo | four-colour badge | 16 | 1.18 s, 105 paths, 1089 anchors, 1556 MB |
| 3 Colors | photo-like | 16 | 1.08 s, 87 paths, 32157 anchors, 352 MB |
| 3 Colors | four-colour badge | 16 | 0.70 s, 6 paths, 227 anchors, 336 MB |
| 6 Colors | photo-like | 16 | 0.98 s, 476 paths, 86962 anchors, 608 MB |
| 6 Colors | four-colour badge | 16 | 0.68 s, 11 paths, 290 anchors, 600 MB |
| 16 Colors | photo-like | 16 | 1.55 s, 7432 paths, 407078 anchors, 1574 MB |
| 16 Colors | four-colour badge | 16 | 0.86 s, 23 paths, 1707 anchors, 1348 MB |
| Shades of Gray | photo-like | 16 | 1.24 s, 5996 paths, 256732 anchors, 789 MB |
| Shades of Gray | four-colour badge | 16 | 1.03 s, 41 paths, 681 anchors, 684 MB |
| Black and White Logo | photo-like | 16 | 1.20 s, 1128 paths, 77629 anchors, 144 MB |
| Black and White Logo | four-colour badge | 16 | 0.46 s, 1 paths, 103 anchors, 128 MB |
| Sketched Art | photo-like | 16 | 1.13 s, 15 paths, 17817 anchors, 144 MB |
| Sketched Art | four-colour badge | 16 | 0.47 s, 2 paths, 478 anchors, 128 MB |
| Silhouettes | photo-like | 16 | 1.36 s, 3 paths, 4891 anchors, 176 MB |
| Silhouettes | four-colour badge | 16 | 0.53 s, 1 paths, 44 anchors, 144 MB |
| Line Art | photo-like | 16 | 1.20 s, 713 paths, 64481 anchors, 144 MB |
| Line Art | four-colour badge | 16 | 0.49 s, 1 paths, 786 anchors, 128 MB |
| Technical Drawing | photo-like | 16 | 1.45 s, 4578 paths, 114292 anchors, 144 MB |
| Technical Drawing | four-colour badge | 16 | 0.48 s, 1 paths, 103 anchors, 128 MB |
| Flat Logo | photo-like | 16 | refused after 0.13 s (not flat art), 40 MB |
| Flat Logo | four-colour badge | 16 | 1.09 s, 5 paths, 67 anchors, 146 MB |
## Revision history
| date | change |
|:--|:--|
| 2026-10-13 | Sub-pixel edges and the outline fitter in Black and White, Grayscale and Color; the harness gains an aliased variant and an "outside px" column, so the baseline was measured again with it (same tracer, main at `baf9693f`) |
| 2026-10-12 | The harness and the baseline: every preset measured before any change to the tracer |
+3 -1
View File
@@ -1,6 +1,6 @@
# Parity with Adobe Illustrator
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (3D and Materials: Extrude & Bevel, Inflate and Rotate added, 3D ~8% → ~25% (estimated), menu stubs 25 → 22; Affinity text frames too short for their first line show it, #1423; Transform dialogs preview, #1412, and the transform tools and commands act on direct-selected anchors, #1408; `.ai` compound path paint, #1410; strokes wider than their shape, #1396; corner drags hide the bounding box, #1229; scores and hours unchanged; PDF and `.ai` import keep overprint, #1388, scores unchanged; `.ai` editing-data follow-ups: gradient stops, type of objects with an appearance, short area-type frames (#1390, #1391, #1392); dialog keyboard focus on every open (#1382, #1395); art flush with an artboard (#1375); font rescan (#1376); symbol instance redraw cache (#1386); scores and hours unchanged; grid tool options, #1377 in part, scores unchanged; `.ai` placed (linked) files read from the editing data, #1264, scores unchanged; gradient shapes import as paths, #1304; white constant alpha masks, #1286 in part; Live Corners widget click selects its corner, #1239; scores and hours unchanged; custom ruler origin, #1212; Artboard click-to-fit verified for objects, groups, visible bounds, undo and cancellation (#1227); scores and hours unchanged; Pathfinder single-result source names and SVG IDs retained, #1293; Localization: Korean catalog added, 54% → 63%, full readiness unchanged at ~62%; desktop print transport adopts craft-print, Windows 7 fallback retained, scores unchanged; Image Trace: an image over 64 megapixels traces scaled down instead of being refused, scores unchanged; Czech render-site localization follow-up; scores and estimates unchanged; Document Setup: Edit Artboards closes the modal after applying valid settings; pointer-click regressions; scores and hours unchanged; Artboards: Escape exits editing; an active drag cancels first; shortcut-routing regression; scores and hours unchanged; Path operations: Simplify preview/counts and component selection (#1272); scores unchanged; G2: Film Grain added; Photoshop effects 29/57; 28 filters remain; Platforms: RPM runtime capabilities and glibc floor (#1275); scores unchanged; Raster effects: squared-distance texture redraws (#1257); pixels unchanged; scores and hours unchanged; Drawing: Curvature point display improved (#1236, in part); scores unchanged; Type core: full-name font matching (#1258), scores and hours unchanged; Selection: no-op anchor Align preserves history and saved state (#1180 follow-up); scores unchanged; UI chrome: Eyedropper cursor and precise-setting regressions (#1269); scores unchanged; Colour: Eyedropper reads visible locked and outside-isolation sources (#1251); scores and hours unchanged; Selection: segment click/Delete preserves neighboring edges (#1278); scores unchanged; Colour: unpainted zero-width strokes regain 1 pt when painted (#1253); scores and hours unchanged; graphs: designs and markers, data, Graph Type and label options; UI chrome: native macOS save Format menu, #866, scores unchanged; compound paths inherit the backmost appearance and member fill-rule edits reach their owner, #1197; scores unchanged; Type core: Middle Eastern digit types done, Character panel menu › Digits; PDF export warns when the pixel cap lowers raster-effect resolution; Drawing tools: Live Corners round corners between curved sides, #1144; Type advanced: proportional vertical metrics (`vpal`) done, #966; Shape Builder: #893 fixed, merged regions of crossing lines no longer keep seams; scores unchanged while #937 is open; #1034: document-point character controls after object/group scaling; full readiness recomputed as the standard's additive weighted sum, ~62%; per-audience hours; essentials-user score ~75% added; ready-for-real-work re-examined: 50% → 55%, mainstream 65% added; earlier the same day: full re-measure against Illustrator 2026 30.x; merged the ROADMAP's parity estimate, honest assessment and "Shipped so far" into this file; SVG knockout groups of opaque art export without masks) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (Image Trace places edges to a fraction of a pixel in every mode, measured in `image-trace-quality.md`, score unchanged; 3D and Materials: Extrude & Bevel, Inflate and Rotate added, 3D ~8% → ~25% (estimated), menu stubs 25 → 22; Affinity text frames too short for their first line show it, #1423; Transform dialogs preview, #1412, and the transform tools and commands act on direct-selected anchors, #1408; `.ai` compound path paint, #1410; strokes wider than their shape, #1396; corner drags hide the bounding box, #1229; scores and hours unchanged; PDF and `.ai` import keep overprint, #1388, scores unchanged; `.ai` editing-data follow-ups: gradient stops, type of objects with an appearance, short area-type frames (#1390, #1391, #1392); dialog keyboard focus on every open (#1382, #1395); art flush with an artboard (#1375); font rescan (#1376); symbol instance redraw cache (#1386); scores and hours unchanged; grid tool options, #1377 in part, scores unchanged; `.ai` placed (linked) files read from the editing data, #1264, scores unchanged; gradient shapes import as paths, #1304; white constant alpha masks, #1286 in part; Live Corners widget click selects its corner, #1239; scores and hours unchanged; custom ruler origin, #1212; Artboard click-to-fit verified for objects, groups, visible bounds, undo and cancellation (#1227); scores and hours unchanged; Pathfinder single-result source names and SVG IDs retained, #1293; Localization: Korean catalog added, 54% → 63%, full readiness unchanged at ~62%; desktop print transport adopts craft-print, Windows 7 fallback retained, scores unchanged; Image Trace: an image over 64 megapixels traces scaled down instead of being refused, scores unchanged; Czech render-site localization follow-up; scores and estimates unchanged; Document Setup: Edit Artboards closes the modal after applying valid settings; pointer-click regressions; scores and hours unchanged; Artboards: Escape exits editing; an active drag cancels first; shortcut-routing regression; scores and hours unchanged; Path operations: Simplify preview/counts and component selection (#1272); scores unchanged; G2: Film Grain added; Photoshop effects 29/57; 28 filters remain; Platforms: RPM runtime capabilities and glibc floor (#1275); scores unchanged; Raster effects: squared-distance texture redraws (#1257); pixels unchanged; scores and hours unchanged; Drawing: Curvature point display improved (#1236, in part); scores unchanged; Type core: full-name font matching (#1258), scores and hours unchanged; Selection: no-op anchor Align preserves history and saved state (#1180 follow-up); scores unchanged; UI chrome: Eyedropper cursor and precise-setting regressions (#1269); scores unchanged; Colour: Eyedropper reads visible locked and outside-isolation sources (#1251); scores and hours unchanged; Selection: segment click/Delete preserves neighboring edges (#1278); scores unchanged; Colour: unpainted zero-width strokes regain 1 pt when painted (#1253); scores and hours unchanged; graphs: designs and markers, data, Graph Type and label options; UI chrome: native macOS save Format menu, #866, scores unchanged; compound paths inherit the backmost appearance and member fill-rule edits reach their owner, #1197; scores unchanged; Type core: Middle Eastern digit types done, Character panel menu › Digits; PDF export warns when the pixel cap lowers raster-effect resolution; Drawing tools: Live Corners round corners between curved sides, #1144; Type advanced: proportional vertical metrics (`vpal`) done, #966; Shape Builder: #893 fixed, merged regions of crossing lines no longer keep seams; scores unchanged while #937 is open; #1034: document-point character controls after object/group scaling; full readiness recomputed as the standard's additive weighted sum, ~62%; per-audience hours; essentials-user score ~75% added; ready-for-real-work re-examined: 50% → 55%, mainstream 65% added; earlier the same day: full re-measure against Illustrator 2026 30.x; merged the ROADMAP's parity estimate, honest assessment and "Shipped so far" into this file; SVG knockout groups of opaque art export without masks) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
The authoritative parity assessment. [`ROADMAP.md`](../ROADMAP.md) summarizes it; [`gaps.md`](gaps.md) is
the work list made from it. Deep areas have their own checklists: [UI and interaction](ui-parity.md),
@@ -468,6 +468,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
- **Interface languages, vertical type:** Preferences ▸ User Interface (or VectorCraft ▸ Language on macOS) picks Automatic (the system locale) or a registered language, persisted as `interfaceLanguage`. Translations come from per-language catalogs (`i18n/*.tsv`): Traditional and Simplified Chinese, Japanese, German (every `de-*` locale), Spanish (neutral international Spanish, for every `es-*` locale), French (every `fr-*` locale), Italian (every `it-*` locale) Russian (every `ru-*` locale) and Ukrainian (every `uk-*` locale) cover the whole interface, Czech and Brazilian Portuguese every menu label, Brazilian Portuguese the shell's `tl!` literals too (tested); German, Spanish, French, Italian, Japanese, Russian and Ukrainian also translate status-bar and error messages as they are shown (`@msg` templates, every message literal tested; the messages themselves stay English for agents); untranslated text stays English. Japanese and Chinese glyphs come from the craft-fonts build input (release builds) or the installed fonts, Czech, German, Spanish, French, Italian, Russian and Ukrainian ones from the bundled UI fonts. The web app follows the browser's languages (or `?lang=`). The Basic toolbar's Type button holds Vertical Type in its flyout. Vertical Type, Vertical Area Type and Vertical Type on a Path create vertical text (columns right to left, upright CJK glyphs and marks with `vert` alternates, Latin and longer numbers on their side, two- and three-digit numbers set as tate-chu-yoko in one em of the column (kept whole when justified), upright glyphs centred on the column (tracked or justified too), point type's anchor on the first column's centre line); kinsoku applies to horizontal and vertical Japanese (Paragraph panel › Kinsoku Set, `text.setFormat {kinsoku}`: Hard, the default, keeps closing marks, iteration marks, the prolonged sound mark and small kana off the line start and opening brackets off its end; Soft lets 々, ー and small kana start a line as JLREQ's level 3 rules do; None turns it off), and justified Japanese lines spread their room between characters (not inside Latin words); Paragraph panel › Mojikumi Set (shown with Preferences › Type › Show East Asian Options, `text.setFormat {mojikumi}`): None or Line-end Punctuation Half Width (new type's default, as in Illustrator; older documents and imported text keep None) shares one half-em space between consecutive punctuation, sets a closing mark ending a line half width and an opening bracket starting a line flush with its start (a paragraph's first line at its first-line indent, JIS X 4051's principle in JLREQ 3.1.5), and puts a quarter em between Japanese and Latin letters or digits; Paragraph panel menu › Top-to-Top / Bottom-to-Bottom Leading measures leading from em box top to top (area type's first line touches the frame) or from baseline to baseline (new type in a Japanese interface starts top to top, with em box centre character alignment, #432); Paragraph panel menu › Burasagari None / Regular / Force (`text.setFormat {burasagari: "none"|"standard"|"forced"}`) hangs an East Asian comma or full stop (、。,.、。) ending an area type line outside it, Regular (new type's default) when it doesn't fit and Force always (the rest of the line then fills the measure; closing brackets and Latin punctuation don't hang); Character panel menu › Character Alignment (with the East Asian options; `text.setFormat` or `text.setRangeStyle {charAlign}`) lines characters smaller than the largest on their line up on the Roman baseline, the em box top/right, centre or bottom/left, or the ICF (ideographic character face) top/right or bottom/left, from the font's BASE table or, without one, the average ink box of some ideographs and kana; Proportional Metrics (the same menu; `{proportionalMetrics}`) sets full-width glyphs on the font's proportional widths (OpenType `palt`) in horizontal type and upright glyphs on its proportional heights (`vpal`, shaped top to bottom; fonts without vertical metrics keep their cells) in vertical type, and Line-end Punctuation Half Width takes nothing more off the punctuation they re-spaced; Type ▸ Type Orientation switches existing text; caret, selection, hit testing and arrow keys follow the writing direction. Vertical text exports to PDF as real text and to SVG as outlines.
- **Transparency:** opacity masks (clip/invert/disable/link), exported as SVG `<mask>` and PDF soft masks. The constant alpha soft mask that PDF and `.ai` export draw a CMYK page with transparency through is white, so applications that read every soft mask by its luminosity show the page too (#1359, part of #1286).
Disable, Enable, Unlink and Link Opacity Mask and Opacity Mask Options (`transparency.setOpacityMask`) record no undo step when every mask they act on already has the flags they set.
- **Image Trace, measured:** `crates/trace/tests/quality` traces drawings made from known vector art with every preset and [`image-trace-quality.md`](image-trace-quality.md) records the numbers against the baseline. Black and White, Grayscale and Color place each edge by the blend of the pixels across it (to a fraction of a pixel on anti-aliased and blurred images; hard-edged images are read as staircases) and fit outlines as Flat Logo does. *Measured* on each preset's own inputs, all sizes and variants: Default's outlines went from 0.31 px off on average to 0.09 (largest 1.51 to 1.02), Black and White Logo's from 0.27 to 0.06 with 0.3 kinks per trace where it had 15, and the gaps between abutting paths from 64 px to 22. On clean curved shapes Black and White Logo is 0.02 px off (the open tracer measured beside it: 0.20). Still weak, by the same numbers: 6 and 16 Colors shatter noisy flat art, High Fidelity Photo makes 51,000 paths of a 1 megapixel photo-like image, thin lines in blurred images take 7 times the art's anchors.
- **Image Trace Flat Logo mode:** a fourth mode beside Black and White, Grayscale and Color, for flat-colour logos. Each pixel is read as a blend of the logo's colours (found automatically or named), the blend is interpolated smoothly and every outline is placed where two colours are equally present, so edges are accurate to a fraction of a pixel. Outlines are then cleaned: corners the blur rounded are put back, near-straight runs and near-circular arcs become exact lines and arcs, the rest is fitted with as few Béziers as the tolerance allows, touching colours overlap by a hair so no gap opens, and an outline that strays from the raw contour is fitted plainly instead. Gradients and photos are refused with advice to use Color. *Measured* (a local experiment, not run in CI): a flat-colour logo's vector original was rendered down to a soft 199 × 100 px transparent PNG, traced, and the result compared with the original at 1600 px wide. The built-in colour presets (6 Colors, 16 Colors, High Fidelity Photo, Low Fidelity Photo) had a mean edge error of 2.5 to 3.4 px and region overlap of 0.88 to 0.91; Flat Logo had 0.78 px and 0.966 (0.48 px and 0.975 from a crisp source), in about 0.1 s. Limits: flat-colour art only; needle-thin sharp tips are shortened by about 1.7 source pixels because the blur erases them; it works at no more than 1024 px on the long side (larger images are averaged down first); only one logo family has been scored against a vector original.
- **Advanced art:** live Blends (steps/distance/smooth colour, editable spine, anchor-targeted Blend tool, faithful interpolation, knockout), Envelope Distort (warp/mesh/top object, Reset, full Envelope Options, mesh handles, Edit Contents; type, images, symbols, gradients, patterns and appearance distorted everywhere), Liquify tools with options and pen pressure, Puppet Warp with rotating pins, Perspective Grid with presets, movable planes and projected type (choosing a perspective tool shows the grid; Hide Grid hides it with the tool still chosen), Gradient Mesh, Shape Builder (stroke-only open paths and lines cut the regions they cross and enclose regions of their own, and regions they bound merge without seams where the lines cross at rounded coordinates (#893); filled open paths count as closed; erase mode while Alt/Option is held: a minus pointer, red highlights of what will go, a click or drag deletes the regions touched, the pieces of open lines and the edges (outline pieces between the points where paths meet, opening their paths there) it passes over, one undo step, `shapeBuilder.merge {erase}` and `shapeBuilder.regions` edges over MCP), Live Paint (every path an edge, open lines included), Image Trace (12 presets, colour layers traced in parallel; a trace past two million anchor points is refused with advice rather than running out of memory, an image over 64 megapixels is traced scaled down to that size (aspect kept, paths at the image's own size) and one over 192 megapixels is refused, and a selection too large to outline shows its bounds (#525); Object › Image Trace › Make and Make and Expand trace at once with the Default preset, #543; with an image selected the Control bar and the Properties panel show Image Trace, whose arrow traces with any preset, Mask (`object.maskImage`: a clipping path on the image's outline, selected so its handles crop), Crop Image (a crop box on the image, starting on its part over the artboard, dragged by its handles or inside it, the outside dimmed, with X/Y/W/H, Apply and Cancel in the Control bar, Enter and Escape, #734; `object.cropImage {rect}` for agents, `{trim: true}` cuts an image to its pixels that aren't fully transparent, pixel for pixel) and Embed or Unembed in place of Fill and Stroke; with an Image Trace object selected, its Preset (choosing another traces again), View, the Image Trace panel and Expand, plus Release in Properties; the five View modes (Tracing Result, with Outlines, Outlines, Outlines with Source Image, Source Image) redraw a trace on screen without tracing again, are saved with it and `imageTrace.setView` sets them, while exports and Expand keep the result; the panel's Advanced section is a header that stays open or closed as it was left (part of #641); Color mode's Palette: Limited, Full Tone (as many colours as the tones need, Less … More), Automatic (flat art with its own colours, else Full Tone; a heuristic) and Document Library (the most used colours of the document's swatches or a swatch library, filled with the swatch colours as they are), part of #641; Advanced › Create: Fills and/or Strokes, where lines up to the Stroke width trace as stroked centre lines (distance transform, thinning, a skeleton graph with spurs pruned, curve fitting; one width per line; without Fills, wider areas become stroked outlines), part of #641), pattern swatches with pattern editing mode, live Repeat (radial/grid/mirror).
- **Paint and appearance (M3):**
@@ -523,6 +524,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
| Date | Change | Summary |
|---|---|---|
| 2026-10-13 | minor | Image Trace: Black and White, Grayscale and Color place edges by the blend of the pixels across them and fit outlines as Flat Logo does; a harness measures every preset (`image-trace-quality.md`): Default's outlines 0.31 → 0.09 px off on average, Black and White Logo's 0.27 → 0.06 with 15 → 0.3 kinks, gaps between abutting paths 64 → 22 px. Score and hours unchanged (estimated) |
| 2026-10-12 | minor | 3D and Materials: Extrude & Bevel, Inflate and Rotate with Position presets ([three-d.md](three-d.md)); 3D ~8% → ~25%, 50–85 → 30–55 h (estimated); menu 353/375 wired (measured from the stubs removed) |
| 2026-10-12 | minor | File formats: an Affinity text frame too short for its first line is made taller with a warning instead of showing nothing (#1423); synthetic-file test; score and hours unchanged (estimated) |
| 2026-10-12 | minor | File formats: a `.ai` compound path takes its last path's paint and keeps paths grouped inside it (#1426, fixes #1410; hand-written editing data test, no public documentation of which member carries the paint); a `.ai` whose PDF part draws only text opens from it when its editing data can't be read (#1414, fixes #1387); score and hours unchanged (estimated) |