aaurelions commited on
Commit
07ece8d
·
verified ·
1 Parent(s): 9e835dd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +91 -71
app.py CHANGED
@@ -3,97 +3,117 @@ import vtracer
3
  import os
4
  import tempfile
5
 
6
- def image_to_svg(image, colormode, hierarchical, mode, filter_speckle, color_precision, layer_difference, corner_threshold, length_threshold, max_iterations, splice_threshold, path_precision):
7
  """
8
  Converts an input image to an SVG string using vtracer.
 
9
  """
10
  if image is None:
11
- return None, None
12
 
13
- # Create a temporary directory to store the output file
 
 
 
14
  with tempfile.TemporaryDirectory() as temp_dir:
15
- # Use the uploaded file's original name for the output, but with an .svg extension
16
- base, _ = os.path.splitext(os.path.basename(image.name))
17
- output_filename = f"{base}.svg"
18
  output_path = os.path.join(temp_dir, output_filename)
19
 
20
- # Convert the image with the specified parameters
21
- vtracer.convert_image_to_svg_py(
22
- image.name,
23
- output_path,
24
- colormode=colormode,
25
- hierarchical=hierarchical,
26
- mode=mode,
27
- filter_speckle=int(filter_speckle),
28
- color_precision=int(color_precision),
29
- layer_difference=int(layer_difference),
30
- corner_threshold=int(corner_threshold),
31
- length_threshold=float(length_threshold),
32
- max_iterations=int(max_iterations),
33
- splice_threshold=int(splice_threshold),
34
- path_precision=int(path_precision)
35
- )
 
 
 
 
 
 
 
 
36
 
37
- # Read the content of the generated SVG file
38
- with open(output_path, "r") as f:
39
- svg_content = f.read()
 
40
 
41
- return output_path, svg_content
42
 
43
  # --- Gradio User Interface ---
44
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
45
- gr.Markdown("# IMG2SVG: Image to SVG Converter")
46
- gr.Markdown("Upload your JPG, PNG, or other image file to convert it to a scalable vector graphic (SVG). Adjust the settings below for finer control over the conversion process.")
47
 
48
- with gr.Row():
 
49
  with gr.Column(scale=1):
50
- image_input = gr.Image(type="filepath", label="Upload Image")
51
 
52
- with gr.Accordion("Conversion Settings", open=True):
53
- colormode = gr.Dropdown(["color", "binary"], value="color", label="Color Mode")
54
- hierarchical = gr.Dropdown(["stacked", "cutout"], value="stacked", label="Hierarchical")
55
- mode = gr.Dropdown(["spline", "polygon", "none"], value="spline", label="Mode")
56
- filter_speckle = gr.Slider(0, 16, value=4, step=1, label="Filter Speckle")
57
- color_precision = gr.Slider(0, 8, value=6, step=1, label="Color Precision")
58
- layer_difference = gr.Slider(0, 32, value=16, step=1, label="Layer Difference")
59
- corner_threshold = gr.Slider(0, 180, value=60, step=1, label="Corner Threshold")
60
- length_threshold = gr.Slider(0.0, 10.0, value=4.0, step=0.5, label="Length Threshold")
61
- max_iterations = gr.Slider(1, 20, value=10, step=1, label="Max Iterations")
62
- splice_threshold = gr.Slider(0, 90, value=45, step=1, label="Splice Threshold")
63
- path_precision = gr.Slider(1, 8, value=3, step=1, label="Path Precision")
64
-
65
- convert_button = gr.Button("Convert to SVG", variant="primary")
66
 
 
 
 
 
 
 
 
 
 
67
  with gr.Column(scale=2):
 
 
 
 
 
 
 
68
  svg_file_output = gr.File(label="Download SVG")
69
- svg_text_output = gr.Code(label="SVG Code", language="xml")
70
 
71
- # Connect the button to the conversion function
72
- convert_button.click(
73
- fn=image_to_svg,
74
- inputs=[
75
- image_input,
76
- colormode,
77
- hierarchical,
78
- mode,
79
- filter_speckle,
80
- color_precision,
81
- layer_difference,
82
- corner_threshold,
83
- length_threshold,
84
- max_iterations,
85
- splice_threshold,
86
- path_precision
87
- ],
88
- outputs=[svg_file_output, svg_text_output]
89
- )
90
-
91
- with gr.Accordion("About vtracer", open=False):
92
  gr.Markdown(
93
- "This application uses the `vtracer` library to convert raster images into vector graphics. [1] "
94
- "It offers a powerful alternative to tools like Adobe Illustrator's Image Trace, with a focus on creating compact SVG files. [1] "
95
- "The core of `vtracer` is built in Rust for high performance. [1]"
 
 
 
 
 
 
96
  )
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  # To launch the application
99
- demo.launch()
 
3
  import os
4
  import tempfile
5
 
6
+ def image_to_svg(image, colormode, hierarchical, filter_speckle, color_precision, layer_difference, mode, corner_threshold, length_threshold, splice_threshold, path_precision):
7
  """
8
  Converts an input image to an SVG string using vtracer.
9
+ This function is triggered automatically when any of the input controls change.
10
  """
11
  if image is None:
12
+ return None, "Upload an image to begin.", None
13
 
14
+ # Use a temporary file to handle the image path
15
+ input_path = image.name
16
+
17
+ # Use a temporary directory for the output to ensure a clean file system
18
  with tempfile.TemporaryDirectory() as temp_dir:
19
+ output_filename = f"{os.path.splitext(os.path.basename(input_path))[0]}.svg"
 
 
20
  output_path = os.path.join(temp_dir, output_filename)
21
 
