diff --git a/crates/trace/src/quantize/cut_edge.rs b/crates/trace/src/quantize/cut_edge.rs index 27b7727b38..658d280eb9 100644 --- a/crates/trace/src/quantize/cut_edge.rs +++ b/crates/trace/src/quantize/cut_edge.rs @@ -284,7 +284,7 @@ pub(super) fn settled_wide(mut q: Quantized, img: &Raster, own: &[bool], gray: b /// stay more than 0.065 as far as a single color does. So is a sepia, single-hue or duotone /// picture whose tones follow one curve through the color cube (19 in 20 of its opaque pixels on /// it, see [`on_one_curve`]). Neither is, however far eight colors stay, when sixteen colors stay -/// at most a fifth as far as eight do. That exception holds for flat art of up to sixteen clean +/// at most a tenth as far as eight do. That exception holds for flat art of up to sixteen clean /// levels, gray or tinted, where sixteen colors come within about a level of every pixel. On gray /// and tinted photos sixteen colors stay 0.18 to 0.57 as far as eight do, and on most anti-aliased /// or noisy gray flat art 0.24 to 0.5 as far, so the exception holds for neither. @@ -323,9 +323,9 @@ pub(crate) fn continuous_tone(img: &Raster) -> bool { } let one_line = || 20 * neutral >= 19 * opaque || 20 * on_one_curve(img) >= 19 * opaque; if eight > 0.1 * one { - return !(unsaid(16) <= 0.2 * eight && one_line()); + return !(unsaid(16) <= 0.1 * eight && one_line()); } - unsaid(16) > 0.2 * eight && one_line() + unsaid(16) > 0.1 * eight && one_line() } /// How far (levels) a pixel may lie from the tone curve of its picture and still count as on it, diff --git a/crates/trace/src/tests.rs b/crates/trace/src/tests.rs index 2bf9e1e2b6..8e2f04e286 100644 --- a/crates/trace/src/tests.rs +++ b/crates/trace/src/tests.rs @@ -2009,6 +2009,16 @@ fn a_gray_photo_is_continuous_tone_as_its_color_original_is() { } } +/// A gray photo with little or no noise (a render, a denoised scan) is continuous tone, as its +/// color original is. Sixteen colors stay 0.19 as far from its pixels as eight do. +#[test] +fn a_clean_gray_photo_is_continuous_tone_as_its_color_original_is() { + for noise in [0.0, 1.0, 2.0, 3.0] { + assert!(quantize::continuous_tone(&photo_scene(noise, false)), "color, noise {noise}"); + assert!(quantize::continuous_tone(&photo_scene(noise, true)), "gray, noise {noise}"); + } +} + /// Sepia: dark brown to cream. const SEPIA: [[f64; 3]; 2] = [[45.0, 28.0, 15.0], [250.0, 235.0, 205.0]]; /// A single blue hue: navy to pale blue. diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index 9ba8866a8c..c12b11596f 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -1436,6 +1436,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - **Image Trace, gray photos:** Color and Grayscale smooth a gray photo within its tones before choosing its colors, as they do a color photo. A picture with at least 95% of its opaque pixels within 8 levels across their channels counts as continuous tone when 8 colors leave an error of more than 6 levels and more than 0.065 of the error of one color, instead of 0.1, unless 16 colors leave at most a fifth of the error of 8 (VectorCraft's own values). That exception keeps gray flat art of up to 16 clean levels on its old route; anti-aliased or noisy gray flat art can now count as continuous tone too. Most gray photos the change reaches, and very noisy gray scans of flat art, trace with fewer specks and fewer staircase edges. Some 16 Colors and High Fidelity Photo palettes of gray photos grow toward the requested count, with more anchors and regions. Some gray illustrations and sketches get more anchors and staircase edges at 16 Colors and High Fidelity Photo, and some 6 Colors traces get more staircase edges. Tests: `tests::a_gray_photo_is_continuous_tone_as_its_color_original_is`, `tests::a_gray_photo_is_smoothed_before_it_is_traced`. Scores and hours unchanged. - **Image Trace, tinted photos:** Color and Grayscale smooth a sepia, single-hue or duotone photo within its tones before choosing its colors, as they do a gray photo. A picture with at least 95% of its opaque pixels within 6 levels of its tone curve counts as continuous tone under the same 0.065 rule as a neutral picture. The tone curve runs through the median color of each 8-level stretch along the direction in which the picture's colors spread the most, and a pixel on it must also lie within 6 levels of the plane the colors spread along most, so art in several unrelated colors is not counted (VectorCraft's own rule and values). The neutral rule's exception for 16 colors leaving at most a fifth of the error of 8 applies to it too. Clean tinted bands of 2, 3 and 9 levels and tinted scans of flat art with up to 8 levels of noise stay on the flat-art route. On the synthetic tinted photos the 16 Colors trace keeps 12 to 15 colors instead of 6 to 13, with 525 to 708 anchors instead of up to 1,402. A duotone with strong noise on each channel can still miss the curve and stay unsmoothed. Tests: `tests::a_tinted_photo_is_continuous_tone_as_a_gray_photo_is`, `tests::small_accents_of_other_colors_leave_a_tinted_photo_continuous_tone`, `tests::tinted_flat_art_stays_flat_art`, `tests::pictures_without_tones_are_not_continuous_tone`, `tests::a_tinted_photo_is_smoothed_before_it_is_traced`. Scores and hours unchanged. - **Image Trace, flat art of 10 to 16 levels:** the exception for 16 colors leaving at most a fifth of the error of 8 also applies to a neutral or tinted picture whose 8-color error is more than 0.1 of the error of one color (VectorCraft's own values), so Color and Grayscale trace clean gray, sepia, single-hue and duotone art of 10 to 16 evenly spaced levels as flat art, without smoothing it first. At 16 Colors, 16 gray or sepia levels crossed by two 1 px lines trace as the 35 regions the lines cut them into instead of 33, and Automatic traces 16 clean sepia levels in 9 colors instead of 4. Tests: `tests::flat_art_of_up_to_sixteen_clean_levels_stays_flat_art`, `tests::thin_lines_on_flat_art_of_up_to_sixteen_clean_levels_are_traced`. Scores and hours unchanged. +- **Image Trace, clean gray photos:** the exception for flat art of up to 16 clean levels now applies when 16 colors leave at most a tenth of the error of 8, instead of a fifth (VectorCraft's own values). On the synthetic gray photo with 0 to 2 levels of noise, 16 colors leave 0.19 of the error of 8, so Color and Grayscale now count it as continuous tone and smooth it before tracing, as they do its color original. Clean gray, sepia, single-hue and duotone art of up to 16 levels, where 16 colors leave no error, stays on the flat-art route. Test: `tests::a_clean_gray_photo_is_continuous_tone_as_its_color_original_is`. Scores and hours unchanged. - **Image Trace, JPEG blocks:** Color, Grayscale and Black and White traces smooth the edges of a JPEG's 8 × 8 blocks before tracing, so a dark ground whose tone changes slowly is no longer traced as staircases along the block edges. The block grid is found in the image itself: the mean step between neighboring pixels must peak at one position in eight, across and down. A cropped JPEG and a JPEG saved in another format are smoothed too. A picture of flat 8 × 8 cells is left as it is, and art made of 8 × 8 cells with slight texture inside each cell is smoothed as a JPEG copy would be. A small step at a block edge, with no edge in the eight pixels around it, is spread over those eight pixels, and larger steps are kept, as the deblocking filters of ITU-T H.263 Annex J and MPEG-4 Part 2 Annex F.3.1 do. Black and White smooths only the smallest steps, and traces of more than 16 colors move every row of a stretch of eight by the same amount (VectorCraft's own rule and values). On a 4000 × 3000 photo saved as JPEG, the straight outline segments that lie on the block grid fall from 52% and 51% (across and down) to 24% and 29% at 16 Colors, and from 54% and 51% to 43% and 42% at High Fidelity Photo; staircase runs fall from 83 to 67 (16 Colors), 11 to 1 (6 Colors), 30 to 13 (Black and White Logo) and 428 to 403 (High Fidelity Photo). A 600 px photo saved as a quality-40 JPEG has 4 staircase runs instead of 2 at 16 Colors. Images without a block grid trace as before. Tests: `tests::a_jpegs_blocks_are_not_traced_as_steps`, `deblock::tests`. Scores and hours unchanged. - **Image Trace, Document Library color groups:** with Document Swatches, the panel's Colors menu and `"colorGroup"` trace with one color group's colors instead of every swatch, as the public panel documentation describes Document Library; code-drawn tests in `crates/engine` and the panel. - **Image Trace, Document Library colors:** with Document Swatches, traced fills and strokes use the displayed colors of process, global, spot and tint swatches without links, so editing a swatch leaves the trace unchanged; swatch-library colors are also unlinked; code-drawn tests in `crates/engine`.