pub mod bezier_fitter;
pub mod edge_detector;
pub mod enhanced_quantizer;
pub mod enhanced_vectorizer;
pub mod image_filters;
pub mod image_processor;
pub mod path_simplifier;
pub mod preprocessor;
pub mod region_extractor;
pub mod svg_generator;
pub mod vectorizer;
pub use anyhow::Result;
pub use enhanced_vectorizer::{
generate_enhanced_svg, vectorize_enhanced, write_enhanced_svg, EnhancedOptions, EnhancedPath,
EnhancedVectorData,
};
pub use image_filters::{
median_filter, prewitt_edge_detection, roberts_edge_detection, weighted_median_filter,
AdaptiveThreshold, AdaptiveToneMapper, CannyEdgeDetector, ColorOps, ColorTemperature,
EmbossFilter, GammaCorrection, HighBoostFilter, HistogramEqualizer, LaplacianSharpen,
MorphologyKind, MorphologyOp, OtsuThreshold, Saturation, SepiaFilter, UnsharpMask,
VignetteFilter, VintageFilter, CLAHE, HSL, LAB,
};
pub use image_processor::{load_image, quantize_colors, ImageData};
pub use preprocessor::{preprocess, PreprocessOptions};
pub use svg_generator::{generate_svg, generate_svg_advanced};
pub use vectorizer::{vectorize, Curve, Point, VectorizedData};
#[derive(Debug, Clone)]
pub struct ConversionOptions {
pub num_colors: usize,
pub threshold: f64,
pub smooth_level: u8,
pub hierarchical: bool,
pub advanced: bool,
}
impl Default for ConversionOptions {
fn default() -> Self {
Self {
num_colors: 16,
threshold: 0.1,
smooth_level: 5,
hierarchical: false,
advanced: false,
}
}
}
pub fn convert(
input_path: &std::path::Path,
output_path: &std::path::Path,
options: &ConversionOptions,
) -> Result<()> {
let image_data = load_image(input_path)?;
let vectorized_data = vectorize(
&image_data,
options.num_colors,
options.threshold,
options.smooth_level,
options.hierarchical,
)?;
if options.advanced {
generate_svg_advanced(&vectorized_data, output_path)?;
} else {
generate_svg(&vectorized_data, output_path)?;
}
Ok(())
}
pub fn convert_to_svg_string(
image_data: &ImageData,
options: &ConversionOptions,
) -> Result<String> {
let vectorized_data = vectorize(
image_data,
options.num_colors,
options.threshold,
options.smooth_level,
options.hierarchical,
)?;
use std::io::Write;
let mut buffer = Vec::new();
let (bg_str, bg_opacity) = svg_generator::color_with_alpha(vectorized_data.background_color);
writeln!(
&mut buffer,
r#"<svg width="{}" height="{}" viewBox="0 0 {} {}" xmlns="http://www.w3.org/2000/svg">"#,
vectorized_data.width,
vectorized_data.height,
vectorized_data.width,
vectorized_data.height
)?;
writeln!(
&mut buffer,
r#" <rect width="{}" height="{}" fill="{}"{}/>"#,
vectorized_data.width, vectorized_data.height, bg_str, bg_opacity
)?;
for curve in &vectorized_data.curves {
let (color_str, opacity_attr) = svg_generator::color_with_alpha(curve.color);
let path_str = if !curve.subpaths.is_empty() {
svg_generator::create_multi_path_string(&curve.subpaths)
} else if !curve.points.is_empty() {
svg_generator::create_subpath_string(&curve.points, curve.is_closed)
} else {
continue;
};
if path_str.is_empty() {
continue;
}
writeln!(
&mut buffer,
r#" <path d="{}" fill="{}"{} stroke="none"/>"#,
path_str, color_str, opacity_attr
)?;
}
writeln!(&mut buffer, "</svg>")?;
Ok(String::from_utf8(buffer)?)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_conversion_options_default() {
let options = ConversionOptions::default();
assert_eq!(options.num_colors, 16);
assert_eq!(options.threshold, 0.1);
assert_eq!(options.smooth_level, 5);
assert!(!options.hierarchical);
assert!(!options.advanced);
}
}