mirror of
https://github.com/visioncortex/vtracer.git
synced 2025-12-07 09:36:09 -08:00
Relative & compound path
This commit is contained in:
@@ -13,4 +13,4 @@ keywords = ["svg", "computer-graphics"]
|
||||
[dependencies]
|
||||
clap = "2.33.3"
|
||||
image = "0.23.10"
|
||||
visioncortex = "0.2.0"
|
||||
visioncortex = "0.3.0"
|
||||
@@ -42,7 +42,7 @@ fn color_image_to_svg(config: ConverterConfig) -> Result<(), String> {
|
||||
let mut svg = SvgFile::new(width, height);
|
||||
for &cluster_index in view.clusters_output.iter().rev() {
|
||||
let cluster = view.get_cluster(cluster_index);
|
||||
let svg_path = cluster.to_svg_path(
|
||||
let paths = cluster.to_compound_path(
|
||||
&view,
|
||||
false,
|
||||
config.mode,
|
||||
@@ -51,22 +51,14 @@ fn color_image_to_svg(config: ConverterConfig) -> Result<(), String> {
|
||||
config.max_iterations,
|
||||
config.splice_threshold
|
||||
);
|
||||
svg.add_path(svg_path, cluster.residue_color());
|
||||
svg.add_path(paths, cluster.residue_color());
|
||||
}
|
||||
|
||||
let out_file = File::create(config.output_path);
|
||||
let mut out_file = match out_file {
|
||||
Ok(file) => file,
|
||||
Err(_) => return Err(String::from("Cannot create output file.")),
|
||||
};
|
||||
|
||||
out_file.write_all(&svg.to_svg_file().as_bytes()).unwrap();
|
||||
|
||||
Ok(())
|
||||
write_svg(svg, config.output_path)
|
||||
}
|
||||
|
||||
fn binary_image_to_svg(config: ConverterConfig) -> Result<(), String> {
|
||||
|
||||
|
||||
let (img, width, height);
|
||||
match read_image(config.input_path) {
|
||||
Ok(values) => {
|
||||
@@ -79,20 +71,19 @@ fn binary_image_to_svg(config: ConverterConfig) -> Result<(), String> {
|
||||
let img = img.to_binary_image(|x| x.r < 128);
|
||||
|
||||
let clusters = img.to_clusters(false);
|
||||
|
||||
|
||||
let mut svg = SvgFile::new(width, height);
|
||||
for i in 0..clusters.len() {
|
||||
let cluster = clusters.get_cluster(i);
|
||||
if cluster.size() >= config.filter_speckle_area {
|
||||
let svg_path = cluster.to_svg_path(
|
||||
let paths = cluster.to_compound_path(
|
||||
config.mode,
|
||||
config.corner_threshold,
|
||||
config.length_threshold,
|
||||
config.max_iterations,
|
||||
config.splice_threshold,
|
||||
);
|
||||
let color = Color::color(&ColorName::Black);
|
||||
svg.add_path(svg_path, color);
|
||||
svg.add_path(paths, Color::color(&ColorName::Black));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,8 +109,8 @@ fn write_svg(svg: SvgFile, output_path: PathBuf) -> Result<(), String> {
|
||||
Ok(file) => file,
|
||||
Err(_) => return Err(String::from("Cannot create output file.")),
|
||||
};
|
||||
|
||||
out_file.write_all(&svg.to_svg_file().as_bytes()).unwrap();
|
||||
|
||||
write!(&mut out_file, "{}", svg).expect("failed to write file.");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,42 +1,57 @@
|
||||
use visioncortex::Color;
|
||||
|
||||
pub struct SvgPath {
|
||||
path: String,
|
||||
color: Color,
|
||||
}
|
||||
use std::fmt;
|
||||
use visioncortex::{Color, CompoundPath, PointF64};
|
||||
|
||||
pub struct SvgFile {
|
||||
patches: Vec<SvgPath>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
pub paths: Vec<SvgPath>,
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
}
|
||||
|
||||
pub struct SvgPath {
|
||||
pub path: CompoundPath,
|
||||
pub color: Color,
|
||||
}
|
||||
|
||||
impl SvgFile {
|
||||
pub fn new(width: usize, height: usize) -> Self {
|
||||
SvgFile {
|
||||
patches: vec![],
|
||||
paths: vec![],
|
||||
width,
|
||||
height,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_path(&mut self, path: String, color: Color) {
|
||||
self.patches.push(SvgPath {
|
||||
pub fn add_path(&mut self, path: CompoundPath, color: Color) {
|
||||
self.paths.push(SvgPath {
|
||||
path,
|
||||
color
|
||||
color,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_svg_file(&self) -> String {
|
||||
let mut result: Vec<String> = vec![format!(r#"<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="{}" height="{}">"#, self.width, self.height)];
|
||||
impl fmt::Display for SvgFile {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, r#"<?xml version="1.0" encoding="UTF-8"?>"#)?;
|
||||
writeln!(f,
|
||||
r#"<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="{}" height="{}">"#,
|
||||
self.width, self.height
|
||||
)?;
|
||||
|
||||
for patch in &self.patches {
|
||||
let color = patch.color;
|
||||
result.push(format!("<path d=\"{}\" fill=\"#{:02x}{:02x}{:02x}\"/>\n", patch.path, color.r, color.g, color.b));
|
||||
for path in &self.paths {
|
||||
path.fmt(f)?;
|
||||
};
|
||||
|
||||
result.push(String::from("</svg>"));
|
||||
result.concat()
|
||||
writeln!(f, "</svg>")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for SvgPath {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let (string, offset) = self.path.to_svg_string(true, PointF64::default());
|
||||
writeln!(
|
||||
f, "<path d=\"{}\" fill=\"{}\" transform=\"translate({},{})\"/>",
|
||||
string, self.color.to_hex_string(),
|
||||
offset.x, offset.y
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user