outline/vectorizer/
vtracer.rs1use image::GrayImage;
2use visioncortex::PathSimplifyMode;
3use vtracer::{ColorImage, ColorMode, Config, Hierarchical, SvgFile, convert};
4
5use crate::mask::gray_to_color_image_rgba;
6use crate::{OutlineError, OutlineResult};
7
8use super::MaskVectorizer;
9
10#[derive(Debug, Clone)]
14pub struct TraceOptions {
15 pub tracer_color_mode: ColorMode,
16 pub tracer_hierarchical: Hierarchical,
17 pub tracer_mode: PathSimplifyMode,
18 pub tracer_filter_speckle: usize,
19 pub tracer_color_precision: i32,
20 pub tracer_layer_difference: i32,
21 pub tracer_corner_threshold: i32,
22 pub tracer_length_threshold: f64,
23 pub tracer_max_iterations: usize,
24 pub tracer_splice_threshold: i32,
25 pub tracer_path_precision: Option<u32>,
26 pub invert_svg: bool,
27}
28
29impl Default for TraceOptions {
30 fn default() -> Self {
31 Self {
32 tracer_color_mode: ColorMode::Binary,
33 tracer_hierarchical: Hierarchical::Stacked,
34 tracer_mode: PathSimplifyMode::Spline,
35 tracer_filter_speckle: 4,
36 tracer_color_precision: 6,
37 tracer_layer_difference: 16,
38 tracer_corner_threshold: 60,
39 tracer_length_threshold: 4.0,
40 tracer_max_iterations: 10,
41 tracer_splice_threshold: 45,
42 tracer_path_precision: Some(2),
43 invert_svg: false,
44 }
45 }
46}
47
48#[derive(Debug, Clone, Copy, Default)]
53pub struct VtracerSvgVectorizer;
54
55impl MaskVectorizer for VtracerSvgVectorizer {
56 type Options = TraceOptions;
57 type Output = String;
58
59 fn vectorize(&self, mask: &GrayImage, options: &Self::Options) -> OutlineResult<Self::Output> {
60 trace_to_svg_string(mask, options)
61 }
62}
63
64pub fn trace_to_svg_string(
66 mask_image: &GrayImage,
67 options: &TraceOptions,
68) -> OutlineResult<String> {
69 let color_img = gray_to_color_image_rgba(mask_image, None, options.invert_svg);
70 let svg_file = trace(color_img, options)?;
71 Ok(svg_file.to_string())
72}
73
74pub fn trace(img: ColorImage, options: &TraceOptions) -> OutlineResult<SvgFile> {
76 let cfg = Config {
77 color_mode: options.tracer_color_mode.clone(),
78 hierarchical: options.tracer_hierarchical.clone(),
79 mode: options.tracer_mode,
80 filter_speckle: options.tracer_filter_speckle,
81 color_precision: options.tracer_color_precision,
82 layer_difference: options.tracer_layer_difference,
83 corner_threshold: options.tracer_corner_threshold,
84 length_threshold: options.tracer_length_threshold,
85 max_iterations: options.tracer_max_iterations,
86 splice_threshold: options.tracer_splice_threshold,
87 path_precision: options.tracer_path_precision,
88 };
89
90 let svg_file = convert(img, cfg).map_err(OutlineError::Trace)?;
91 Ok(svg_file)
92}