Alibrown commited on
Commit
2a4cc69
·
verified ·
1 Parent(s): bb06cc3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +133 -67
app.py CHANGED
@@ -4,31 +4,65 @@ from PIL import Image
4
  import vtracer
5
  import tempfile
6
 
7
- # Localization dictionary
8
  TRANSLATIONS = {
9
  'en': {
10
- 'title': 'Convert Image to SVG Vectors',
11
- 'description': 'Upload an image and customize the conversion parameters as needed.'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  },
13
  'de': {
14
- 'title': 'Bild in SVG-Vektoren umwandeln',
15
- 'description': 'Laden Sie ein Bild hoch und passen Sie die Konvertierungsparameter nach Bedarf an.'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  }
17
  }
18
 
19
- def convert_image(image, color_mode, hierarchical, mode, filter_speckle,
20
- color_precision, layer_difference, corner_threshold,
21
- length_threshold, max_iterations, splice_threshold, path_precision, language):
22
  """Converts an image to SVG using vtracer with customizable parameters."""
23
- # Convert Gradio image to bytes for vtracer compatibility
 
 
24
  img_byte_array = io.BytesIO()
25
  image.save(img_byte_array, format='PNG')
26
  img_bytes = img_byte_array.getvalue()
27
 
28
- # Perform the conversion
29
  svg_str = vtracer.convert_raw_image_to_svg(
30
- img_bytes,
31
- img_format='png',
32
  colormode=color_mode.lower(),
33
  hierarchical=hierarchical.lower(),
34
  mode=mode.lower(),
@@ -42,75 +76,107 @@ def convert_image(image, color_mode, hierarchical, mode, filter_speckle,
42
  path_precision=int(path_precision)
43
  )
44
 
45
- # Save the SVG string to a temporary file
46
- temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.svg')
47
- temp_file.write(svg_str.encode('utf-8'))
48
  temp_file.close()
 
 
 
49
 
50
- return (
51
- gr.HTML(f'<svg viewBox="0 0 {image.width} {image.height}">{svg_str}</svg>'),
52
- temp_file.name
53
- )
54
 
55
- # Gradio interface
56
- vector_converter_interface = gr.Blocks()
 
 
57
 
58
- with vector_converter_interface:
59
  language_dropdown = gr.Dropdown(
60
- choices=['en', 'de'],
61
- value='en',
62
- label='Language'
 
63
  )
64
-
65
- # FULL REWRITE START (1/2 allowed)
66
- title_component = gr.Markdown(TRANSLATIONS['en']['title'])
67
- description_component = gr.Markdown(TRANSLATIONS['en']['description'])
68
 
 
 
 
69
  with gr.Row():
70
- image_input = gr.Image(type="pil", label="Upload Image")
71
- with gr.Row():
72
- with gr.Column():
73
- color_mode = gr.Radio(choices=["Color", "Binary"], value="Color", label="Color Mode")
74
- hierarchical = gr.Radio(choices=["Stacked", "Cutout"], value="Stacked", label="Hierarchical")
75
- mode = gr.Radio(choices=["Spline", "Polygon", "None"], value="Spline", label="Mode")
76
- filter_speckle = gr.Slider(minimum=1, maximum=10, value=4, step=1, label="Filter Speckle")
77
- color_precision = gr.Slider(minimum=1, maximum=8, value=6, step=1, label="Color Precision")
78
- with gr.Column():
79
- layer_difference = gr.Slider(minimum=1, maximum=32, value=16, step=1, label="Layer Difference")
80
- corner_threshold = gr.Slider(minimum=10, maximum=90, value=60, step=1, label="Corner Threshold")
81
- length_threshold = gr.Slider(minimum=3.5, maximum=10, value=4.0, step=0.5, label="Length Threshold")
82
- max_iterations = gr.Slider(minimum=1, maximum=20, value=10, step=1, label="Max Iterations")
83
- splice_threshold = gr.Slider(minimum=10, maximum=90, value=45, step=1, label="Splice Threshold")
84
- path_precision = gr.Slider(minimum=1, maximum=10, value=8, step=1, label="Path Precision")
85
-
86
- convert_btn = gr.Button("Convert")
87
-
88
- svg_output = gr.HTML(label="SVG Output")
89
- file_output = gr.File(label="Download SVG")
90
-
91
- convert_btn.click(
92
- convert_image,
93
- inputs=[
94
- image_input, color_mode, hierarchical, mode, filter_speckle,
95
- color_precision, layer_difference, corner_threshold,
96
- length_threshold, max_iterations, splice_threshold, path_precision, language_dropdown
97
- ],
98
- outputs=[svg_output, file_output]
99
- )
100
- # FULL REWRITE END
101
 
102
- # HALF-LINE CHANGE 1/2 (gr.Textbox gr.Markdown)
103
  def update_language(language):
 
104
  return {
105
- title_component: TRANSLATIONS[language]['title'],
106
- description_component: TRANSLATIONS[language]['description']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  }
108
 
109
- # HALF-LINE CHANGE 2/2 (removed invisible textboxes)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  language_dropdown.change(
111
- update_language,
112
- inputs=language_dropdown,
113
- outputs=[title_component, description_component]
114
  )
