mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-10 06:31:19 +00:00
Image Trace: keepColors traces only the listed palette colors
Image Trace had no way to trace some of an image's colors and leave the rest out. Ignore Color drops one color, so tracing only the line work of a multi-color image took a full trace and then deleting the other colors' paths by hand. With "keepColors": ["#rrggbb", ...] in the params of imageTrace.make and imageTrace.makeAndExpand, only the palette colors within about 30 levels of a listed color are traced, the distance Ignore Color matches by. With Method Abutting, the kept colors' paths are the same as in a trace of every color. With Method Overlapping, a kept color's paths do not reach under the colors left out, as with Ignore Color. An empty list traces every color, and a value that is not a six-digit hex color is refused. Flat Logo mode does not use the list. The reply's warnings name each listed color that matches none of the colors the trace found, and say when nothing was traced; the status bar shows the first. The warnings are translated in every complete catalog. The params help of imageTrace.make lists keepColors and the new warnings, and the help of imageTrace.makeAndExpand lists the warnings it returns.
This commit is contained in:
@@ -130,7 +130,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Make",
|
||||
["Object", "Image Trace"],
|
||||
None,
|
||||
"{id?: image or Image Trace group (default: selection), preset?: name (imageTrace.presets), enhanced?: false (the preset's enhanced version: with Auto Grouping, and with Shapes in all but High Fidelity Photo; Flat Logo has none and is traced as it is), params?: {mode: \"blackAndWhite\"|\"grayscale\"|\"color\"|\"logo\", threshold: 0-255, palette: \"limited\"|\"fullTone\"|\"automatic\"|\"documentLibrary\" (color mode; limited: the `colors` best colours, fullTone: as many as the tones need, more with colorDetail, automatic: flat art with its own colours, else fullTone, documentLibrary: at most `colors` of the library's colours, as they are), colors: 2-256, colorDetail: 0-100 (fullTone, automatic), library: \"document\" (the document's swatches) or a swatch library id or name (swatch.library.list; documentLibrary), paths: 0-100, corners: 0-100, noise: px, method: \"abutting\"|\"overlapping\", ignoreWhite (leave out white areas), ignoreColor?: \"#rrggbb\" (with ignoreWhite: the colour left out instead of white), snapCurvesToLines, shapes: false (filled outlines that are a circle, an ellipse, a rectangle or a regular polygon come out as that live shape), autoGrouping: false (each path that has others inside it is grouped with them), gradients: false (grayscale and color: an area whose colour changes evenly along one direction is one path with a linear gradient fill), fills: true, strokes: false (Create: lines up to strokeWidth wide become stroked centre lines; without fills, wider areas become stroked outlines), strokeWidth: px (10), logoColors?: [\"#rrggbb\"…] (mode logo: flat-colour logos only; colours found automatically or named here, white is always its own colour, at most ten; noise = areas under noise/10 px ignored; edges to a fraction of a pixel, sharp corners restored, lines and circles snapped; enclosed transparent areas are painted white unless ignoreWhite makes them holes; fills/strokes are ignored; gradients and photos are refused)}, view?: as imageTrace.setView (default: the traced object's own, else tracingResult), ids?: [id…] (instead of id)} → {id, paths, anchors, colors, warnings: [text…] (the image is over 1500 px on a side, so it traces more slowly; or it was traced scaled down)}",
|
||||
"{id?: image or Image Trace group (default: selection), preset?: name (imageTrace.presets), enhanced?: false (the preset's enhanced version: with Auto Grouping, and with Shapes in all but High Fidelity Photo; Flat Logo has none and is traced as it is), params?: {mode: \"blackAndWhite\"|\"grayscale\"|\"color\"|\"logo\", threshold: 0-255, palette: \"limited\"|\"fullTone\"|\"automatic\"|\"documentLibrary\" (color mode; limited: the `colors` best colours, fullTone: as many as the tones need, more with colorDetail, automatic: flat art with its own colours, else fullTone, documentLibrary: at most `colors` of the library's colours, as they are), colors: 2-256, colorDetail: 0-100 (fullTone, automatic), library: \"document\" (the document's swatches) or a swatch library id or name (swatch.library.list; documentLibrary), paths: 0-100, corners: 0-100, noise: px, method: \"abutting\"|\"overlapping\", ignoreWhite (leave out white areas), ignoreColor?: \"#rrggbb\" (with ignoreWhite: the colour left out instead of white), keepColors?: [\"#rrggbb\"…] (not mode logo: only the palette colors within about 30 levels of a listed color are traced; empty: every color), snapCurvesToLines, shapes: false (filled outlines that are a circle, an ellipse, a rectangle or a regular polygon come out as that live shape), autoGrouping: false (each path that has others inside it is grouped with them), gradients: false (grayscale and color: an area whose colour changes evenly along one direction is one path with a linear gradient fill), fills: true, strokes: false (Create: lines up to strokeWidth wide become stroked centre lines; without fills, wider areas become stroked outlines), strokeWidth: px (10), logoColors?: [\"#rrggbb\"…] (mode logo: flat-colour logos only; colours found automatically or named here, white is always its own colour, at most ten; noise = areas under noise/10 px ignored; edges to a fraction of a pixel, sharp corners restored, lines and circles snapped; enclosed transparent areas are painted white unless ignoreWhite makes them holes; fills/strokes are ignored; gradients and photos are refused)}, view?: as imageTrace.setView (default: the traced object's own, else tracingResult), ids?: [id…] (instead of id)} → {id, paths, anchors, colors, warnings: [text…] (the image is over 1500 px on a side, so it traces more slowly; or it was traced scaled down; or a keepColors color matches none the trace found, or nothing was traced)}",
|
||||
has_selection_or_ids,
|
||||
|s, p| trace_make(s, p, false)
|
||||
),
|
||||
@@ -139,7 +139,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Make and Expand",
|
||||
["Object", "Image Trace"],
|
||||
None,
|
||||
"{…as imageTrace.make} same as imageTrace.make, then expand → {id, paths, anchors, colors}",
|
||||
"{…as imageTrace.make} same as imageTrace.make, then expand → {id, paths, anchors, colors, warnings: [text…] (as imageTrace.make)}",
|
||||
has_selection_or_ids,
|
||||
|s, p| trace_make(s, p, true)
|
||||
),
|
||||
@@ -1121,7 +1121,8 @@ fn trace_make(s: &mut Session, p: &Value, expand: bool) -> Result<Value> {
|
||||
let raster = tr::Raster::decode_to_fit(&blob.bytes).map_err(|e| EngineError::Other(e.to_string()))?;
|
||||
let library = trace_library(s, &mut params)?;
|
||||
let res = tr::trace_within(&raster, ¶ms, MAX_TRACE_ANCHORS).map_err(|e| EngineError::Other(e.to_string()))?;
|
||||
let warnings = trace_warnings((img.width, img.height), (raster.width, raster.height));
|
||||
let mut warnings = keep_warnings(¶ms, &res);
|
||||
warnings.extend(trace_warnings((img.width, img.height), (raster.width, raster.height)));
|
||||
// Pixel space of the decoded raster → the image object's pixel space → document.
|
||||
let sx = img.width.max(1) as f64 / raster.width.max(1) as f64;
|
||||
let sy = img.height.max(1) as f64 / raster.height.max(1) as f64;
|
||||
@@ -1221,6 +1222,27 @@ pub(crate) fn trace_warnings(size: (u32, u32), traced: (u32, u32)) -> Vec<String
|
||||
out
|
||||
}
|
||||
|
||||
/// What a trace with Keep Colors tells the user: that nothing was traced because no color the
|
||||
/// trace found matches a listed one, or because Ignore Color left out the ones that match; each
|
||||
/// listed color that matches none of them; and that Flat Logo mode does not use the list.
|
||||
pub(crate) fn keep_warnings(params: &tr::TraceParams, res: &tr::TraceResult) -> Vec<String> {
|
||||
if params.keep_colors.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
if params.mode == tr::Mode::Logo {
|
||||
return vec!["Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds.".to_string()];
|
||||
}
|
||||
if res.paths.is_empty() && res.keep_unmatched.len() == params.keep_colors.len() {
|
||||
return vec![format!("Nothing was traced: none of the colors the trace found matches keepColors ({}).", params.keep_colors.join(", "))];
|
||||
}
|
||||
let mut out = vec![];
|
||||
if res.paths.is_empty() && params.ignore_white {
|
||||
out.push("Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists.".to_string());
|
||||
}
|
||||
out.extend(res.keep_unmatched.iter().map(|c| format!("keepColors: none of the colors the trace found matches {c}, so nothing of it is traced.")));
|
||||
out
|
||||
}
|
||||
|
||||
fn trace_targets(s: &Session, p: &Value) -> Result<Vec<NodeId>> {
|
||||
let d = &s.doc()?.doc;
|
||||
let v: Vec<NodeId> = root_ids(s, p)?.into_iter().filter(|i| d.node(*i).is_some_and(is_trace_group)).collect();
|
||||
|
||||
@@ -2047,6 +2047,91 @@ fn image_trace_make_places_paths_over_the_image() {
|
||||
assert_eq!(paths[0].appearance.fill_paint(), Paint::solid(Color::rgb8(0, 0, 0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn image_trace_keep_colors_traces_only_the_colors_listed() {
|
||||
// A light field with a black ring, a red square and a blue bar on it.
|
||||
let art = vectorcraft_trace::Raster::from_fn(200, 150, |x, y| {
|
||||
let r = (f64::from(x) + 0.5 - 70.0).hypot(f64::from(y) + 0.5 - 60.0);
|
||||
if (34.0..=40.0).contains(&r) {
|
||||
[0, 0, 0, 255]
|
||||
} else if (130..170).contains(&x) && (30..70).contains(&y) {
|
||||
[200, 40, 50, 255]
|
||||
} else if (30..170).contains(&x) && (110..130).contains(&y) {
|
||||
[40, 80, 200, 255]
|
||||
} else {
|
||||
[240, 240, 220, 255]
|
||||
}
|
||||
});
|
||||
let traced = |keep: Value| {
|
||||
let mut s = session();
|
||||
add_image(&mut s, &art, Affine::IDENTITY);
|
||||
let params = json!({"params": {"mode": "color", "palette": "limited", "colors": 4, "keepColors": keep}});
|
||||
let r = s.execute("imageTrace.makeAndExpand", ¶ms)?;
|
||||
let g = node(&s, NodeId(r["id"].as_u64().unwrap()));
|
||||
let fills: Vec<Paint> = g.children().unwrap().iter().map(|n| n.appearance.fill_paint()).collect();
|
||||
Ok::<_, EngineError>((r["colors"].clone(), fills))
|
||||
};
|
||||
let (black, red, blue, light) = (Color::rgb8(0, 0, 0), Color::rgb8(200, 40, 50), Color::rgb8(40, 80, 200), Color::rgb8(240, 240, 220));
|
||||
let has = |fills: &[Paint], c: Color| fills.contains(&Paint::solid(c));
|
||||
// Nothing listed: every color.
|
||||
let (colors, fills) = traced(json!([])).unwrap();
|
||||
assert_eq!(colors, 4);
|
||||
assert!([black, red, blue, light].into_iter().all(|c| has(&fills, c)), "{fills:?}");
|
||||
// The black and the red only.
|
||||
let (colors, fills) = traced(json!(["#000000", "#c8283c"])).unwrap();
|
||||
assert_eq!(colors, 2);
|
||||
assert!(has(&fills, black) && has(&fills, red), "{fills:?}");
|
||||
assert!(fills.iter().all(|f| *f == Paint::solid(black) || *f == Paint::solid(red)), "{fills:?}");
|
||||
// A color that is none is refused.
|
||||
let e = traced(json!(["#000000", "black"])).unwrap_err().to_string();
|
||||
assert!(e.contains("\"black\"") && e.contains("#rrggbb"), "{e}");
|
||||
assert!(find_command("imageTrace.make").unwrap().params.contains("keepColors?: [\"#rrggbb\"…]"));
|
||||
assert!(find_command("imageTrace.makeAndExpand").unwrap().params.contains("warnings: [text…] (as imageTrace.make)"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn image_trace_keep_colors_warns_about_colors_that_match_nothing() {
|
||||
// A light field with a black ring and a red square on it.
|
||||
let art = vectorcraft_trace::Raster::from_fn(200, 150, |x, y| {
|
||||
let r = (f64::from(x) + 0.5 - 70.0).hypot(f64::from(y) + 0.5 - 60.0);
|
||||
if (34.0..=40.0).contains(&r) {
|
||||
[0, 0, 0, 255]
|
||||
} else if (130..170).contains(&x) && (30..70).contains(&y) {
|
||||
[200, 40, 50, 255]
|
||||
} else {
|
||||
[240, 240, 220, 255]
|
||||
}
|
||||
});
|
||||
let traced = |params: Value| {
|
||||
let mut s = session();
|
||||
add_image(&mut s, &art, Affine::IDENTITY);
|
||||
let r = s.execute("imageTrace.makeAndExpand", &json!({ "params": params })).unwrap();
|
||||
(r["paths"].as_u64().unwrap(), r["warnings"].clone())
|
||||
};
|
||||
let color = |keep: Value| traced(json!({"mode": "color", "palette": "limited", "colors": 3, "keepColors": keep}));
|
||||
// Every color listed is in the image: no warning.
|
||||
let (paths, warnings) = color(json!(["#000000", "#c8283c"]));
|
||||
assert!(paths > 0);
|
||||
assert_eq!(warnings, json!([]));
|
||||
// No color matches: nothing is traced, and the reply says why.
|
||||
assert_eq!(
|
||||
color(json!(["#ff00ff", "#00ffff"])),
|
||||
(0, json!(["Nothing was traced: none of the colors the trace found matches keepColors (#ff00ff, #00ffff)."]))
|
||||
);
|
||||
// One color matches nothing: the others are traced, and that one is named.
|
||||
let (paths, warnings) = color(json!(["#000000", "#00ffff"]));
|
||||
assert!(paths > 0);
|
||||
assert_eq!(warnings, json!(["keepColors: none of the colors the trace found matches #00ffff, so nothing of it is traced."]));
|
||||
// Ignore Color leaves out the only color listed.
|
||||
let ignored =
|
||||
traced(json!({"mode": "color", "palette": "limited", "colors": 3, "keepColors": ["#000000"], "ignoreWhite": true, "ignoreColor": "#000000"}));
|
||||
assert_eq!(ignored, (0, json!(["Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists."])));
|
||||
// Flat Logo mode does not use the list.
|
||||
let (paths, warnings) = traced(json!({"mode": "logo", "keepColors": ["#ff00ff"]}));
|
||||
assert!(paths > 0);
|
||||
assert_eq!(warnings, json!(["Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds."]));
|
||||
}
|
||||
|
||||
/// Shapes: the disc of the test image comes out as a live ellipse where the image lies, the same
|
||||
/// circle as its traced path; without the option it is a plain path.
|
||||
#[test]
|
||||
|
||||
+43
-6
@@ -295,6 +295,11 @@ pub struct TraceParams {
|
||||
/// The colour Ignore Color leaves out (`#rrggbb`): the palette colours within about 30 levels
|
||||
/// of it. `None` is white. (Flat Logo mode leaves out white only.)
|
||||
pub ignore_color: Option<String>,
|
||||
/// Keep Colors: the colors to trace (`#rrggbb`). Only the palette colors within about 30
|
||||
/// levels of one of them (as Ignore Color matches a color) are traced, a gradient by its middle
|
||||
/// color, and their paths are the ones the trace of every color has. Empty traces every color.
|
||||
/// (Flat Logo mode does not use it: it traces the colors named in `logo_colors`.)
|
||||
pub keep_colors: Vec<String>,
|
||||
/// Replace nearly-straight curves with straight lines. In Logo mode this also snaps tight arcs
|
||||
/// to true circles.
|
||||
pub snap_curves_to_lines: bool,
|
||||
@@ -336,6 +341,7 @@ impl Default for TraceParams {
|
||||
method: Method::Abutting,
|
||||
ignore_white: false,
|
||||
ignore_color: None,
|
||||
keep_colors: Vec::new(),
|
||||
snap_curves_to_lines: false,
|
||||
shapes: false,
|
||||
auto_grouping: false,
|
||||
@@ -484,6 +490,9 @@ pub struct TraceResult {
|
||||
/// option). Each path drawn together with those inside it, in the order they have here, paints
|
||||
/// what `paths` paints in its order.
|
||||
pub parents: Vec<Option<usize>>,
|
||||
/// Keep Colors: the colors listed in [`TraceParams::keep_colors`] (as written) that no color
|
||||
/// the trace found matches, so that nothing of them is traced. (Flat Logo mode: empty.)
|
||||
pub keep_unmatched: Vec<String>,
|
||||
}
|
||||
|
||||
impl TraceResult {
|
||||
@@ -504,6 +513,12 @@ fn is_ignored(c: [u8; 3], target: Option<[u8; 3]>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether Keep Colors traces palette color `c`: every color when `keep` is empty, else those
|
||||
/// Ignore Color would match to one of `keep`.
|
||||
fn is_kept(c: [u8; 3], keep: &[[u8; 3]]) -> bool {
|
||||
keep.is_empty() || keep.iter().any(|&k| is_ignored(c, Some(k)))
|
||||
}
|
||||
|
||||
/// Trace `img` with `params`. Failures (an image Logo mode refuses, say) give an empty result: use
|
||||
/// [`trace_within`] to see why.
|
||||
pub fn trace(img: &Raster, params: &TraceParams) -> TraceResult {
|
||||
@@ -530,6 +545,12 @@ pub fn trace_within(img: &Raster, params: &TraceParams, max_anchors: usize) -> R
|
||||
|
||||
fn trace_paths(img: &Raster, params: &TraceParams, max_anchors: usize) -> Result<TraceResult, TraceError> {
|
||||
let (w, h) = (img.width as usize, img.height as usize);
|
||||
// The colors Keep Colors traces (checked in every mode).
|
||||
let listed = params
|
||||
.keep_colors
|
||||
.iter()
|
||||
.map(|name| logo::parse_hex(name).ok_or_else(|| TraceError::BadPalette(name.clone())))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
if params.mode == Mode::Logo {
|
||||
return logo::trace_logo(img, params, max_anchors);
|
||||
}
|
||||
@@ -611,14 +632,26 @@ fn trace_paths(img: &Raster, params: &TraceParams, max_anchors: usize) -> Result
|
||||
for (r, &i) in order.iter().enumerate() {
|
||||
rank[i] = r;
|
||||
}
|
||||
let layers: Vec<(usize, usize)> =
|
||||
order.iter().copied().enumerate().filter(|&(_, ci)| !(params.ignore_white && is_ignored(q.palette[ci], ignore))).collect();
|
||||
// Layers left out: Ignore Color's, and those Keep Colors does not list. Abutting, the others
|
||||
// are traced as they are in the trace of every color; stacked, they do not reach under the
|
||||
// colors left out (see `Layers::ignored`).
|
||||
let dropped = |ci: usize| (params.ignore_white && is_ignored(q.palette[ci], ignore)) || !is_kept(q.palette[ci], &listed);
|
||||
let layers: Vec<(usize, usize)> = order.iter().copied().enumerate().filter(|&(_, ci)| !dropped(ci)).collect();
|
||||
// The listed colors that match none of the colors found.
|
||||
let keep_unmatched = params
|
||||
.keep_colors
|
||||
.iter()
|
||||
.zip(&listed)
|
||||
.filter(|&(_, &k)| !order.iter().any(|&ci| is_kept(q.palette[ci], &[k])))
|
||||
.map(|(name, _)| name.clone())
|
||||
.collect();
|
||||
let job = Layers {
|
||||
q: &q,
|
||||
rank: &rank,
|
||||
params,
|
||||
img,
|
||||
ignore,
|
||||
keep: &listed,
|
||||
boxes,
|
||||
gradients: &gradients,
|
||||
bw_tones: bw_tones(img, &q),
|
||||
@@ -628,7 +661,7 @@ fn trace_paths(img: &Raster, params: &TraceParams, max_anchors: usize) -> Result
|
||||
anchors: AtomicUsize::new(0),
|
||||
max_anchors,
|
||||
};
|
||||
let mut out = TraceResult::default();
|
||||
let mut out = TraceResult { keep_unmatched, ..TraceResult::default() };
|
||||
// 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.
|
||||
@@ -681,6 +714,8 @@ struct Layers<'a> {
|
||||
img: &'a Raster,
|
||||
/// The colour Ignore Color leaves out, if not white.
|
||||
ignore: Option<[u8; 3]>,
|
||||
/// The colors Keep Colors lists (empty: every color).
|
||||
keep: &'a [[u8; 3]],
|
||||
/// The box each palette entry's pixels lie in: `(x0, y0, x1, y1)`, the far sides excluded.
|
||||
boxes: Vec<Option<(usize, usize, usize, usize)>>,
|
||||
/// Gradients: the gradient each palette entry is, if it is one.
|
||||
@@ -697,10 +732,11 @@ struct Layers<'a> {
|
||||
}
|
||||
|
||||
impl Layers<'_> {
|
||||
/// Ignore White: white is no part of any layer (stacked layers reach under the layers above
|
||||
/// them, and must not reach under white that is left out).
|
||||
/// Ignore White, and the colors Keep Colors does not list: such a color is no part of any
|
||||
/// layer (stacked layers reach under the layers above them, and must not reach under a color
|
||||
/// that is left out).
|
||||
fn ignored(&self, label: u16) -> bool {
|
||||
self.params.ignore_white && self.q.palette.get(label as usize).is_some_and(|c| is_ignored(*c, self.ignore))
|
||||
self.q.palette.get(label as usize).is_some_and(|c| (self.params.ignore_white && is_ignored(*c, self.ignore)) || !is_kept(*c, self.keep))
|
||||
}
|
||||
/// The region across a crack, for cutting outlines at their junctions: the outside pixel's
|
||||
/// colour. Stacked layers end on many colours at once and share no edge: one neighbour.
|
||||
@@ -1058,6 +1094,7 @@ pub(crate) fn shift_probe(img: &Raster, params: &TraceParams) -> Vec<[f64; 4]> {
|
||||
params,
|
||||
img,
|
||||
ignore: None,
|
||||
keep: &[],
|
||||
boxes: vec![None; n],
|
||||
gradients: &gradients,
|
||||
bw_tones: bw_tones(img, &q),
|
||||
|
||||
@@ -1095,6 +1095,105 @@ fn ignore_color_leaves_out_the_colour_picked() {
|
||||
assert_eq!(serde_json::to_value(¶ms).unwrap()["ignoreColor"], serde_json::Value::Null);
|
||||
}
|
||||
|
||||
/// A navy field with a yellow disc, a green bar and a red square on it, hard-edged.
|
||||
fn four_color_art() -> Raster {
|
||||
Raster::from_fn(160, 120, |x, y| {
|
||||
let (fx, fy) = (f64::from(x) + 0.5, f64::from(y) + 0.5);
|
||||
if Point::new(fx, fy).distance(Point::new(50.0, 45.0)) <= 30.0 {
|
||||
[250, 200, 40, 255]
|
||||
} else if (20.0..140.0).contains(&fx) && (90.0..108.0).contains(&fy) {
|
||||
[40, 160, 90, 255]
|
||||
} else if (100.0..140.0).contains(&fx) && (20.0..60.0).contains(&fy) {
|
||||
[200, 40, 50, 255]
|
||||
} else {
|
||||
[20, 40, 90, 255]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keep_colors_traces_only_the_colors_listed() {
|
||||
let near = |c: [u8; 3], want: [u8; 3]| (0..3).all(|k| c[k].abs_diff(want[k]) <= 3);
|
||||
let (yellow, red, navy) = ([250, 200, 40], [200, 40, 50], [20, 40, 90]);
|
||||
let img = four_color_art();
|
||||
let pixels = |res: &TraceResult, c: [u8; 3]| res.paths.iter().filter(|p| near(p.color, c)).map(|p| p.pixels).sum::<usize>();
|
||||
let abutting = TraceParams { mode: Mode::Color, palette: Palette::Limited, colors: 4, ..TraceParams::default() };
|
||||
let abutting_all = trace(&img, &abutting);
|
||||
for method in [Method::Abutting, Method::Overlapping] {
|
||||
let params = TraceParams { method, ..abutting.clone() };
|
||||
let all = trace(&img, ¶ms);
|
||||
assert_eq!(all.palette.len(), 4, "{method:?}: {:?}", all.palette);
|
||||
// The yellow and the red, each picked a little off.
|
||||
let res = trace(&img, &TraceParams { keep_colors: vec!["#f0c832".into(), "#c8283c".into()], ..params.clone() });
|
||||
assert_eq!(res.palette.len(), 2, "{method:?}: {:?}", res.palette);
|
||||
if method == Method::Abutting {
|
||||
// Their paths as the whole trace has them.
|
||||
let want: Vec<TracedPath> = all.paths.iter().filter(|p| near(p.color, yellow) || near(p.color, red)).cloned().collect();
|
||||
assert!(want.iter().any(|p| near(p.color, yellow)) && want.iter().any(|p| near(p.color, red)));
|
||||
assert_eq!(res.paths, want);
|
||||
} else {
|
||||
// Stacked, the red reaches under the yellow above it, not under the green left out.
|
||||
assert!(res.paths.iter().all(|p| near(p.color, yellow) || near(p.color, red)));
|
||||
assert_eq!(pixels(&res, red), pixels(&abutting_all, red) + pixels(&abutting_all, yellow));
|
||||
assert_eq!(pixels(&res, yellow), pixels(&abutting_all, yellow));
|
||||
// The navy field alone, at the bottom of the stack: no part of the colors left out.
|
||||
let field = trace(&img, &TraceParams { keep_colors: vec!["#14285a".into()], ..params.clone() });
|
||||
assert!(!field.paths.is_empty());
|
||||
assert_eq!(pixels(&field, navy), pixels(&abutting_all, navy));
|
||||
assert!(pixels(&all, navy) > pixels(&abutting_all, navy));
|
||||
}
|
||||
// Every color listed: the trace of every color, as with none listed.
|
||||
let every = vec!["#fac828".into(), "#28a05a".into(), "#c82832".into(), "#14285a".into()];
|
||||
assert_eq!(trace(&img, &TraceParams { keep_colors: every, ..params.clone() }), all, "{method:?}");
|
||||
// A color the image does not have: nothing is traced.
|
||||
assert!(trace(&img, &TraceParams { keep_colors: vec!["#ff00ff".into()], ..params.clone() }).paths.is_empty(), "{method:?}");
|
||||
// With Ignore Color as well, a kept color it matches is left out.
|
||||
let both = TraceParams {
|
||||
keep_colors: vec!["#fac828".into(), "#14285a".into()],
|
||||
ignore_white: true,
|
||||
ignore_color: Some("#14285a".into()),
|
||||
..params.clone()
|
||||
};
|
||||
let res = trace(&img, &both);
|
||||
assert!(!res.paths.is_empty() && res.paths.iter().all(|p| near(p.color, yellow)), "{method:?}");
|
||||
}
|
||||
// A color that is none is refused, in Flat Logo mode too.
|
||||
for mode in [Mode::Color, Mode::Logo] {
|
||||
let bad = trace_within(&img, &TraceParams { mode, keep_colors: vec!["#c8283c".into(), "red".into()], ..TraceParams::default() }, usize::MAX);
|
||||
assert!(matches!(&bad, Err(TraceError::BadPalette(name)) if name == "red"), "{mode:?}");
|
||||
}
|
||||
// Old documents have no such setting: every color.
|
||||
let old: TraceParams = serde_json::from_str(r#"{"mode":"color"}"#).unwrap();
|
||||
assert!(old.keep_colors.is_empty());
|
||||
let on: TraceParams = serde_json::from_str(r##"{"keepColors":["#c8283c"]}"##).unwrap();
|
||||
assert_eq!(on.keep_colors, ["#c8283c"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keep_colors_names_the_colors_nothing_matches() {
|
||||
let img = four_color_art();
|
||||
let params = TraceParams { mode: Mode::Color, palette: Palette::Limited, colors: 4, ..TraceParams::default() };
|
||||
let unmatched = |keep: &[&str], params: &TraceParams| {
|
||||
let res = trace(&img, &TraceParams { keep_colors: keep.iter().map(|k| k.to_string()).collect(), ..params.clone() });
|
||||
(res.keep_unmatched, res.paths.len())
|
||||
};
|
||||
// Every color listed matches one the trace found.
|
||||
assert_eq!(unmatched(&["#f0c832", "#c8283c"], ¶ms).0, Vec::<String>::new());
|
||||
// A color the image does not have is named, as written, beside the ones traced.
|
||||
let (names, paths) = unmatched(&["#f0c832", "#FF00FF", "#c8283c"], ¶ms);
|
||||
assert_eq!(names, ["#FF00FF"]);
|
||||
assert!(paths > 0);
|
||||
// None matches: every one is named, and nothing is traced.
|
||||
assert_eq!(unmatched(&["#ff00ff", "#00ffff"], ¶ms), (vec!["#ff00ff".to_string(), "#00ffff".to_string()], 0));
|
||||
// A color Ignore Color leaves out still matches one the trace found.
|
||||
let ignoring = TraceParams { ignore_white: true, ignore_color: Some("#14285a".into()), ..params.clone() };
|
||||
assert_eq!(unmatched(&["#14285a"], &ignoring), (Vec::new(), 0));
|
||||
// With none listed, none is named.
|
||||
assert!(trace(&img, ¶ms).keep_unmatched.is_empty());
|
||||
// Flat Logo mode does not use the list.
|
||||
assert!(trace(&img, &TraceParams { mode: Mode::Logo, keep_colors: vec!["#ff00ff".into()], ..params }).keep_unmatched.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snap_curves_to_lines_levels_a_rectangle_a_degree_askew() {
|
||||
// 120 × 60, turned 1.5° about its centre.
|
||||
|
||||
@@ -5385,6 +5385,10 @@ mark-style Japanese Japonské
|
||||
Snap to Perpendicular Přichytávat ke kolmici
|
||||
@msg unknown snap option `{key}` (use {options}) neznámá možnost přichytávání `{key}` (použijte {options})
|
||||
Gap Length: Délka mezery:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Režim Ploché logo nepoužívá keepColors: vektorizuje barvy uvedené v logoColors nebo barvy, které najde.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Nic nebylo vektorizováno: žádná z barev, které vektorizace našla, neodpovídá keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Nic nebylo vektorizováno: Ignorovat barvu vynechává všechny oblasti barev uvedených v keepColors.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: žádná z barev, které vektorizace našla, neodpovídá {c}, takže z ní není nic vektorizováno.
|
||||
Artboard {n} of {total} Pracovní plocha {n} z {total}
|
||||
File {n} of {total} Soubor {n} z {total}
|
||||
Encoding and writing the file… Kódování a zápis souboru…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4964,6 +4964,10 @@ effect Soft Weich
|
||||
Snap to Perpendicular An Senkrechter ausrichten
|
||||
@msg unknown snap option `{key}` (use {options}) unbekannte Einrastoption `{key}` (möglich: {options})
|
||||
Gap Length: Lückenlänge:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Der Modus „Flaches Logo“ verwendet keepColors nicht: Er zeichnet die in logoColors genannten Farben nach oder die Farben, die er findet.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Nichts wurde nachgezeichnet: Keine der beim Nachzeichnen gefundenen Farben entspricht keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Nichts wurde nachgezeichnet: „Farbe ignorieren“ lässt jeden Bereich der in keepColors aufgeführten Farben aus.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: Keine der beim Nachzeichnen gefundenen Farben entspricht {c}, daher wird davon nichts nachgezeichnet.
|
||||
Artboard {n} of {total} Zeichenfläche {n} von {total}
|
||||
File {n} of {total} Datei {n} von {total}
|
||||
Encoding and writing the file… Datei wird codiert und geschrieben…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5337,6 +5337,10 @@ effect Points Σημεία
|
||||
Snap to Perpendicular Προσκόλληση σε κάθετο
|
||||
@msg unknown snap option `{key}` (use {options}) άγνωστη επιλογή προσκόλλησης `{key}` (χρησιμοποιήστε {options})
|
||||
Gap Length: Μήκος κενού:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Η λειτουργία Επίπεδο λογότυπο δεν χρησιμοποιεί το keepColors: ανιχνεύει τα χρώματα που ορίζονται στο logoColors ή τα χρώματα που βρίσκει.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Δεν ανιχνεύτηκε τίποτα: κανένα από τα χρώματα που βρήκε η ανίχνευση δεν αντιστοιχεί στο keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Δεν ανιχνεύτηκε τίποτα: η Παράβλεψη χρώματος παραλείπει κάθε περιοχή των χρωμάτων που ορίζει το keepColors.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: κανένα από τα χρώματα που βρήκε η ανίχνευση δεν αντιστοιχεί στο {c}, οπότε τίποτα από αυτό δεν ανιχνεύεται.
|
||||
Artboard {n} of {total} Πίνακας σχεδίασης {n} από {total}
|
||||
File {n} of {total} Αρχείο {n} από {total}
|
||||
Encoding and writing the file… Κωδικοποίηση και εγγραφή του αρχείου…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2066 and column 19.
|
@@ -5327,6 +5327,10 @@ mark-style Japanese Japonesas
|
||||
Snap to Perpendicular Ajustar a perpendicular
|
||||
@msg unknown snap option `{key}` (use {options}) opción de ajuste desconocida `{key}` (use {options})
|
||||
Gap Length: Longitud del hueco:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. El modo Logotipo plano no usa keepColors: calca los colores indicados en logoColors o los colores que encuentra.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). No se calcó nada: ninguno de los colores que encontró el calco coincide con keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. No se calcó nada: Ignorar color omite todas las áreas de los colores que indica keepColors.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: ninguno de los colores que encontró el calco coincide con {c}, así que no se calca nada de él.
|
||||
Artboard {n} of {total} Mesa de trabajo {n} de {total}
|
||||
File {n} of {total} Archivo {n} de {total}
|
||||
Encoding and writing the file… Codificando y escribiendo el archivo…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5349,6 +5349,10 @@ mark-style Japanese Japanilainen
|
||||
Snap to Perpendicular Kohdista kohtisuoraan
|
||||
@msg unknown snap option `{key}` (use {options}) tuntematon tartuntavalinta `{key}` (käytä: {options})
|
||||
Gap Length: Aukon pituus:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Tasainen logo -tila ei käytä keepColors-asetusta: se jäljittää logoColors-asetuksessa nimetyt värit tai löytämänsä värit.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Mitään ei jäljitetty: mikään jäljityksen löytämistä väreistä ei vastaa keepColors-asetusta ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Mitään ei jäljitetty: Ohita väri jättää pois kaikki keepColors-asetuksen värien alueet.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: mikään jäljityksen löytämistä väreistä ei vastaa väriä {c}, joten siitä ei jäljitetä mitään.
|
||||
Artboard {n} of {total} Piirtoalusta {n}/{total}
|
||||
File {n} of {total} Tiedosto {n}/{total}
|
||||
Encoding and writing the file… Tiedostoa koodataan ja kirjoitetaan…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5384,6 +5384,10 @@ theme Appearance Apparence
|
||||
Snap to Perpendicular Magnétisme de la perpendiculaire
|
||||
@msg unknown snap option `{key}` (use {options}) option de magnétisme inconnue `{key}` (utilisez {options})
|
||||
Gap Length: Longueur de lacune :
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Le mode Logo en aplats n’utilise pas keepColors : il vectorise les couleurs indiquées dans logoColors ou celles qu’il trouve.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Rien n’a été vectorisé : aucune des couleurs trouvées par la vectorisation ne correspond à keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Rien n’a été vectorisé : Ignorer la couleur omet toutes les zones des couleurs indiquées dans keepColors.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors : aucune des couleurs trouvées par la vectorisation ne correspond à {c}, donc rien n’en est vectorisé.
|
||||
Artboard {n} of {total} Plan de travail {n} sur {total}
|
||||
File {n} of {total} Fichier {n} sur {total}
|
||||
Encoding and writing the file… Encodage et écriture du fichier…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5371,6 +5371,10 @@ imageTrace Outline Körvonal
|
||||
Snap to Perpendicular Illesztés merőlegesre
|
||||
@msg unknown snap option `{key}` (use {options}) ismeretlen illesztési beállítás: `{key}` (használható: {options})
|
||||
Gap Length: Rés hossza:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Az Egyszínű logó mód nem használja a keepColors beállítást: a logoColors beállításban megadott színeket vagy az általa talált színeket vektorizálja.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Semmi sem lett vektorizálva: a vektorizálás által talált színek egyike sem felel meg a keepColors beállításnak ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Semmi sem lett vektorizálva: a Szín figyelmen kívül hagyása kihagyja a keepColors beállításban felsorolt színek minden területét.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: a vektorizálás által talált színek egyike sem felel meg ennek: {c}, így belőle semmi sem lesz vektorizálva.
|
||||
Artboard {n} of {total} Rajztábla: {n} / {total}
|
||||
File {n} of {total} Fájl: {n} / {total}
|
||||
Encoding and writing the file… A fájl kódolása és írása…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4998,6 +4998,10 @@ lighting Light Luce
|
||||
Snap to Perpendicular Aggancia alla perpendicolare
|
||||
@msg unknown snap option `{key}` (use {options}) opzione di aggancio sconosciuta `{key}` (usare {options})
|
||||
Gap Length: Lunghezza lacuna:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. La modalità Logo piatto non usa keepColors: vettorializza i colori indicati in logoColors o i colori che trova.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Non è stato vettorializzato nulla: nessuno dei colori trovati dalla vettorializzazione corrisponde a keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Non è stato vettorializzato nulla: Ignora colore esclude ogni area dei colori elencati in keepColors.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: nessuno dei colori trovati dalla vettorializzazione corrisponde a {c}, quindi non ne viene vettorializzato nulla.
|
||||
Artboard {n} of {total} Tavola da disegno {n} di {total}
|
||||
File {n} of {total} File {n} di {total}
|
||||
Encoding and writing the file… Codifica e scrittura del file…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5038,6 +5038,10 @@ lighting Light ライト
|
||||
Snap to Perpendicular 垂線にスナップ
|
||||
@msg unknown snap option `{key}` (use {options}) 不明なスナップオプション `{key}` ({options} を使用してください)
|
||||
Gap Length: ギャップの長さ:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. フラットロゴモードは keepColors を使いません。logoColors で指定したカラー、または検出したカラーをトレースします。
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). 何もトレースされませんでした。トレースで検出したカラーのどれも keepColors ({_1}) に一致しません。
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. 何もトレースされませんでした。「カラーを無視」が keepColors に指定したカラーの領域をすべて除外します。
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: トレースで検出したカラーのどれも {c} に一致しないため、このカラーは何もトレースされません。
|
||||
Artboard {n} of {total} アートボード {n} / {total}
|
||||
File {n} of {total} ファイル {n} / {total}
|
||||
Encoding and writing the file… ファイルをエンコードして書き込み中…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5225,6 +5225,10 @@ imageTrace Outline კონტური
|
||||
@msg Save writes {_1}, not {_2}: use file.saveAsTemplate to write it „შენახვა“ წერს ფორმატს {_1} და არა {_2}: ამისთვის გამოიყენეთ file.saveAsTemplate
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. გამოსახულება არის {_1} × {_2} პიქსელი, ანუ ერთ მხარეზე {LARGE_TRACE_SIDE}-ზე მეტი: ის ვექტორიზდება, მაგრამ უფრო ნელა. ნაკლები სიზუსტის პრესეტი ან გამოსახულების უფრო პატარა ასლი უფრო სწრაფად ვექტორიზდება.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). გამოსახულება ვექტორიზდა {_1} × {_2} პიქსელზე, შემცირდა {_3} × {_4}-დან (მაქსიმუმ {_5} მეგაპიქსელი).
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. ბრტყელი ლოგოს რეჟიმი keepColors-ს არ იყენებს: ის ვექტორიზებს logoColors-ში მითითებულ ფერებს ან მის მიერ ნაპოვნ ფერებს.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). არაფერი ვექტორიზდა: ვექტორიზაციის მიერ ნაპოვნი არცერთი ფერი არ შეესაბამება keepColors-ს ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. არაფერი ვექტორიზდა: ფერის იგნორირება გამოტოვებს keepColors-ში ჩამოთვლილი ფერების ყველა არეს.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: ვექტორიზაციის მიერ ნაპოვნი არცერთი ფერი არ შეესაბამება {c}-ს, ამიტომ მისგან არაფერი ვექტორიზდება.
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` ბიბლიოთეკის პანელი არ არის (იხ. window.swatchLibrary)
|
||||
@msg `{key}` must be a #rrggbb color `{key}` უნდა იყოს #rrggbb ფერი
|
||||
@msg a key object sits on that point ამ წერტილზე საკვანძო ობიექტი მდებარეობს
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4961,6 +4961,10 @@ lighting Light 광원
|
||||
Snap to Perpendicular 수직선에 스냅
|
||||
@msg unknown snap option `{key}` (use {options}) 알 수 없는 스냅 옵션 `{key}` ({options} 중에서 사용하세요)
|
||||
Gap Length: 간격 길이:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. 단색 로고 모드는 keepColors를 사용하지 않습니다. logoColors에 지정한 색상 또는 찾은 색상을 추적합니다.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). 아무것도 추적하지 않았습니다. 추적에서 찾은 색상 중 keepColors({_1})와 일치하는 색상이 없습니다.
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. 아무것도 추적하지 않았습니다. 색상 무시가 keepColors에 나열된 색상의 모든 영역을 제외합니다.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: 추적에서 찾은 색상 중 {c}와 일치하는 색상이 없어 이 색상은 추적하지 않습니다.
|
||||
Artboard {n} of {total} 아트보드 {n} / {total}
|
||||
File {n} of {total} 파일 {n} / {total}
|
||||
Encoding and writing the file… 파일을 인코딩하고 쓰는 중…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5378,6 +5378,10 @@ swatch Bright Violet Felviolet
|
||||
@msg too many library panels were opened in this session er zijn in deze sessie te veel bibliotheekpanelen geopend
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. De afbeelding is {_1} × {_2} pixels, meer dan {LARGE_TRACE_SIDE} aan één zijde: ze wordt getraceerd, maar langzamer. Een voorinstelling met minder detail of een kleinere kopie van de afbeelding traceert sneller.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). De afbeelding is getraceerd op {_1} × {_2} pixels, verkleind van {_3} × {_4} (maximaal {_5} megapixels).
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. De modus Plat logo gebruikt keepColors niet: hij traceert de kleuren die in logoColors staan, of de kleuren die hij vindt.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Er is niets getraceerd: geen van de kleuren die het traceren vond, komt overeen met keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Er is niets getraceerd: Kleur negeren laat elk gebied van de kleuren in keepColors weg.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: geen van de kleuren die het traceren vond, komt overeen met {c}, dus daarvan wordt niets getraceerd.
|
||||
Artboard {n} of {total} Tekengebied {n} van {total}
|
||||
File {n} of {total} Bestand {n} van {total}
|
||||
Encoding and writing the file… Bestand coderen en schrijven…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5237,6 +5237,10 @@ mark-style Japanese Japońskie
|
||||
Snap to Perpendicular Przyciągaj do prostopadłych
|
||||
@msg unknown snap option `{key}` (use {options}) nieznana opcja przyciągania `{key}` (użyj: {options})
|
||||
Gap Length: Długość przerwy:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Tryb Płaskie logo nie używa keepColors: obrysowuje kolory podane w logoColors lub kolory, które znajdzie.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Nic nie zostało obrysowane: żaden z kolorów znalezionych podczas obrysowania nie pasuje do keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Nic nie zostało obrysowane: Ignoruj kolor pomija każdy obszar kolorów wymienionych w keepColors.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: żaden z kolorów znalezionych podczas obrysowania nie pasuje do {c}, więc nic z niego nie jest obrysowywane.
|
||||
Artboard {n} of {total} Obszar kompozycji {n} z {total}
|
||||
File {n} of {total} Plik {n} z {total}
|
||||
Encoding and writing the file… Kodowanie i zapisywanie pliku…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5302,6 +5302,10 @@ mark-style Japanese Japonesas
|
||||
Snap to Perpendicular Ajustar à Perpendicular
|
||||
@msg unknown snap option `{key}` (use {options}) opção de ajuste desconhecida `{key}` (use {options})
|
||||
Gap Length: Comprimento da Lacuna:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. O modo Logotipo Plano não usa keepColors: ele traça as cores indicadas em logoColors ou as cores que encontra.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Nada foi traçado: nenhuma das cores que o traçado encontrou corresponde a keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Nada foi traçado: Ignorar Cor deixa de fora todas as áreas das cores listadas em keepColors.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: nenhuma das cores que o traçado encontrou corresponde a {c}, então nada dela é traçado.
|
||||
Artboard {n} of {total} Mesa de Trabalho {n} de {total}
|
||||
File {n} of {total} Arquivo {n} de {total}
|
||||
Encoding and writing the file… Codificando e gravando o arquivo…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -4994,6 +4994,10 @@ lighting Light Свет
|
||||
Snap to Perpendicular Привязать к перпендикуляру
|
||||
@msg unknown snap option `{key}` (use {options}) неизвестный параметр привязки `{key}` (допустимо: {options})
|
||||
Gap Length: Длина зазора:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Режим «Плоский логотип» не использует keepColors: он трассирует цвета, указанные в logoColors, или найденные им цвета.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Ничего не трассировано: ни один из найденных при трассировке цветов не соответствует keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Ничего не трассировано: «Игнорировать цвет» исключает все области цветов, перечисленных в keepColors.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: ни один из найденных при трассировке цветов не соответствует {c}, поэтому из него ничего не трассируется.
|
||||
Artboard {n} of {total} Монтажная область {n} из {total}
|
||||
File {n} of {total} Файл {n} из {total}
|
||||
Encoding and writing the file… Кодирование и запись файла…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5341,6 +5341,10 @@ theme Appearance Utseende
|
||||
Snap to Perpendicular Fäst mot vinkelrät
|
||||
@msg unknown snap option `{key}` (use {options}) okänt fästalternativ `{key}` (använd {options})
|
||||
Gap Length: Lucklängd:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Läget Platt logotyp använder inte keepColors: det vektoriserar färgerna som anges i logoColors eller färgerna det hittar.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Ingenting vektoriserades: ingen av färgerna som vektoriseringen hittade motsvarar keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Ingenting vektoriserades: Ignorera färg utelämnar alla områden med färgerna som keepColors anger.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: ingen av färgerna som vektoriseringen hittade motsvarar {c}, så ingenting av den vektoriseras.
|
||||
Artboard {n} of {total} Rityta {n} av {total}
|
||||
File {n} of {total} Fil {n} av {total}
|
||||
Encoding and writing the file… Kodar och skriver filen…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -1390,6 +1390,40 @@ fn width(p: &Value, cmd: &str, key: &str) -> Result<f64> {
|
||||
assert_eq!(c.message("`width` must be a number").map(|m| m.1), Some(vec![("key", "width")]));
|
||||
}
|
||||
|
||||
/// The warnings of an Image Trace with keepColors, which the status bar shows and the scan above
|
||||
/// doesn't read, are translated in each language of [`COMPLETE_MESSAGES`], with the colors kept.
|
||||
#[test]
|
||||
fn the_keep_colors_trace_warnings_are_translated() {
|
||||
use serde_json::json;
|
||||
let mut s = vectorcraft_engine::Session::new();
|
||||
s.execute("file.new", &json!({"width": 100, "height": 100})).unwrap();
|
||||
// A white field with a black square in it.
|
||||
let img = image::RgbaImage::from_fn(40, 40, |x, y| {
|
||||
image::Rgba(if (10..30).contains(&x) && (10..30).contains(&y) { [0, 0, 0, 255] } else { [255, 255, 255, 255] })
|
||||
});
|
||||
let mut png = vec![];
|
||||
img.write_to(&mut std::io::Cursor::new(&mut png), image::ImageFormat::Png).unwrap();
|
||||
let data = vectorcraft_format::base64_encode(&png);
|
||||
let mut warnings = vec![];
|
||||
for (params, shown) in [
|
||||
(json!({"mode": "color", "palette": "limited", "colors": 2, "keepColors": ["#ff00ff", "#00ffff"]}), "#ff00ff, #00ffff"),
|
||||
(json!({"mode": "color", "palette": "limited", "colors": 2, "keepColors": ["#000000", "#00ffff"]}), "#00ffff"),
|
||||
(json!({"mode": "color", "palette": "limited", "colors": 2, "keepColors": ["#000000"], "ignoreWhite": true, "ignoreColor": "#000000"}), ""),
|
||||
(json!({"mode": "logo", "keepColors": ["#000000"]}), ""),
|
||||
] {
|
||||
s.execute("file.place", &json!({"name": "square.png", "dataBase64": data, "link": false})).unwrap();
|
||||
let r = s.execute("imageTrace.makeAndExpand", &json!({ "params": params })).unwrap();
|
||||
let w = r["warnings"].as_array().and_then(|w| w.first()).and_then(|w| w.as_str()).unwrap_or_else(|| panic!("{params}: {r}"));
|
||||
warnings.push((w.to_string(), shown));
|
||||
}
|
||||
for (warning, shown) in &warnings {
|
||||
for code in COMPLETE_MESSAGES {
|
||||
let tr = message(Lang::from_code(code).unwrap(), warning);
|
||||
assert!(tr != *warning && tr.contains(shown) && tr.contains("keepColors"), "{code}: {tr}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The parameter errors of the blend spine commands (Move Spine Point, Reshape Spine Segment, Add
|
||||
/// Spine Point and Delete Spine Point, which Direct Selection, the Pen and the Anchor Point tool
|
||||
/// send) say what is wrong.
|
||||
|
||||
@@ -5379,6 +5379,10 @@ theme Appearance Görünüm
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. Görüntü {_1} × {_2} piksel, bir kenarı {LARGE_TRACE_SIDE} değerinden büyük: izlenir, ancak daha yavaş. Daha düşük doğruluklu bir ön ayar veya görüntünün daha küçük bir kopyası daha hızlı izlenir.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). Görüntü {_3} × {_4} boyutundan küçültülerek {_1} × {_2} pikselde izlendi (en fazla {_5} megapiksel).
|
||||
Gap Length: Boşluk Uzunluğu:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Düz Logo modu keepColors kullanmaz: logoColors içinde adı verilen renkleri veya bulduğu renkleri izler.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Hiçbir şey izlenmedi: izlemenin bulduğu renklerin hiçbiri keepColors ({_1}) ile eşleşmiyor.
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Hiçbir şey izlenmedi: Rengi Yoksay, keepColors içinde listelenen renklerin tüm alanlarını dışarıda bırakıyor.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: izlemenin bulduğu renklerin hiçbiri {c} ile eşleşmiyor, bu yüzden bu renkten hiçbir şey izlenmiyor.
|
||||
@plural {n} more export waiting|{n} more exports waiting {n} dışa aktarma daha bekliyor|{n} dışa aktarma daha bekliyor
|
||||
@msg Export cancelled Dışa aktarma iptal edildi
|
||||
Add filters from the list above Yukarıdaki listeden filtre ekleyin
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -4978,6 +4978,10 @@ lighting Light Світло
|
||||
Snap to Perpendicular Прив’язати до перпендикуляра
|
||||
@msg unknown snap option `{key}` (use {options}) невідомий параметр прив’язки `{key}` (використовуйте {options})
|
||||
Gap Length: Довжина проміжку:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Режим «Плоский логотип» не використовує keepColors: він трасує кольори, вказані в logoColors, або знайдені ним кольори.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Нічого не трасовано: жоден із кольорів, знайдених під час трасування, не відповідає keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Нічого не трасовано: «Ігнорувати колір» пропускає всі області кольорів, перелічених у keepColors.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: жоден із кольорів, знайдених під час трасування, не відповідає {c}, тому з нього нічого не трасується.
|
||||
Artboard {n} of {total} Монтажна область {n} з {total}
|
||||
File {n} of {total} Файл {n} з {total}
|
||||
Encoding and writing the file… Кодування та запис файлу…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 747 and column 40.
|
@@ -4978,6 +4978,10 @@ theme Appearance Giao diện
|
||||
Snap to Perpendicular Hút vào đường vuông góc
|
||||
@msg unknown snap option `{key}` (use {options}) tùy chọn hút không hợp lệ `{key}` (dùng {options})
|
||||
Gap Length: Độ dài khoảng hở:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. Chế độ Logo phẳng không dùng keepColors: chế độ này dò các màu được nêu trong logoColors hoặc các màu nó tìm thấy.
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). Không có gì được dò: không màu nào mà quá trình dò tìm thấy khớp với keepColors ({_1}).
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. Không có gì được dò: Bỏ qua màu bỏ đi mọi vùng của các màu mà keepColors liệt kê.
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors: không màu nào mà quá trình dò tìm thấy khớp với {c}, nên không có gì của màu đó được dò.
|
||||
Artboard {n} of {total} Bảng vẽ {n} / {total}
|
||||
File {n} of {total} Tệp {n} / {total}
|
||||
Encoding and writing the file… Đang mã hóa và ghi tệp…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 4051 and column 10.
|
@@ -5217,6 +5217,10 @@ lighting Light 光源
|
||||
Snap to Perpendicular 对齐垂线
|
||||
@msg unknown snap option `{key}` (use {options}) 未知的对齐选项 `{key}`(可用:{options})
|
||||
Gap Length: 间隙长度:
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. “扁平徽标”模式不使用 keepColors:它描摹 logoColors 中指定的颜色,或它找到的颜色。
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). 未描摹任何内容:描摹找到的颜色中没有一种与 keepColors ({_1}) 匹配。
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. 未描摹任何内容:“忽略颜色”排除了 keepColors 所列颜色的所有区域。
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors:描摹找到的颜色中没有一种与 {c} 匹配,因此该颜色未被描摹。
|
||||
# Links and Attributes: files and URLs handed to other apps.
|
||||
@msg Edit Original opens image and document files only; “{name}” is not one 编辑原稿只能打开图像和文档文件;“{name}” 不是其中之一
|
||||
@msg only http, https and mailto URLs open in the browser, not “{url}” 浏览器中只会打开 http、https 和 mailto 的 URL,不会打开 “{url}”
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2364,6 +2364,10 @@ file-filter Templates 範本
|
||||
@msg too many library panels were opened in this session 本次工作階段開啟的資料庫面板過多
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. 影像為 {_1} × {_2} 像素,有一邊超過 {LARGE_TRACE_SIDE}:仍會描圖,但速度較慢。使用精確度較低的預設集或較小的影像拷貝,描圖會較快。
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). 影像已以 {_1} × {_2} 像素描圖,由 {_3} × {_4} 縮小而來 (最多 {_5} 百萬像素)。
|
||||
@msg Flat Logo mode does not use keepColors: it traces the colors named in logoColors, or the colors it finds. 「扁平標誌」模式不使用 keepColors:它會描圖 logoColors 中指定的顏色,或它找到的顏色。
|
||||
@msg Nothing was traced: none of the colors the trace found matches keepColors ({_1}). 未描圖任何內容:描圖找到的顏色中沒有一種與 keepColors ({_1}) 相符。
|
||||
@msg Nothing was traced: Ignore Color leaves out every area of the colors keepColors lists. 未描圖任何內容:「忽略顏色」排除了 keepColors 所列顏色的所有區域。
|
||||
@msg keepColors: none of the colors the trace found matches {c}, so nothing of it is traced. keepColors:描圖找到的顏色中沒有一種與 {c} 相符,因此該顏色未被描圖。
|
||||
# Links and Attributes: files and URLs handed to other apps.
|
||||
@msg Edit Original opens image and document files only; “{name}” is not one 「編輯原稿」只能開啟影像與文件檔案;「{name}」不屬於這兩類
|
||||
@msg only http, https and mailto URLs open in the browser, not “{url}” 只有 http、https 和 mailto URL 會在瀏覽器中開啟,「{url}」不會
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -32,6 +32,19 @@ white beside a cream), at most six; scattered specks of a colour add none. Adobe
|
||||
its own palettes are chosen; this is VectorCraft's own method (see
|
||||
[image-trace-quality.md](image-trace-quality.md#auto-color-keeps-rare-colours)).
|
||||
|
||||
**Keep Colors.** `"keepColors": ["#rrggbb", …]` in the params of `imageTrace.make` or
|
||||
`imageTrace.makeAndExpand` traces only the palette colors within about 30 levels of a listed color,
|
||||
the distance Ignore Color matches by, and leaves the other colors out. With Method Abutting, the paths
|
||||
of the kept colors are the same as in a trace of every color. With Method Overlapping, a kept color's
|
||||
paths reach under the kept colors above it in the stack and not under the colors left out, as with
|
||||
Ignore Color. An empty list traces every color, and a value that is not a six-digit hex color is
|
||||
refused. With Ignore Color as well, a kept color that Ignore Color matches is still left out. Flat
|
||||
Logo does not use `keepColors`: it traces the colors named in `logoColors`, or the colors it finds.
|
||||
The reply's `warnings` name each listed color that matches none of the colors the trace found. When
|
||||
nothing is traced because no listed color matches, or because Ignore Color leaves out every area of
|
||||
the ones that match, the first warning says so, and the status bar shows it. In Flat Logo mode the
|
||||
warning says that `keepColors` is not used.
|
||||
|
||||
**Large images.** An image of more than 1500 pixels on a side is traced as any other, only more
|
||||
slowly, and the trace says so: `imageTrace.make` returns the note in `warnings` and the status bar
|
||||
shows it (the [results optimization](https://helpx.adobe.com/illustrator/using/image-trace-results-optimization.html)
|
||||
|
||||
+2
-1
@@ -1447,7 +1447,8 @@ already walks Image Trace. Short agent entry points:
|
||||
format's first extension (`png8` gives `.png`, `template` gives `.vctemplate`). A step without `format` keeps the
|
||||
source file's extension (`.vectorcraft` over data sets).
|
||||
- Image Trace: `imageTrace.presets`, `imageTrace.make {id?, preset?, params?, view?}` (or `imageTrace.makeAndExpand`),
|
||||
`imageTrace.setView`, `imageTrace.expand`, `imageTrace.release`.
|
||||
`imageTrace.setView`, `imageTrace.expand`, `imageTrace.release`. With `keepColors` in `params`, the reply's
|
||||
`warnings` name each listed color that no traced color matches, and say when nothing was traced.
|
||||
- Live Paint: `livePaint.make`, `livePaint.merge`, `livePaint.fill {group?, point}`, `livePaint.strokeEdge`,
|
||||
`livePaint.info {group}`, `livePaint.release`, `livePaint.expand`, and `livePaint.gapOptions {ids?, detect?, size?,
|
||||
color?, closeGaps?}` (Object › Live Paint › Gap Options). With `detect: true`, paint stops at the gaps that run
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user