mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Image Trace: Flat Logo says when it traces a large image at a reduced size
Flat Logo traces a copy of the image at most 1024 pixels on a side, averaged down by a whole factor, so a 1025-pixel image is traced at 513 pixels. The trace's warnings did not say so, because they compared the image only with the decoded raster. For an image over 1500 pixels they said instead that it is traced more slowly, which Flat Logo does not do. The trace result now carries Flat Logo's working size when it averaged the image down. imageTrace.make and imageTrace.makeAndExpand then name both sizes in their warnings, and the status bar shows that note, in place of the slower-trace and megapixel notes. Other modes keep their warnings. The message has a row in each catalog that translates the other Image Trace warnings.
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), 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; Flat Logo names only the size it traced a larger image at)}",
|
||||
has_selection_or_ids,
|
||||
|s, p| trace_make(s, p, false)
|
||||
),
|
||||
@@ -1141,7 +1141,7 @@ 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(c, 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 warnings = trace_warnings((img.width, img.height), (raster.width, raster.height), res.worked_at);
|
||||
// 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;
|
||||
@@ -1217,18 +1217,21 @@ fn trace_make(s: &mut Session, p: &Value, expand: bool) -> Result<Value> {
|
||||
/// Images larger than this on a side are traced, but more slowly: the trace says so.
|
||||
pub const LARGE_TRACE_SIDE: u32 = 1500;
|
||||
|
||||
/// What a trace of an image of `size` pixels, traced at `traced` pixels, tells the user: that a
|
||||
/// large image takes longer (the public documentation's warning for images over 1500 px), and that
|
||||
/// one over the tracer's [`tr::MAX_PIXELS`] was traced scaled down.
|
||||
pub(crate) fn trace_warnings(size: (u32, u32), traced: (u32, u32)) -> Vec<String> {
|
||||
/// What a trace of an image of `size` pixels, traced at `traced` pixels, tells the user: that
|
||||
/// Flat Logo averaged it down to `worked` pixels first, or else that a large image takes longer
|
||||
/// (the public documentation's warning for images over 1500 px) and that one over the tracer's
|
||||
/// [`tr::MAX_PIXELS`] was traced scaled down.
|
||||
pub(crate) fn trace_warnings(size: (u32, u32), traced: (u32, u32), worked: Option<(u32, u32)>) -> Vec<String> {
|
||||
let mut out = vec![];
|
||||
if size.0.max(size.1) > LARGE_TRACE_SIDE {
|
||||
if worked.is_none() && size.0.max(size.1) > LARGE_TRACE_SIDE {
|
||||
out.push(format!(
|
||||
"The image is {} × {} 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.",
|
||||
size.0, size.1
|
||||
));
|
||||
}
|
||||
if u64::from(traced.0) * u64::from(traced.1) < u64::from(size.0) * u64::from(size.1) {
|
||||
if let Some(worked) = worked {
|
||||
out.push(format!("Flat Logo traced the image at {} × {} pixels, averaged down from {} × {}.", worked.0, worked.1, size.0, size.1));
|
||||
} else if u64::from(traced.0) * u64::from(traced.1) < u64::from(size.0) * u64::from(size.1) {
|
||||
out.push(format!(
|
||||
"The image was traced at {} × {} pixels, scaled down from {} × {} ({} megapixels at most).",
|
||||
traced.0,
|
||||
@@ -1314,11 +1317,19 @@ mod trace_limit_tests {
|
||||
|
||||
#[test]
|
||||
fn trace_warnings_name_a_large_or_scaled_down_image() {
|
||||
assert!(trace_warnings((1500, 1500), (1500, 1500)).is_empty());
|
||||
assert_eq!(trace_warnings((1501, 10), (1501, 10)).len(), 1);
|
||||
let w = trace_warnings((16000, 12000), (9459, 7094));
|
||||
assert!(trace_warnings((1500, 1500), (1500, 1500), None).is_empty());
|
||||
assert_eq!(trace_warnings((1501, 10), (1501, 10), None).len(), 1);
|
||||
let w = trace_warnings((16000, 12000), (9459, 7094), None);
|
||||
assert_eq!(w.len(), 2, "{w:?}");
|
||||
assert!(w[0].contains("16000 × 12000") && w[1].contains("9459 × 7094") && w[1].contains("64 megapixels"), "{w:?}");
|
||||
// Flat Logo's own working size is named instead of the megapixel limit.
|
||||
let w = trace_warnings((1025, 1025), (1025, 1025), Some((513, 513)));
|
||||
assert_eq!(w, ["Flat Logo traced the image at 513 × 513 pixels, averaged down from 1025 × 1025."]);
|
||||
// Flat Logo traces a large image at its reduced size, so it gives no slow-trace warning.
|
||||
let w = trace_warnings((1600, 1600), (1600, 1600), Some((800, 800)));
|
||||
assert_eq!(w, ["Flat Logo traced the image at 800 × 800 pixels, averaged down from 1600 × 1600."]);
|
||||
let w = trace_warnings((16000, 12000), (9459, 7094), Some((946, 710)));
|
||||
assert_eq!(w, ["Flat Logo traced the image at 946 × 710 pixels, averaged down from 16000 × 12000."]);
|
||||
}
|
||||
|
||||
// A 4000 × 3000 photo at High Fidelity Photo makes about 1.9 million anchors, which must fit;
|
||||
|
||||
@@ -2069,6 +2069,36 @@ fn a_large_image_traces_with_a_warning() {
|
||||
assert_eq!(s.execute("imageTrace.make", &json!({})).unwrap()["warnings"], json!([]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flat_logo_says_when_it_traces_an_image_averaged_down() {
|
||||
// Flat Logo works at most 1024 px on a side: a 1025 px image is averaged down to 513 px.
|
||||
let params = json!({"params": {"mode": "logo", "logoColors": ["#000000", "#F0F0DC"]}});
|
||||
let warnings = |n: u32| {
|
||||
let art = vectorcraft_trace::Raster::from_fn(n, n, |x, y| {
|
||||
if !(50..n - 50).contains(&x) || !(50..n - 50).contains(&y) {
|
||||
[0, 0, 0, 0]
|
||||
} else if (i64::from(x) - i64::from(y) / 8).rem_euclid(40) < 2 {
|
||||
[0, 0, 0, 255]
|
||||
} else {
|
||||
[240, 240, 220, 255]
|
||||
}
|
||||
});
|
||||
let mut s = session();
|
||||
add_image(&mut s, &art, Affine::IDENTITY);
|
||||
let r = s.execute("imageTrace.makeAndExpand", ¶ms).unwrap();
|
||||
assert!(r["paths"].as_u64().unwrap() > 0, "{r}");
|
||||
r["warnings"].clone()
|
||||
};
|
||||
let w = warnings(1025);
|
||||
let w = w.as_array().unwrap();
|
||||
assert_eq!(w.len(), 1, "{w:?}");
|
||||
let text = w[0].as_str().unwrap();
|
||||
assert!(text.contains("513 × 513") && text.contains("1025 × 1025"), "{text}");
|
||||
assert_eq!(warnings(1024), json!([]));
|
||||
// Over 1500 px, Flat Logo still traces at its reduced size: no slow-trace warning.
|
||||
assert_eq!(warnings(1600), json!(["Flat Logo traced the image at 800 × 800 pixels, averaged down from 1600 × 1600."]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn image_trace_make_places_paths_over_the_image() {
|
||||
let mut s = session();
|
||||
|
||||
@@ -484,6 +484,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>>,
|
||||
/// Flat Logo: the size in pixels the image was traced at when it was averaged down first;
|
||||
/// `None` when it was traced at its own size.
|
||||
pub worked_at: Option<(u32, u32)>,
|
||||
}
|
||||
|
||||
impl TraceResult {
|
||||
|
||||
@@ -472,7 +472,7 @@ pub(crate) fn trace_logo(img: &Raster, params: &TraceParams, max_anchors: usize)
|
||||
// Painter's order: biggest shapes first, so smaller ones sit on top of what they belong to.
|
||||
shapes.sort_by(|a, b| b.area.total_cmp(&a.area).then(a.class.cmp(&b.class)));
|
||||
let to_source = ToSource { factor: factor as f64, work: (w, h), source: (w0, h0) };
|
||||
let mut out = TraceResult::default();
|
||||
let mut out = TraceResult { worked_at: (factor > 1).then_some((w as u32, h as u32)), ..TraceResult::default() };
|
||||
for s in shapes {
|
||||
let color = palette.get(s.class).copied().unwrap_or([255, 255, 255]);
|
||||
let mut subs: Vec<SubPath> = Vec::new();
|
||||
|
||||
@@ -219,6 +219,31 @@ fn a_large_image_is_traced_at_reduced_size_and_scaled_back() {
|
||||
}
|
||||
}
|
||||
|
||||
/// A light square inset 50 px with slanted 2 px black lines across it, on a transparent background.
|
||||
fn lined_square(n: u32) -> Raster {
|
||||
Raster::from_fn(n, n, |x, y| {
|
||||
if !(50..n - 50).contains(&x) || !(50..n - 50).contains(&y) {
|
||||
[0, 0, 0, 0]
|
||||
} else if (i64::from(x) - i64::from(y) / 8).rem_euclid(40) < 2 {
|
||||
[0, 0, 0, 255]
|
||||
} else {
|
||||
[240, 240, 220, 255]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_trace_averaged_down_says_the_size_it_worked_at() {
|
||||
let named = TraceParams { logo_colors: vec!["#000000".into(), "#F0F0DC".into()], ..logo_params() };
|
||||
// 1025 px is over the working size: averaged down by 2, to 513 px.
|
||||
let res = trace(&lined_square(1025), &named);
|
||||
assert!(!res.paths.is_empty());
|
||||
assert_eq!(res.worked_at, Some((513, 513)));
|
||||
let res = trace(&lined_square(1024), &named);
|
||||
assert!(!res.paths.is_empty());
|
||||
assert_eq!(res.worked_at, None);
|
||||
}
|
||||
|
||||
/// Every anchor of every path is finite and inside (a small margin around) the image.
|
||||
fn assert_sane(res: &TraceResult, w: u32, h: u32) {
|
||||
for t in &res.paths {
|
||||
|
||||
@@ -5397,6 +5397,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Režim Ploché logo vektorizoval obraz v rozlišení {_1} × {_2} pixelů, zmenšený průměrováním z {_3} × {_4}.
|
||||
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.
|
@@ -4976,6 +4976,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Der Modus „Flaches Logo“ hat das Bild mit {_1} × {_2} Pixeln nachgezeichnet, durch Mittelung verkleinert von {_3} × {_4}.
|
||||
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.
|
@@ -5349,6 +5349,7 @@ effect Points Σημεία
|
||||
Snap to Perpendicular Προσκόλληση σε κάθετο
|
||||
@msg unknown snap option `{key}` (use {options}) άγνωστη επιλογή προσκόλλησης `{key}` (χρησιμοποιήστε {options})
|
||||
Gap Length: Μήκος κενού:
|
||||
@msg Flat Logo traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Η λειτουργία Επίπεδο λογότυπο ανίχνευσε την εικόνα σε {_1} × {_2} εικονοστοιχεία, σμικρυμένη με μέσο όρο από {_3} × {_4}.
|
||||
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 2069 and column 19.
|
@@ -5339,6 +5339,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. El modo Logotipo plano calcó la imagen a {_1} × {_2} píxeles, reducida promediando desde {_3} × {_4}.
|
||||
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.
|
@@ -5361,6 +5361,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Tasainen logo -tila jäljitti kuvan kokoon {_1} × {_2} kuvapistettä keskiarvoistamalla pienennettynä koosta {_3} × {_4}.
|
||||
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.
|
@@ -5396,6 +5396,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Le mode Logo en aplats a vectorisé l’image à {_1} × {_2} pixels, réduite par moyennage de {_3} × {_4}.
|
||||
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.
|
@@ -5383,6 +5383,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Az Egyszínű logó mód {_1} × {_2} képponton vektorizálta a képet, {_3} × {_4} méretről átlagolással kicsinyítve.
|
||||
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.
|
@@ -5010,6 +5010,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. La modalità Logo piatto ha vettorializzato l’immagine a {_1} × {_2} pixel, ridotta per media da {_3} × {_4}.
|
||||
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.
|
@@ -5050,6 +5050,7 @@ lighting Light ライト
|
||||
Snap to Perpendicular 垂線にスナップ
|
||||
@msg unknown snap option `{key}` (use {options}) 不明なスナップオプション `{key}` ({options} を使用してください)
|
||||
Gap Length: ギャップの長さ:
|
||||
@msg Flat Logo traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. フラットロゴモードは画像を {_3} × {_4} から平均化して縮小した {_1} × {_2} ピクセルでトレースしました。
|
||||
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.
|
@@ -5237,6 +5237,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. ბრტყელი ლოგოს რეჟიმში გამოსახულება ვექტორიზდა {_1} × {_2} პიქსელზე, საშუალოს გამოთვლით შემცირდა {_3} × {_4}-დან.
|
||||
@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.
|
@@ -4973,6 +4973,7 @@ lighting Light 광원
|
||||
Snap to Perpendicular 수직선에 스냅
|
||||
@msg unknown snap option `{key}` (use {options}) 알 수 없는 스냅 옵션 `{key}` ({options} 중에서 사용하세요)
|
||||
Gap Length: 간격 길이:
|
||||
@msg Flat Logo traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. 단색 로고 모드에서 이미지를 {_3} × {_4}에서 평균을 내어 축소한 {_1} × {_2}픽셀로 추적했습니다.
|
||||
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.
|
@@ -5382,6 +5382,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. De modus Plat logo heeft de afbeelding getraceerd op {_1} × {_2} pixels, door middeling verkleind van {_3} × {_4}.
|
||||
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.
|
@@ -5249,6 +5249,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Tryb Płaskie logo obrysował obraz w rozdzielczości {_1} × {_2} pikseli, po zmniejszeniu przez uśrednienie z {_3} × {_4}.
|
||||
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.
|
@@ -5314,6 +5314,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. O modo Logotipo Plano traçou a imagem em {_1} × {_2} pixels, reduzida por média de {_3} × {_4}.
|
||||
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.
|
@@ -5006,6 +5006,7 @@ lighting Light Свет
|
||||
Snap to Perpendicular Привязать к перпендикуляру
|
||||
@msg unknown snap option `{key}` (use {options}) неизвестный параметр привязки `{key}` (допустимо: {options})
|
||||
Gap Length: Длина зазора:
|
||||
@msg Flat Logo traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Режим «Плоский логотип» трассировал изображение в размере {_1} × {_2} пикселей, уменьшенное усреднением с {_3} × {_4}.
|
||||
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.
|
@@ -5353,6 +5353,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Läget Platt logotyp vektoriserade bilden vid {_1} × {_2} pixlar, nedskalad genom medelvärdesbildning från {_3} × {_4}.
|
||||
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.
|
@@ -5391,6 +5391,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Düz Logo modu görüntüyü {_3} × {_4} boyutundan ortalama alarak küçültüp {_1} × {_2} pikselde izledi.
|
||||
@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.
|
@@ -4990,6 +4990,7 @@ lighting Light Світло
|
||||
Snap to Perpendicular Прив’язати до перпендикуляра
|
||||
@msg unknown snap option `{key}` (use {options}) невідомий параметр прив’язки `{key}` (використовуйте {options})
|
||||
Gap Length: Довжина проміжку:
|
||||
@msg Flat Logo traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Режим «Плоский логотип» трасував зображення в розмірі {_1} × {_2} пікселів, зменшене усередненням з {_3} × {_4}.
|
||||
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 749 and column 40.
|
@@ -4990,6 +4990,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. Chế độ Logo phẳng đã dò ảnh ở {_1} × {_2} điểm ảnh, thu nhỏ bằng cách lấy trung bình từ {_3} × {_4}.
|
||||
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 4054 and column 10.
|
@@ -5229,6 +5229,7 @@ lighting Light 光源
|
||||
Snap to Perpendicular 对齐垂线
|
||||
@msg unknown snap option `{key}` (use {options}) 未知的对齐选项 `{key}`(可用:{options})
|
||||
Gap Length: 间隙长度:
|
||||
@msg Flat Logo traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. “扁平徽标”模式已按 {_1} × {_2} 像素描摹图像,由 {_3} × {_4} 平均缩小而来。
|
||||
# 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.
|
@@ -2373,6 +2373,7 @@ 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 traced the image at {_1} × {_2} pixels, averaged down from {_3} × {_4}. 「扁平標誌」模式已以 {_1} × {_2} 像素描圖,由 {_3} × {_4} 平均縮小而來。
|
||||
# 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.
|
@@ -590,6 +590,20 @@ mod tests {
|
||||
assert!(app.ui.status.contains("1601 × 12") && app.ui.status.contains("more slowly"), "{}", app.ui.status);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_large_image_traced_as_a_flat_logo_shows_the_size_it_was_traced_at() {
|
||||
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default());
|
||||
app.session.execute("file.new", &json!({"width": 100, "height": 100})).unwrap();
|
||||
let img = image::RgbaImage::from_fn(1602, 1602, |x, _| image::Rgba(if x < 800 { [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);
|
||||
app.run("file.place", json!({"name": "logo.png", "dataBase64": data, "link": false})).unwrap();
|
||||
trace_with(&mut app, "Flat Logo");
|
||||
assert!(target(&app).2.is_some(), "the image is traced: {}", app.ui.status);
|
||||
assert_eq!(app.ui.status, "Flat Logo traced the image at 801 × 801 pixels, averaged down from 1602 × 1602.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sketch_quick_trace_reveals_all_adjustments_and_keeps_the_source() {
|
||||
let mut app = traced_app();
|
||||
|
||||
@@ -36,7 +36,10 @@ its own palettes are chosen; this is VectorCraft's own method (see
|
||||
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)
|
||||
page describes the same warning for images over 1500 px). An image of more than 64 megapixels (up to
|
||||
192) is traced from a copy scaled down to 64 megapixels, and the trace says that too. A trace that would
|
||||
192) is traced from a copy scaled down to 64 megapixels, and the trace says that too. Flat Logo traces an
|
||||
image at most 1024 pixels on a side: a larger image is averaged down by a whole factor first (a 1025-pixel
|
||||
image is traced at 513), and the trace names both sizes in `warnings`. Flat Logo gives that note in place
|
||||
of the slower-trace note for an image over 1500 pixels and in place of the 64-megapixel note. A trace that would
|
||||
make more than 8,000,000 anchor points (2,000,000 on the web) is refused to protect memory, with advice:
|
||||
raise Noise, lower Paths or Colors, or pick a lower-fidelity preset. A trace keeps
|
||||
about 90 bytes an anchor; a 4000 × 3000 photo at High Fidelity Photo makes about 1.9 million.
|
||||
|
||||
@@ -57,7 +57,8 @@ nothing changes: 14, 72, 199 and 98 colours, the same paths, anchors and rendere
|
||||
|
||||
|
||||
## Large images
|
||||
Images over 1500 px on a side are traced with a warning that they trace more slowly (see
|
||||
Images over 1500 px on a side are traced with a warning that they trace more slowly (Flat Logo names
|
||||
the size it traced at instead; see
|
||||
[image-trace-adjustments.md](image-trace-adjustments.md)), and the anchor limit that guards memory is
|
||||
8,000,000 (2,000,000 on the web) instead of 2,000,000. Measured through `imageTrace.make` (release
|
||||
build, 4 cores, one trace at a time; memory is the peak allocated above the placed image, and what the
|
||||
|
||||
@@ -792,6 +792,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- **Image Trace, Auto Color rare colours:** the Automatic palette keeps colours too rare for its area count when they are distinct (Oklab) and drawn as coherent regions, at most six, protected from mixed-colour merging and Noise; code-drawn stem, highlight, low-contrast and scattered-noise tests (see [quality notes](image-trace-quality.md#auto-color-keeps-rare-colours)).
|
||||
- **Image Trace, source image on hold:** while the eye button next to the Image Trace panel's View is held down, the canvas shows the selected Image Trace objects' source image whatever their View, and shows their View again on release, with no change to the document or the undo history.
|
||||
- **Image Trace, large images:** images over 1500 px on a side trace with a warning in the result and the status bar; the anchor limit is 8,000,000 (2,000,000 on the web), measured at about 90 bytes an anchor (see [quality notes](image-trace-quality.md#large-images)).
|
||||
- **Image Trace, Flat Logo working size:** Flat Logo traces at most 1024 px on a side; a larger image is averaged down by a whole factor first, and the trace's `warnings` name the size it was traced at and the image's own size, in place of the slower-trace and 64-megapixel notes; code-drawn 1024 and 1025 px tests in `crates/trace` and `crates/engine`.
|
||||
- **Image Trace, Preview:** the Image Trace panel's Preview checkbox, before Trace, is on by default, and a setting change traces the selected Image Trace object again at once. Off, changes wait in the panel until Trace applies them as one undo step, or until Preview is turned on again. Preview is kept with the UI preferences, and Reset to Default leaves it.
|
||||
- **Image Trace small contours:** closed fits too small to form an editable subpath retain their positioned outline, including holes. Source-generated island, hole/winding and stepped-region regressions cover Corners and Noise; defaults, parity scores and estimates are unchanged.
|
||||
- **Create Strokes baseline (2026-10-17, measured):** the ignored centre-lines class covers 23 exact code-drawn scenes in aa and hard variants, including junctions, crossings, fills meeting strokes and varying widths. [Baseline and metric definitions](image-trace-quality.md#centre-lines). Topology is recovered from emitted geometry; width-profile metrics remain unavailable. No behaviour change or score increase.
|
||||
|
||||
Reference in New Issue
Block a user