115
 
116
  vector_converter_interface.launch()
 
4
  import vtracer
5
  import tempfile
6
 
7
+ # --- 1. Erweitertes Wörterbuch für die komplette Übersetzung ---
8
  TRANSLATIONS = {
9
  'en': {
10
+ 'title': '# Convert Image to SVG Vectors',
11
+ 'description': 'Upload an image and customize the conversion parameters. Click "Convert" to start.',
12
+ 'lang_label': 'Language',
13
+ 'image_label': 'Upload Image',
14
+ 'advanced_label': 'Advanced Settings',
15
+ 'color_mode_label': 'Color Mode',
16
+ 'hierarchical_label': 'Hierarchical',
17
+ 'mode_label': 'Mode',
18
+ 'filter_speckle_label': 'Filter Speckle',
19
+ 'color_precision_label': 'Color Precision',
20
+ 'layer_difference_label': 'Layer Difference',
21
+ 'corner_threshold_label': 'Corner Threshold',
22
+ 'length_threshold_label': 'Length Threshold',
23
+ 'max_iterations_label': 'Max Iterations',
24
+ 'splice_threshold_label': 'Splice Threshold',
25
+ 'path_precision_label': 'Path Precision',
26
+ 'convert_button': 'Convert',
27
+ 'output_svg_label': 'SVG Output',
28
+ 'download_svg_label': 'Download SVG'
29
  },
30
  'de': {
31
+ 'title': '# Bild in SVG-Vektoren umwandeln',
32
+ 'description': 'Laden Sie ein Bild hoch und passen Sie die Parameter an. Klicken Sie auf "Umwandeln", um zu starten.',
33
+ 'lang_label': 'Sprache',
34
+ 'image_label': 'Bild hochladen',
35
+ 'advanced_label': 'Erweiterte Einstellungen',
36
+ 'color_mode_label': 'Farbmodus',
37
+ 'hierarchical_label': 'Hierarchisch',
38
+ 'mode_label': 'Modus',
39
+ 'filter_speckle_label': 'Flecken filtern',
40
+ 'color_precision_label': 'Farbpräzision',
41
+ 'layer_difference_label': 'Ebenenunterschied',
42
+ 'corner_threshold_label': 'Eckenschwelle',
43
+ 'length_threshold_label': 'Längenschwelle',
44
+ 'max_iterations_label': 'Max. Iterationen',
45
+ 'splice_threshold_label': 'Spleißschwelle',
46
+ 'path_precision_label': 'Pfadpräzision',
47
+ 'convert_button': 'Umwandeln',
48
+ 'output_svg_label': 'SVG-Ausgabe',
49
+ 'download_svg_label': 'SVG herunterladen'
50
  }
51
  }
52
 
53
+ def convert_image(image, color_mode, hierarchical, mode, filter_speckle,
54
+ color_precision, layer_difference, corner_threshold,
55
+ length_threshold, max_iterations, splice_threshold, path_precision):
56
  """Converts an image to SVG using vtracer with customizable parameters."""
57
+ if image is None:
58
+ return None, None
59
+
60
  img_byte_array = io.BytesIO()
61
  image.save(img_byte_array, format='PNG')
62
  img_bytes = img_byte_array.getvalue()
63
 
 
64
  svg_str = vtracer.convert_raw_image_to_svg(
65
+ image_data=img_bytes,
 
66
  colormode=color_mode.lower(),
67
  hierarchical=hierarchical.lower(),
68
  mode=mode.lower(),
 
76
  path_precision=int(path_precision)
77
  )
78
 
79
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.svg', mode='w', encoding='utf-8')
80
+ temp_file.write(svg_str)
 
81
  temp_file.close()
82
+
83
+ # Simple preview, as full SVG rendering can be complex in gr.HTML
84
+ preview_html = f"<div style='background-color:#f0f0f0; padding:10px; border-radius:5px;'>SVG successfully generated. Preview:<br><img src='/file={temp_file.name}' width='300'></div>"
85
 
86
+ return preview_html, temp_file.name
 
 
 
87
 
88
+ # --- 2. Manuelles UI-Layout mit gr.Blocks für volle Kontrolle ---
89
+ with gr.Blocks() as vector_converter_interface:
90
+ # Initial language is 'en'
91
+ lang = 'de'
92
 
 
93
  language_dropdown = gr.Dropdown(
94
+ choices=['en', 'de'],
95
+ value=lang,
96
+ label=TRANSLATIONS[lang]['lang_label'],
97
+ interactive=True
98
  )
 
 
 
 
99
 
100
+ title = gr.Markdown(value=TRANSLATIONS[lang]['title'])
101
+ description = gr.Markdown(value=TRANSLATIONS[lang]['description'])
102
+
103
  with gr.Row():
