Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import vtracer | |
| import os | |
| import tempfile | |
| def image_to_svg(image, colormode, hierarchical, filter_speckle, color_precision, layer_difference, mode, corner_threshold, length_threshold, splice_threshold, path_precision): | |
| """ | |
| Converts an input image to an SVG string using vtracer. | |
| This function is triggered automatically when any of the input controls change. | |
| """ | |
| if image is None: | |
| # A clear startup state before an image is uploaded. | |
| return None, "Upload an image to see the SVG preview and code.", None | |
| input_path = image | |
| # Create a persistent temporary file that Gradio can access after the function returns. | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".svg", mode='w', encoding='utf-8') as temp_output_file: | |
| output_path = temp_output_file.name | |
| try: | |
| # vtracer conversion call with all parameters from the UI | |
| vtracer.convert_image_to_svg_py( | |
| input_path, | |
| output_path, | |
| colormode=colormode.lower(), | |
| hierarchical=hierarchical.lower(), | |
| mode=mode.lower(), | |
| filter_speckle=int(filter_speckle), | |
| color_precision=int(color_precision), | |
| layer_difference=int(layer_difference), | |
| corner_threshold=int(corner_threshold), | |
| length_threshold=float(length_threshold), | |
| splice_threshold=int(splice_threshold), | |
| path_precision=int(path_precision), | |
| max_iterations=10 # A reasonable default | |
| ) | |
| # Read the generated SVG content to display in the code block | |
| with open(output_path, "r", encoding='utf-8') as f: | |
| svg_content = f.read() | |
| # Return the path for the file download, the SVG code, and the path for the image preview. | |
| return output_path, svg_content, output_path | |
| except Exception as e: | |
| # Handle potential errors during conversion and display them | |
| error_message = f"An error occurred during conversion: {str(e)}" | |
| return None, error_message, None | |
| # --- Gradio User Interface --- | |
| with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue")) as demo: | |
| # --- Top Row: Upload and Project Info --- | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| image_input = gr.Image(type="filepath", label="Upload Your Image", sources=["upload", "clipboard"]) | |
| with gr.Column(scale=2): | |
| gr.Markdown( | |
| """ | |
| # IMG2SVG: Real-time SVG Converter | |
| This application converts raster images (like JPG, PNG) into clean, scalable vector graphics (SVG) using the powerful `vtracer` library. | |
| **How to use:** | |
| 1. Upload an image. | |
| 2. Adjust the settings in the control panel below. | |
| 3. The SVG preview will update automatically. | |
| """ | |
| ) | |
| # --- Bottom Row: Controls and Output --- | |
| with gr.Row(variant="panel"): | |
| # ----- Control Panel Column ----- | |
| with gr.Column(scale=1): | |
| gr.Markdown("### Control Panel") | |
| with gr.Group(): | |
| gr.Markdown("#### Clustering") | |
| colormode = gr.Radio(["Color", "B/W"], value="Color", label="Color Mode") | |
| hierarchical = gr.Radio(["Stacked", "Cutout"], value="Stacked", label="Hierarchical Mode") | |
| filter_speckle = gr.Slider(0, 128, value=4, step=1, label="Filter Speckle (Cleaner)") | |
| color_precision = gr.Slider(0, 8, value=6, step=1, label="Color Precision (More accurate)") | |
| layer_difference = gr.Slider(0, 128, value=16, step=1, label="Gradient Step (Less layers)") | |
| with gr.Group(): | |
| gr.Markdown("#### Curve Fitting") | |
| mode = gr.Radio(["Spline", "Polygon", "Pixel"], value="Spline", label="Mode") | |
| corner_threshold = gr.Slider(0, 180, value=60, step=1, label="Corner Threshold (Smoother)") | |
| length_threshold = gr.Slider(0, 10, value=4.0, step=0.5, label="Segment Length (More coarse)") | |
| splice_threshold = gr.Slider(0, 180, value=45, step=1, label="Splice Threshold (Less accurate)") | |
| path_precision = gr.Slider(1, 8, value=3, step=1, label="Path Precision") | |
| # ----- Output Column ----- | |
| with gr.Column(scale=2): | |
| gr.Markdown("### Result") | |
| with gr.Tabs(): | |
| with gr.TabItem("SVG Preview"): | |
| svg_image_output = gr.Image(label="Live SVG Preview", interactive=False) | |
| with gr.TabItem("SVG Code"): | |
| svg_text_output = gr.Code(label="Generated SVG Code", language="html", interactive=False) | |
| svg_file_output = gr.File(label="Download SVG") | |
| # --- Event Handling for Live Update --- | |
| # A list of all the input controls that should trigger a re-render. | |
| controls = [ | |
| image_input, colormode, hierarchical, filter_speckle, color_precision, | |
| layer_difference, mode, corner_threshold, length_threshold, splice_threshold, path_precision | |
| ] | |
| # A list of all the components that will display the output. | |
| outputs = [svg_file_output, svg_text_output, svg_image_output] | |
| # This loop attaches an event listener to every control. | |
| # The 'debounce' parameter is crucial for performance. It waits for 0.5s of inactivity | |
| # before triggering the conversion, ensuring it doesn't run excessively while a slider is being dragged. | |
| for component in controls: | |
| component.change(fn=image_to_svg, inputs=controls, outputs=outputs, debounce=0.5) | |
| # To launch the application | |
| demo.launch() |