Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9fac95760 | ||
|
|
c391e1dbf2 |
No files matched your search
@@ -51,7 +51,8 @@ fn step(d: u8) -> (i32, i32) {
|
||||
fn label(mask: &[bool], w: usize, h: usize) -> (Vec<u32>, Vec<usize>) {
|
||||
let mut comp = vec![u32::MAX; w * h];
|
||||
let mut sizes = Vec::new();
|
||||
let mut stack = Vec::new();
|
||||
// (Indices as `u32`: a mask has at most 64 million pixels, and this stack can hold them all.)
|
||||
let mut stack: Vec<u32> = Vec::new();
|
||||
for s in 0..w * h {
|
||||
if !mask[s] || comp[s] != u32::MAX {
|
||||
continue;
|
||||
@@ -59,14 +60,15 @@ fn label(mask: &[bool], w: usize, h: usize) -> (Vec<u32>, Vec<usize>) {
|
||||
let id = sizes.len() as u32;
|
||||
let mut n = 0usize;
|
||||
comp[s] = id;
|
||||
stack.push(s);
|
||||
stack.push(s as u32);
|
||||
while let Some(i) = stack.pop() {
|
||||
let i = i as usize;
|
||||
n += 1;
|
||||
let (x, y) = (i % w, i / w);
|
||||
let mut go = |j: usize| {
|
||||
if mask[j] && comp[j] == u32::MAX {
|
||||
comp[j] = id;
|
||||
stack.push(j);
|
||||
stack.push(j as u32);
|
||||
}
|
||||
};
|
||||
if x > 0 {
|
||||
|
||||
+50
-19
@@ -469,11 +469,14 @@ pub fn trace_within(img: &Raster, params: &TraceParams, max_anchors: usize) -> R
|
||||
let img = smoothed.as_ref().unwrap_or(img);
|
||||
let mut q = quantize(img, params);
|
||||
denoise(&mut q.labels, w, h, params.noise as usize);
|
||||
// Pixel count per palette entry.
|
||||
// Pixel count per palette entry, and the box its pixels lie in.
|
||||
let mut counts = vec![0usize; q.palette.len()];
|
||||
for &l in &q.labels {
|
||||
if let Some(c) = counts.get_mut(l as usize) {
|
||||
let mut boxes: Vec<Option<(usize, usize, usize, usize)>> = vec![None; q.palette.len()];
|
||||
for (i, &l) in q.labels.iter().enumerate() {
|
||||
if let (Some(c), Some(b)) = (counts.get_mut(l as usize), boxes.get_mut(l as usize)) {
|
||||
*c += 1;
|
||||
let (x, y) = (i % w, i / w);
|
||||
*b = Some(b.map_or((x, y, x + 1, y + 1), |b| (b.0.min(x), b.1.min(y), b.2.max(x + 1), b.3.max(y + 1))));
|
||||
}
|
||||
}
|
||||
// Layers bottom → top: largest area first.
|
||||
@@ -503,6 +506,7 @@ pub fn trace_within(img: &Raster, params: &TraceParams, max_anchors: usize) -> R
|
||||
rank: &rank,
|
||||
params,
|
||||
img,
|
||||
boxes,
|
||||
bw_tones: bw_tones(img, &q),
|
||||
style: params.outline_style(),
|
||||
opts: fit::FitOptions {
|
||||
@@ -517,7 +521,12 @@ pub fn trace_within(img: &Raster, params: &TraceParams, max_anchors: usize) -> R
|
||||
max_anchors,
|
||||
};
|
||||
let mut out = TraceResult::default();
|
||||
for (paths, &(_, ci)) in parallel_map(&layers, |&(r, ci)| job.layer(r, ci)).into_iter().zip(&layers) {
|
||||
// A layer takes about ten bytes a pixel of its box while it is traced (its mask, the labels
|
||||
// of its components, the stack that fills them, its edges): as many layers at a time as fit
|
||||
// in half a gigabyte, so that a large image is not traced at the cost of gigabytes.
|
||||
let largest = job.boxes.iter().flatten().map(|b| (b.2 - b.0) * (b.3 - b.1)).max().unwrap_or(1).max(1);
|
||||
let at_a_time = ((512 << 20) / (largest * 10)).max(1);
|
||||
for (paths, &(_, ci)) in parallel_map_at_most(at_a_time, &layers, |&(r, ci)| job.layer(r, ci)).into_iter().zip(&layers) {
|
||||
out.paths.extend(paths.ok_or(TraceError::TooComplex { max: max_anchors })?);
|
||||
let color = q.palette[ci];
|
||||
if !out.palette.contains(&color) {
|
||||
@@ -547,6 +556,8 @@ struct Layers<'a> {
|
||||
rank: &'a [usize],
|
||||
params: &'a TraceParams,
|
||||
img: &'a Raster,
|
||||
/// The box each palette entry's pixels lie in: `(x0, y0, x1, y1)`, the far sides excluded.
|
||||
boxes: Vec<Option<(usize, usize, usize, usize)>>,
|
||||
/// Black and White: the mean luminance of the white pixels and of the black ones.
|
||||
bw_tones: [f64; 2],
|
||||
/// How outlines are fitted.
|
||||
@@ -709,17 +720,23 @@ impl Layers<'_> {
|
||||
} else {
|
||||
(vec![], vec![])
|
||||
};
|
||||
let mask: Vec<bool> = self
|
||||
.q
|
||||
.labels
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, &l)| {
|
||||
l != TRANSPARENT
|
||||
&& !thin.get(i).copied().unwrap_or(false)
|
||||
&& if overlapping { self.rank.get(l as usize).is_some_and(|&lr| lr >= r) && !self.ignored(l) } else { l as usize == ci }
|
||||
})
|
||||
.collect();
|
||||
// The layer is traced within the box its pixels lie in, not the whole image.
|
||||
let part = |l: u16| if overlapping { self.rank.get(l as usize).is_some_and(|&lr| lr >= r) && !self.ignored(l) } else { l as usize == ci };
|
||||
let (mut x0, mut y0, mut x1, mut y1) = (w, h, 0, 0);
|
||||
for (l, b) in self.boxes.iter().enumerate() {
|
||||
if let Some(b) = b.filter(|_| part(l as u16)) {
|
||||
(x0, y0, x1, y1) = (x0.min(b.0), y0.min(b.1), x1.max(b.2), y1.max(b.3));
|
||||
}
|
||||
}
|
||||
if x0 >= x1 || y0 >= y1 {
|
||||
return Some(vec![]);
|
||||
}
|
||||
let (bw, bh) = (x1 - x0, y1 - y0);
|
||||
let mut mask = Vec::with_capacity(bw * bh);
|
||||
for y in y0..y1 {
|
||||
let row = self.q.labels.get(y * w + x0..y * w + x1)?;
|
||||
mask.extend(row.iter().enumerate().map(|(k, &l)| l != TRANSPARENT && !thin.get(y * w + x0 + k).copied().unwrap_or(false) && part(l)));
|
||||
}
|
||||
// Without Fills, areas are outlined with a 1 px stroke.
|
||||
let area_stroke = (params.strokes && !params.fills).then_some(1.0);
|
||||
let min_hole = params.noise.max(1) as i64;
|
||||
@@ -732,7 +749,16 @@ impl Layers<'_> {
|
||||
paths.push(TracedPath { path, color, pixels, stroke });
|
||||
true
|
||||
};
|
||||
for comp in trace_mask(&mask, w, h) {
|
||||
let mut comps = trace_mask(&mask, bw, bh);
|
||||
drop(mask);
|
||||
for comp in &mut comps {
|
||||
for l in std::iter::once(&mut comp.outer).chain(&mut comp.holes) {
|
||||
for p in &mut l.pts {
|
||||
*p = (p.0 + x0 as i32, p.1 + y0 as i32);
|
||||
}
|
||||
}
|
||||
}
|
||||
for comp in comps {
|
||||
let fit = |l: &Loop| fit::fit_loop(l, w, h, &|c| (self.shift(c), self.neighbour(c)), &|x, y| self.junction(x, y), &self.style);
|
||||
let Some(outer) = fit(&comp.outer) else { continue };
|
||||
let mut subs = vec![outer];
|
||||
@@ -756,9 +782,14 @@ impl Layers<'_> {
|
||||
}
|
||||
|
||||
/// `f` of each of `items`, in order, spread over the available cores.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn parallel_map<T: Sync, R: Send>(items: &[T], f: impl Fn(&T) -> R + Sync) -> Vec<R> {
|
||||
let threads = std::thread::available_parallelism().map_or(1, |n| n.get()).min(items.len());
|
||||
parallel_map_at_most(usize::MAX, items, f)
|
||||
}
|
||||
|
||||
/// `f` of each of `items`, in order, spread over the available cores, at most `at_a_time` at once.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn parallel_map_at_most<T: Sync, R: Send>(at_a_time: usize, items: &[T], f: impl Fn(&T) -> R + Sync) -> Vec<R> {
|
||||
let threads = std::thread::available_parallelism().map_or(1, |n| n.get()).min(items.len()).min(at_a_time);
|
||||
if threads <= 1 {
|
||||
return items.iter().map(f).collect();
|
||||
}
|
||||
@@ -787,7 +818,7 @@ fn parallel_map<T: Sync, R: Send>(items: &[T], f: impl Fn(&T) -> R + Sync) -> Ve
|
||||
|
||||
/// `f` of each of `items`, in order (no threads on the web).
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn parallel_map<T: Sync, R: Send>(items: &[T], f: impl Fn(&T) -> R + Sync) -> Vec<R> {
|
||||
fn parallel_map_at_most<T: Sync, R: Send>(_: usize, items: &[T], f: impl Fn(&T) -> R + Sync) -> Vec<R> {
|
||||
items.iter().map(f).collect()
|
||||
}
|
||||
|
||||
|
||||
@@ -1037,3 +1037,15 @@ fn abutting_regions_share_one_curve_along_their_edge() {
|
||||
}
|
||||
assert!(shared >= 12, "{shared} shared curves");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn layers_traced_a_few_at_a_time_come_out_the_same() {
|
||||
let items: Vec<usize> = (0..40).collect();
|
||||
for at_a_time in [1, 3, usize::MAX] {
|
||||
assert_eq!(parallel_map_at_most(at_a_time, &items, |i| i * i), items.iter().map(|i| i * i).collect::<Vec<_>>());
|
||||
}
|
||||
// A layer is traced within the box of its pixels: a shape far from the image's origin stays there.
|
||||
let img = Raster::from_fn(90, 70, |x, y| if (60..80).contains(&x) && (40..60).contains(&y) { BLACK } else { WHITE });
|
||||
let b = trace(&img, &bw()).paths[0].path.bounds().unwrap();
|
||||
assert!([(b.x0, 60.0), (b.y0, 40.0), (b.x1, 80.0), (b.y1, 60.0)].iter().all(|(got, want)| (got - want).abs() < 0.01), "{b:?}");
|
||||
}
|
||||
+78
-77
@@ -1,6 +1,6 @@
|
||||
# Image Trace quality
|
||||
|
||||
> **Last reviewed:** 2026-10-13 · **Last updated:** 2026-10-13 · **Change:** minor (shared edges: gaps and overlaps between abutting paths from 22 to 50 px down to under 1)
|
||||
> **Last reviewed:** 2026-10-13 · **Last updated:** 2026-10-13 · **Change:** minor (memory: a 16 megapixel photo traced in 0.9 GB where it took 3.9)
|
||||
|
||||
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
|
||||
@@ -72,7 +72,7 @@ Each preset on the inputs it is meant for, all sizes and variants.
|
||||
| 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, the palette, photo smoothing, shared edges)
|
||||
### Now (sub-pixel edges, the palette, photo smoothing, shared edges, memory)
|
||||
|
||||
| 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 |
|
||||
|:--|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
|
||||
@@ -90,7 +90,7 @@ Each preset on the inputs it is meant for, all sizes and variants.
|
||||
| Technical Drawing | polygons, star, letter A, lines | 2.55 | 9.72 | 0.092 | 1.06 | 105.75 | 4.8 | 56 | 3.67 | 71 | 74 | 0.7 | – | – | – | – | 1.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, the palette, photo smoothing, shared edges).
|
||||
The sections below are the numbers now (sub-pixel edges, the palette, photo smoothing, shared edges, memory).
|
||||
|
||||
## 1. Each preset on the inputs it is meant for
|
||||
|
||||
@@ -282,89 +282,90 @@ 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.04 s, 29 paths, 6888 anchors, 15 MB |
|
||||
| Default | four-colour badge | 1 | 0.02 s, 3 paths, 96 anchors, 15 MB |
|
||||
| High Fidelity Photo | photo-like | 1 | 0.21 s, 968 paths, 114383 anchors, 238 MB |
|
||||
| High Fidelity Photo | four-colour badge | 1 | 0.06 s, 6 paths, 172 anchors, 36 MB |
|
||||
| Low Fidelity Photo | photo-like | 1 | 0.11 s, 129 paths, 22929 anchors, 144 MB |
|
||||
| Low Fidelity Photo | four-colour badge | 1 | 0.05 s, 6 paths, 136 anchors, 36 MB |
|
||||
| 3 Colors | photo-like | 1 | 0.08 s, 9 paths, 3367 anchors, 26 MB |
|
||||
| 3 Colors | four-colour badge | 1 | 0.05 s, 4 paths, 88 anchors, 21 MB |
|
||||
| 6 Colors | photo-like | 1 | 0.08 s, 78 paths, 9008 anchors, 42 MB |
|
||||
| 6 Colors | four-colour badge | 1 | 0.05 s, 5 paths, 84 anchors, 33 MB |
|
||||
| 16 Colors | photo-like | 1 | 0.10 s, 178 paths, 20466 anchors, 102 MB |
|
||||
| 16 Colors | four-colour badge | 1 | 0.05 s, 5 paths, 88 anchors, 33 MB |
|
||||
| Shades of Gray | photo-like | 1 | 0.08 s, 81 paths, 6698 anchors, 65 MB |
|
||||
| Shades of Gray | four-colour badge | 1 | 0.06 s, 10 paths, 733 anchors, 56 MB |
|
||||
| Black and White Logo | photo-like | 1 | 0.04 s, 71 paths, 5465 anchors, 9 MB |
|
||||
| Black and White Logo | four-colour badge | 1 | 0.02 s, 1 paths, 52 anchors, 8 MB |
|
||||
| Sketched Art | photo-like | 1 | 0.04 s, 5 paths, 2971 anchors, 9 MB |
|
||||
| Sketched Art | four-colour badge | 1 | 0.02 s, 2 paths, 131 anchors, 8 MB |
|
||||
| Silhouettes | photo-like | 1 | 0.04 s, 2 paths, 791 anchors, 11 MB |
|
||||
| Silhouettes | four-colour badge | 1 | 0.02 s, 1 paths, 25 anchors, 9 MB |
|
||||
| Line Art | photo-like | 1 | 0.04 s, 54 paths, 4421 anchors, 9 MB |
|
||||
| Line Art | four-colour badge | 1 | 0.02 s, 1 paths, 232 anchors, 8 MB |
|
||||
| Technical Drawing | photo-like | 1 | 0.04 s, 221 paths, 7680 anchors, 9 MB |
|
||||
| Technical Drawing | four-colour badge | 1 | 0.02 s, 1 paths, 52 anchors, 8 MB |
|
||||
| Default | photo-like | 1 | 0.04 s, 29 paths, 6888 anchors, 12 MB |
|
||||
| Default | four-colour badge | 1 | 0.02 s, 3 paths, 96 anchors, 12 MB |
|
||||
| High Fidelity Photo | photo-like | 1 | 0.22 s, 968 paths, 114383 anchors, 170 MB |
|
||||
| High Fidelity Photo | four-colour badge | 1 | 0.05 s, 6 paths, 172 anchors, 23 MB |
|
||||
| Low Fidelity Photo | photo-like | 1 | 0.11 s, 129 paths, 22929 anchors, 103 MB |
|
||||
| Low Fidelity Photo | four-colour badge | 1 | 0.05 s, 6 paths, 136 anchors, 23 MB |
|
||||
| 3 Colors | photo-like | 1 | 0.07 s, 9 paths, 3367 anchors, 18 MB |
|
||||
| 3 Colors | four-colour badge | 1 | 0.05 s, 4 paths, 88 anchors, 13 MB |
|
||||
| 6 Colors | photo-like | 1 | 0.08 s, 78 paths, 9008 anchors, 24 MB |
|
||||
| 6 Colors | four-colour badge | 1 | 0.05 s, 5 paths, 84 anchors, 12 MB |
|
||||
| 16 Colors | photo-like | 1 | 0.10 s, 178 paths, 20466 anchors, 32 MB |
|
||||
| 16 Colors | four-colour badge | 1 | 0.05 s, 5 paths, 88 anchors, 12 MB |
|
||||
| Shades of Gray | photo-like | 1 | 0.08 s, 81 paths, 6698 anchors, 45 MB |
|
||||
| Shades of Gray | four-colour badge | 1 | 0.06 s, 10 paths, 733 anchors, 34 MB |
|
||||
| Black and White Logo | photo-like | 1 | 0.04 s, 71 paths, 5465 anchors, 8 MB |
|
||||
| Black and White Logo | four-colour badge | 1 | 0.02 s, 1 paths, 52 anchors, 6 MB |
|
||||
| Sketched Art | photo-like | 1 | 0.04 s, 5 paths, 2971 anchors, 8 MB |
|
||||
| Sketched Art | four-colour badge | 1 | 0.02 s, 2 paths, 131 anchors, 6 MB |
|
||||
| Silhouettes | photo-like | 1 | 0.04 s, 2 paths, 791 anchors, 9 MB |
|
||||
| Silhouettes | four-colour badge | 1 | 0.02 s, 1 paths, 25 anchors, 6 MB |
|
||||
| Line Art | photo-like | 1 | 0.04 s, 54 paths, 4421 anchors, 8 MB |
|
||||
| Line Art | four-colour badge | 1 | 0.02 s, 1 paths, 232 anchors, 6 MB |
|
||||
| Technical Drawing | photo-like | 1 | 0.04 s, 221 paths, 7680 anchors, 8 MB |
|
||||
| Technical Drawing | four-colour badge | 1 | 0.02 s, 1 paths, 52 anchors, 6 MB |
|
||||
| Flat Logo | photo-like | 1 | refused after 0.09 s (not flat art), 40 MB |
|
||||
| Flat Logo | four-colour badge | 1 | 0.64 s, 5 paths, 78 anchors, 146 MB |
|
||||
| Default | photo-like | 4 | 0.18 s, 48 paths, 17801 anchors, 60 MB |
|
||||
| Default | four-colour badge | 4 | 0.09 s, 3 paths, 178 anchors, 64 MB |
|
||||
| High Fidelity Photo | photo-like | 4 | 0.72 s, 4475 paths, 341272 anchors, 981 MB |
|
||||
| High Fidelity Photo | four-colour badge | 4 | 0.24 s, 6 paths, 200 anchors, 152 MB |
|
||||
| Low Fidelity Photo | photo-like | 4 | 0.38 s, 304 paths, 61093 anchors, 568 MB |
|
||||
| Low Fidelity Photo | four-colour badge | 4 | 0.23 s, 6 paths, 152 anchors, 152 MB |
|
||||
| 3 Colors | photo-like | 4 | 0.28 s, 20 paths, 8453 anchors, 104 MB |
|
||||
| 3 Colors | four-colour badge | 4 | 0.18 s, 4 paths, 122 anchors, 84 MB |
|
||||
| 6 Colors | photo-like | 4 | 0.37 s, 115 paths, 23128 anchors, 168 MB |
|
||||
| 6 Colors | four-colour badge | 4 | 0.19 s, 5 paths, 92 anchors, 128 MB |
|
||||
| 16 Colors | photo-like | 4 | 0.32 s, 353 paths, 52749 anchors, 408 MB |
|
||||
| 16 Colors | four-colour badge | 4 | 0.19 s, 5 paths, 96 anchors, 128 MB |
|
||||
| Shades of Gray | photo-like | 4 | 0.29 s, 138 paths, 18794 anchors, 224 MB |
|
||||
| Shades of Gray | four-colour badge | 4 | 0.27 s, 10 paths, 1265 anchors, 220 MB |
|
||||
| Black and White Logo | photo-like | 4 | 0.20 s, 208 paths, 17188 anchors, 36 MB |
|
||||
| Black and White Logo | four-colour badge | 4 | 0.09 s, 1 paths, 64 anchors, 36 MB |
|
||||
| Sketched Art | photo-like | 4 | 0.20 s, 9 paths, 6884 anchors, 36 MB |
|
||||
| Sketched Art | four-colour badge | 4 | 0.09 s, 2 paths, 236 anchors, 36 MB |
|
||||
| Silhouettes | photo-like | 4 | 0.19 s, 2 paths, 1951 anchors, 44 MB |
|
||||
| Silhouettes | four-colour badge | 4 | 0.10 s, 1 paths, 32 anchors, 36 MB |
|
||||
| Line Art | photo-like | 4 | 0.19 s, 127 paths, 12091 anchors, 36 MB |
|
||||
| Line Art | four-colour badge | 4 | 0.09 s, 1 paths, 419 anchors, 36 MB |
|
||||
| Technical Drawing | photo-like | 4 | 0.20 s, 931 paths, 23132 anchors, 36 MB |
|
||||
| Technical Drawing | four-colour badge | 4 | 0.08 s, 1 paths, 64 anchors, 36 MB |
|
||||
| Flat Logo | four-colour badge | 1 | 0.65 s, 5 paths, 78 anchors, 146 MB |
|
||||
| Default | photo-like | 4 | 0.19 s, 48 paths, 17801 anchors, 49 MB |
|
||||
| Default | four-colour badge | 4 | 0.09 s, 3 paths, 178 anchors, 48 MB |
|
||||
| High Fidelity Photo | photo-like | 4 | 0.72 s, 4475 paths, 341272 anchors, 643 MB |
|
||||
| High Fidelity Photo | four-colour badge | 4 | 0.23 s, 6 paths, 200 anchors, 93 MB |
|
||||
| Low Fidelity Photo | photo-like | 4 | 0.36 s, 304 paths, 61093 anchors, 412 MB |
|
||||
| Low Fidelity Photo | four-colour badge | 4 | 0.23 s, 6 paths, 152 anchors, 96 MB |
|
||||
| 3 Colors | photo-like | 4 | 0.26 s, 20 paths, 8453 anchors, 73 MB |
|
||||
| 3 Colors | four-colour badge | 4 | 0.18 s, 4 paths, 122 anchors, 53 MB |
|
||||
| 6 Colors | photo-like | 4 | 0.26 s, 115 paths, 23128 anchors, 100 MB |
|
||||
| 6 Colors | four-colour badge | 4 | 0.19 s, 5 paths, 92 anchors, 46 MB |
|
||||
| 16 Colors | photo-like | 4 | 0.28 s, 353 paths, 52749 anchors, 122 MB |
|
||||
| 16 Colors | four-colour badge | 4 | 0.19 s, 5 paths, 96 anchors, 46 MB |
|
||||
| Shades of Gray | photo-like | 4 | 0.31 s, 138 paths, 18794 anchors, 154 MB |
|
||||
| Shades of Gray | four-colour badge | 4 | 0.26 s, 10 paths, 1265 anchors, 138 MB |
|
||||
| Black and White Logo | photo-like | 4 | 0.19 s, 208 paths, 17188 anchors, 32 MB |
|
||||
| Black and White Logo | four-colour badge | 4 | 0.08 s, 1 paths, 64 anchors, 24 MB |
|
||||
| Sketched Art | photo-like | 4 | 0.20 s, 9 paths, 6884 anchors, 32 MB |
|
||||
| Sketched Art | four-colour badge | 4 | 0.08 s, 2 paths, 236 anchors, 24 MB |
|
||||
| Silhouettes | photo-like | 4 | 0.17 s, 2 paths, 1951 anchors, 36 MB |
|
||||
| Silhouettes | four-colour badge | 4 | 0.08 s, 1 paths, 32 anchors, 24 MB |
|
||||
| Line Art | photo-like | 4 | 0.18 s, 127 paths, 12091 anchors, 32 MB |
|
||||
| Line Art | four-colour badge | 4 | 0.08 s, 1 paths, 419 anchors, 24 MB |
|
||||
| Technical Drawing | photo-like | 4 | 0.19 s, 931 paths, 23132 anchors, 32 MB |
|
||||
| Technical Drawing | four-colour badge | 4 | 0.08 s, 1 paths, 64 anchors, 24 MB |
|
||||
| Flat Logo | photo-like | 4 | refused after 0.10 s (not flat art), 40 MB |
|
||||
| Flat Logo | four-colour badge | 4 | 0.65 s, 5 paths, 69 anchors, 146 MB |
|
||||
| Default | photo-like | 16 | 1.04 s, 127 paths, 43656 anchors, 256 MB |
|
||||
| Default | four-colour badge | 16 | 0.47 s, 3 paths, 250 anchors, 240 MB |
|
||||
| High Fidelity Photo | photo-like | 16 | 2.85 s, 31125 paths, 1175671 anchors, 3856 MB |
|
||||
| High Fidelity Photo | four-colour badge | 16 | 1.11 s, 6 paths, 274 anchors, 576 MB |
|
||||
| Low Fidelity Photo | photo-like | 16 | 1.49 s, 2036 paths, 181832 anchors, 1972 MB |
|
||||
| Low Fidelity Photo | four-colour badge | 16 | 1.07 s, 6 paths, 187 anchors, 576 MB |
|
||||
| 3 Colors | photo-like | 16 | 1.22 s, 76 paths, 22878 anchors, 416 MB |
|
||||
| 3 Colors | four-colour badge | 16 | 0.82 s, 4 paths, 190 anchors, 336 MB |
|
||||
| 6 Colors | photo-like | 16 | 1.13 s, 470 paths, 60539 anchors, 672 MB |
|
||||
| 6 Colors | four-colour badge | 16 | 0.82 s, 5 paths, 126 anchors, 500 MB |
|
||||
| 16 Colors | photo-like | 16 | 1.18 s, 1973 paths, 145173 anchors, 1625 MB |
|
||||
| 16 Colors | four-colour badge | 16 | 0.84 s, 5 paths, 128 anchors, 504 MB |
|
||||
| Shades of Gray | photo-like | 16 | 1.48 s, 686 paths, 53872 anchors, 852 MB |
|
||||
| Shades of Gray | four-colour badge | 16 | 1.40 s, 9 paths, 2216 anchors, 800 MB |
|
||||
| Black and White Logo | photo-like | 16 | 1.15 s, 1128 paths, 52547 anchors, 144 MB |
|
||||
| Black and White Logo | four-colour badge | 16 | 0.47 s, 1 paths, 95 anchors, 128 MB |
|
||||
| Sketched Art | photo-like | 16 | 1.16 s, 15 paths, 16298 anchors, 144 MB |
|
||||
| Sketched Art | four-colour badge | 16 | 0.47 s, 2 paths, 414 anchors, 128 MB |
|
||||
| Silhouettes | photo-like | 16 | 1.34 s, 3 paths, 4516 anchors, 176 MB |
|
||||
| Silhouettes | four-colour badge | 16 | 0.53 s, 1 paths, 40 anchors, 144 MB |
|
||||
| Line Art | photo-like | 16 | 1.04 s, 713 paths, 43982 anchors, 144 MB |
|
||||
| Line Art | four-colour badge | 16 | 0.45 s, 1 paths, 707 anchors, 128 MB |
|
||||
| Technical Drawing | photo-like | 16 | 1.21 s, 4578 paths, 84475 anchors, 144 MB |
|
||||
| Technical Drawing | four-colour badge | 16 | 0.46 s, 1 paths, 95 anchors, 128 MB |
|
||||
| Default | photo-like | 16 | 1.02 s, 127 paths, 43656 anchors, 199 MB |
|
||||
| Default | four-colour badge | 16 | 0.47 s, 3 paths, 250 anchors, 184 MB |
|
||||
| High Fidelity Photo | photo-like | 16 | 3.65 s, 31125 paths, 1175671 anchors, 880 MB |
|
||||
| High Fidelity Photo | four-colour badge | 16 | 1.08 s, 6 paths, 274 anchors, 257 MB |
|
||||
| Low Fidelity Photo | photo-like | 16 | 1.80 s, 2036 paths, 181832 anchors, 754 MB |
|
||||
| Low Fidelity Photo | four-colour badge | 16 | 1.04 s, 6 paths, 187 anchors, 257 MB |
|
||||
| 3 Colors | photo-like | 16 | 1.20 s, 76 paths, 22878 anchors, 290 MB |
|
||||
| 3 Colors | four-colour badge | 16 | 0.80 s, 4 paths, 190 anchors, 205 MB |
|
||||
| 6 Colors | photo-like | 16 | 1.13 s, 470 paths, 60539 anchors, 298 MB |
|
||||
| 6 Colors | four-colour badge | 16 | 0.83 s, 5 paths, 126 anchors, 184 MB |
|
||||
| 16 Colors | photo-like | 16 | 1.15 s, 1973 paths, 145173 anchors, 298 MB |
|
||||
| 16 Colors | four-colour badge | 16 | 0.89 s, 5 paths, 128 anchors, 185 MB |
|
||||
| Shades of Gray | photo-like | 16 | 1.76 s, 686 paths, 53872 anchors, 407 MB |
|
||||
| Shades of Gray | four-colour badge | 16 | 1.33 s, 9 paths, 2216 anchors, 270 MB |
|
||||
| Black and White Logo | photo-like | 16 | 1.13 s, 1128 paths, 52547 anchors, 129 MB |
|
||||
| Black and White Logo | four-colour badge | 16 | 0.36 s, 1 paths, 95 anchors, 88 MB |
|
||||
| Sketched Art | photo-like | 16 | 0.99 s, 15 paths, 16298 anchors, 128 MB |
|
||||
| Sketched Art | four-colour badge | 16 | 0.40 s, 2 paths, 414 anchors, 88 MB |
|
||||
| Silhouettes | photo-like | 16 | 1.37 s, 3 paths, 4516 anchors, 144 MB |
|
||||
| Silhouettes | four-colour badge | 16 | 0.40 s, 1 paths, 40 anchors, 95 MB |
|
||||
| Line Art | photo-like | 16 | 1.07 s, 713 paths, 43982 anchors, 129 MB |
|
||||
| Line Art | four-colour badge | 16 | 0.37 s, 1 paths, 707 anchors, 88 MB |
|
||||
| Technical Drawing | photo-like | 16 | 1.17 s, 4578 paths, 84475 anchors, 130 MB |
|
||||
| Technical Drawing | four-colour badge | 16 | 0.37 s, 1 paths, 95 anchors, 88 MB |
|
||||
| Flat Logo | photo-like | 16 | refused after 0.11 s (not flat art), 40 MB |
|
||||
| Flat Logo | four-colour badge | 16 | 0.69 s, 5 paths, 67 anchors, 146 MB |
|
||||
| Flat Logo | four-colour badge | 16 | 0.66 s, 5 paths, 67 anchors, 146 MB |
|
||||
|
||||
## Revision history
|
||||
|
||||
| date | change |
|
||||
|:--|:--|
|
||||
| 2026-10-13 | Memory: layers traced within the box of their pixels and a few at a time (16 megapixel photo: 3.9 GB to 0.9 GB) |
|
||||
| 2026-10-13 | Shared edges: outlines are cut at their junctions and each piece is fitted once, the same from either side |
|
||||
| 2026-10-13 | Photos: continuous-tone images are smoothed within their tones before quantising, and stacked layers go by lightness |
|
||||
| 2026-10-13 | The palette: made of the picture's own colours, noise-made colours merged, blend pixels settled, cuts where colours differ most, colours compared in Oklab |
|
||||
|
||||
Reference in new issue
Block a user