104
+ with gr.Column(scale=1):
105
+ image_input = gr.Image(type="pil", label=TRANSLATIONS[lang]['image_label'])
106
+
107
+ with gr.Accordion(TRANSLATIONS[lang]['advanced_label'], open=False):
108
+ color_mode_input = gr.Radio(choices=["Color", "Binary"], value="Color", label=TRANSLATIONS[lang]['color_mode_label'])
109
+ hierarchical_input = gr.Radio(choices=["Stacked", "Cutout"], value="Stacked", label=TRANSLATIONS[lang]['hierarchical_label'])
110
+ mode_input = gr.Radio(choices=["Spline", "Polygon", "None"], value="Spline", label=TRANSLATIONS[lang]['mode_label'])
111
+ filter_speckle_input = gr.Slider(minimum=1, maximum=10, value=4, step=1, label=TRANSLATIONS[lang]['filter_speckle_label'])
112
+ color_precision_input = gr.Slider(minimum=1, maximum=8, value=6, step=1, label=TRANSLATIONS[lang]['color_precision_label'])
113
+ layer_difference_input = gr.Slider(minimum=1, maximum=32, value=16, step=1, label=TRANSLATIONS[lang]['layer_difference_label'])
114
+ corner_threshold_input = gr.Slider(minimum=10, maximum=90, value=60, step=1, label=TRANSLATIONS[lang]['corner_threshold_label'])
115
+ length_threshold_input = gr.Slider(minimum=3.5, maximum=10, value=4.0, step=0.5, label=TRANSLATIONS[lang]['length_threshold_label'])
116
+ max_iterations_input = gr.Slider(minimum=1, maximum=20, value=10, step=1, label=TRANSLATIONS[lang]['max_iterations_label'])
117
+ splice_threshold_input = gr.Slider(minimum=10, maximum=90, value=45, step=1, label=TRANSLATIONS[lang]['splice_threshold_label'])
118
+ path_precision_input = gr.Slider(minimum=1, maximum=10, value=8, step=1, label=TRANSLATIONS[lang]['path_precision_label'])
119
+
120
+ convert_button = gr.Button(value=TRANSLATIONS[lang]['convert_button'])
121
+
122
+ with gr.Column(scale=1):
123
+ svg_output = gr.HTML(label=TRANSLATIONS[lang]['output_svg_label'])
124
+ file_output = gr.File(label=TRANSLATIONS[lang]['download_svg_label'])
 
 
 
 
 
 
 
 
 
 
125
 
126
+ # --- 3. Die Update-Funktion, die alle UI-Elemente aktualisiert ---
127
  def update_language(language):
128
+ t = TRANSLATIONS[language]
129
  return {
130
+ language_dropdown: gr.update(label=t['lang_label']),
131
+ title: gr.update(value=t['title']),
132
+ description: gr.update(value=t['description']),
133
+ image_input: gr.update(label=t['image_label']),
134
+ # Python-seitige Komponenten wie das Accordion müssen so aktualisiert werden
135
+ gr.Accordion(label=t['advanced_label']): gr.update(),
136
+ color_mode_input: gr.update(label=t['color_mode_label']),
137
+ hierarchical_input: gr.update(label=t['hierarchical_label']),
138
+ mode_input: gr.update(label=t['mode_label']),
139
+ filter_speckle_input: gr.update(label=t['filter_speckle_label']),
140
+ color_precision_input: gr.update(label=t['color_precision_label']),
141
+ layer_difference_input: gr.update(label=t['layer_difference_label']),
142
+ corner_threshold_input: gr.update(label=t['corner_threshold_label']),
143
+ length_threshold_input: gr.update(label=t['length_threshold_label']),
144
+ max_iterations_input: gr.update(label=t['max_iterations_label']),
145
+ splice_threshold_input: gr.update(label=t['splice_threshold_label']),
146
+ path_precision_input: gr.update(label=t['path_precision_label']),
147
+ convert_button: gr.update(value=t['convert_button']),
148
+ svg_output: gr.update(label=t['output_svg_label']),
149
+ file_output: gr.update(label=t['download_svg_label']),
150
  }
151
 
152
+ # --- 4. Event-Handler verbinden ---
153
+ all_inputs = [
154
+ image_input, color_mode_input, hierarchical_input, mode_input,
155
+ filter_speckle_input, color_precision_input, layer_difference_input,
156
+ corner_threshold_input, length_threshold_input, max_iterations_input,
157
+ splice_threshold_input, path_precision_input
158
+ ]
159
+ all_outputs = [svg_output, file_output]
160
+
161
+ # Konvertierung starten
162
+ convert_button.click(
163
+ fn=convert_image,
164
+ inputs=all_inputs,
165
+ outputs=all_outputs
166
+ )
167
+
168
+ # Sprache ändern
169
+ ui_components_to_update = [
170
+ language_dropdown, title, description, image_input, color_mode_input,
171
+ hierarchical_input, mode_input, filter_speckle_input, color_precision_input,
172
+ layer_difference_input, corner_threshold_input, length_threshold_input,
173
+ max_iterations_input, splice_threshold_input, path_precision_input,
174
+ convert_button, svg_output, file_output
175
+ ]
176
  language_dropdown.change(
177
+ fn=update_language,
178
+ inputs=language_dropdown,
179
+ outputs=ui_components_to_update
180
  )
181
 
182
  vector_converter_interface.launch()