22
+ try:
23
+ # vtracer conversion call with all parameters from the UI
24
+ vtracer.convert_image_to_svg_py(
25
+ input_path,
26
+ output_path,
27
+ colormode=colormode.lower(),
28
+ hierarchical=hierarchical.lower(),
29
+ mode=mode.lower(),
30
+ filter_speckle=int(filter_speckle),
31
+ color_precision=int(color_precision),
32
+ layer_difference=int(layer_difference),
33
+ corner_threshold=int(corner_threshold),
34
+ length_threshold=float(length_threshold),
35
+ splice_threshold=int(splice_threshold),
36
+ path_precision=int(path_precision),
37
+ max_iterations=10 # Default from vtracer docs
38
+ )
39
+
40
+ # Read the generated SVG content to display in the code block
41
+ with open(output_path, "r") as f:
42
+ svg_content = f.read()
43
+
44
+ # Return the path for the file download, the SVG code, and an updated image for display
45
+ return output_path, svg_content, output_path
46
 
47
+ except Exception as e:
48
+ # Handle potential errors during conversion
49
+ error_message = f"An error occurred during conversion: {str(e)}"
50
+ return None, error_message, None
51
 
 
52
 
53
  # --- Gradio User Interface ---
54
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue")) as demo:
55
+ gr.Markdown("# IMG2SVG: Real-time Image to SVG Converter")
56
+ gr.Markdown("Upload an image, then adjust the settings below. The SVG will update automatically.")
57
 
58
+ with gr.Row(variant="panel"):
59
+ # ----- Input Column -----
60
  with gr.Column(scale=1):
61
+ image_input = gr.Image(type="filepath", label="Upload Image", sources=["upload", "clipboard"])
62
 
63
+ with gr.Group():
64
+ gr.Markdown("### Clustering")
65
+ colormode = gr.Radio(["Color", "B/W"], value="Color", label="Color Mode")
66
+ hierarchical = gr.Radio(["Stacked", "Cutout"], value="Stacked", label="Hierarchical Mode")
67
+ filter_speckle = gr.Slider(0, 128, value=4, step=1, label="Filter Speckle (Cleaner)")
68
+ color_precision = gr.Slider(0, 8, value=6, step=1, label="Color Precision (More accurate)")
69
+ layer_difference = gr.Slider(0, 128, value=16, step=1, label="Gradient Step (Less layers)")
 
 
 
 
 
 
 
70
 
71
+ with gr.Group():
72
+ gr.Markdown("### Curve Fitting")
73
+ mode = gr.Radio(["Spline", "Polygon", "Pixel"], value="Spline", label="Mode")
74
+ corner_threshold = gr.Slider(0, 180, value=60, step=1, label="Corner Threshold (Smoother)")
75
+ length_threshold = gr.Slider(0, 10, value=4.0, step=0.5, label="Segment Length (More coarse)")
76
+ splice_threshold = gr.Slider(0, 180, value=45, step=1, label="Splice Threshold (Less accurate)")
77
+ path_precision = gr.Slider(1, 8, value=3, step=1, label="Path Precision")
78
+
79
+ # ----- Output Column -----
80
  with gr.Column(scale=2):
81
+ with gr.Tabs():
82
+ with gr.TabItem("SVG Preview"):
83
+ svg_image_output = gr.Image(label="SVG Preview", interactive=False)
84
+ with gr.TabItem("SVG Code"):
85
+ # The traceback error is fixed here by using 'html' which supports XML syntax highlighting.
86
+ svg_text_output = gr.Code(label="SVG Code", language="html", interactive=False)
87
+
88
  svg_file_output = gr.File(label="Download SVG")
 
89
 
90
+ # ----- Documentation -----
91
+ with gr.Accordion("How VTracer Works (Technical Details)", open=False):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  gr.Markdown(
93
+ """
94
+ This tool uses VTracer to convert raster images (like JPG, PNG) into vector graphics (SVG). The process involves several key stages:
95
+
96
+ 1. **Clustering**: The input image is first analyzed and grouped into clusters of similar colors using Hierarchical Clustering. Each cluster will become a separate shape in the final vector image.
97
+ 2. **Path Walking**: A "walker" algorithm traces the outline of each pixel cluster to create a raw, pixelated path.
98
+ 3. **Path Simplification**: This raw path is then simplified to remove "jaggies" (pixel staircases) and reduce the number of points by replacing sections of the path with straight lines, as long as it doesn't deviate too much from the original shape.
99
+ 4. **Path Smoothing**: To create smooth curves, the simplified polygon is refined using a corner-preserving subdivision algorithm. This adds more points to the path where needed, allowing for better curve generation.
100
+ 5. **Curve Fitting**: Finally, the smoothed path is analyzed to find the best places to "cut" it into segments. Each segment is then approximated with a Bézier curve, resulting in the final, clean SVG output.
101
+ """
102
  )
103
 
104
+ # List of all input controls that should trigger a re-render
105
+ inputs = [
106
+ image_input, colormode, hierarchical, filter_speckle, color_precision,
107
+ layer_difference, mode, corner_threshold, length_threshold, splice_threshold, path_precision
108
+ ]
109
+
110
+ outputs = [svg_file_output, svg_text_output, svg_image_output]
111
+
112
+ # Connect all input controls to the conversion function.
113
+ # The 'debounce' parameter adds a 1-second delay after the user stops changing a value
114
+ # before the function is called, improving performance and user experience.
115
+ for component in inputs:
116
+ component.change(fn=image_to_svg, inputs=inputs, outputs=outputs, every=1)
117
+
118
  # To launch the application
119
+ demo.launch(debug=True)