AkashKumarave commited on
Commit
bd2dc2e
·
verified ·
1 Parent(s): d5e944b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -156
app.py CHANGED
@@ -1,179 +1,68 @@
1
  from flask import Flask, request, jsonify
2
  from flask_cors import CORS
3
- import vtracer
4
  from PIL import Image
 
5
  import io
6
  import os
7
- import logging
8
- import base64
9
- import re
10
-
11
- # Set up logging
12
- logging.basicConfig(level=logging.INFO)
13
- logger = logging.getLogger(__name__)
14
 
15
  app = Flask(__name__)
16
- CORS(app, resources={r"/convert": {"origins": ["https://www.figma.com", "*"]}})
17
 
18
- # VTracer conversion function
19
- def convert_to_vector(
20
- image,
21
- colormode="color",
22
- hierarchical="stacked",
23
- mode="spline",
24
- filter_speckle=4,
25
- color_precision=6,
26
- layer_difference=16,
27
- corner_threshold=60,
28
- length_threshold=4.0,
29
- max_iterations=10,
30
- splice_threshold=45,
31
- path_precision=3
32
- ):
33
  input_path = "temp_input.jpg"
34
  output_path = "svg_output.svg"
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  try:
37
- # Save the input image to a temporary file
38
- image.save(input_path)
39
- logger.info(f"Saved image to {input_path}")
40
-
41
- # Convert the image to SVG using VTracer
42
- vtracer.convert_image_to_svg_py(
43
- input_path,
44
- output_path,
45
- colormode=colormode,
46
- hierarchical=hierarchical,
47
- mode=mode,
48
- filter_speckle=int(filter_speckle),
49
- color_precision=int(color_precision),
50
- layer_difference=int(layer_difference),
51
- corner_threshold=int(corner_threshold),
52
- length_threshold=float(length_threshold),
53
- max_iterations=int(max_iterations),
54
- splice_threshold=int(splice_threshold),
55
- path_precision=int(path_precision)
56
- )
57
- logger.info(f"Converted image to SVG at {output_path}")
58
-
59
- # Read the SVG output
60
- with open(output_path, "r") as f:
61
- svg_content = f.read()
62
-
63
- return svg_content
64
- except Exception as e:
65
- logger.error(f"Error in convert_to_vector: {str(e)}")
66
- raise Exception(f"Conversion failed: {str(e)}")
67
- finally:
68
- # Clean up temporary files
69
- for path in [input_path, output_path]:
70
- if os.path.exists(path):
71
- try:
72
- os.remove(path)
73
- logger.info(f"Removed {path}")
74
- except Exception as e:
75
- logger.warning(f"Failed to remove {path}: {str(e)}")
76
-
77
- # Flask endpoint for vector conversion
78
- @app.route('/convert', methods=['POST'])
79
- def convert_image():
80
- try:
81
- # Handle JSON payload
82
- data = request.get_json()
83
- if not data or 'file' not in data:
84
- logger.error("No image data provided in request")
85
  return jsonify({'error': 'No image data provided'}), 400
86
 
87
- # Extract base64 string
88
- base64_string = data['file']
89
- if not base64_string:
90
- logger.error("Empty base64 string")
91
- return jsonify({'error': 'Invalid base64 image data: empty string'}), 400
92
-
93
- # Parse data URL
94
- match = re.match(r'^data:image/(\w+);base64,(.+)$', base64_string)
95
- if not match:
96
- logger.error("Invalid data URL format")
97
- return jsonify({'error': 'Invalid base64 image data: incorrect data URL format'}), 400
98
-
99
- image_format, base64_data = match.groups()
100
- if image_format not in ['jpeg', 'png']:
101
- logger.error(f"Unsupported image format: {image_format}")
102
- return jsonify({'error': f'Invalid base64 image data: unsupported format {image_format}'}), 400
103
-
104
- # Validate base64 string
105
- if not re.match(r'^[A-Za-z0-9+/=]+$', base64_data):
106
- logger.error("Invalid base64 string characters")
107
- return jsonify({'error': 'Invalid base64 image data: contains invalid characters'}), 400
108
-
109
- # Decode base64
110
- try:
111
- image_data = base64.b64decode(base64_data, validate=True)
112
- logger.info(f"Decoded base64 data, length: {len(image_data)}")
113
- except Exception as e:
114
- logger.error(f"Base64 decode failed: {str(e)}")
115
- return jsonify({'error': f'Invalid base64 image data: {str(e)}'}), 400
116
-
117
- # Validate image data
118
- if len(image_data) == 0:
119
- logger.error("Decoded image data is empty")
120
- return jsonify({'error': 'Invalid base64 image data: empty after decoding'}), 400
121
-
122
- # Process image
123
- try:
124
- image = Image.open(io.BytesIO(image_data))
125
- if image_format == 'png':
126
- image = image.convert('RGB') # Convert PNG to RGB for consistency
127
- except Exception as e:
128
- logger.error(f"Image processing failed: {str(e)}")
129
- return jsonify({'error': f'Failed to process image: {str(e)}'}), 400
130
-
131
- # Get parameters (with defaults)
132
- colormode = data.get('colormode', 'color')
133
- hierarchical = data.get('hierarchical', 'stacked')
134
- mode = data.get('mode', 'spline')
135
- try:
136
- filter_speckle = int(data.get('filter_speckle', 4))
137
- color_precision = int(data.get('color_precision', 6))
138
- layer_difference = int(data.get('layer_difference', 16))
139
- corner_threshold = int(data.get('corner_threshold', 60))
140
- length_threshold = float(data.get('length_threshold', 4.0))
141
- max_iterations = int(data.get('max_iterations', 10))
142
- splice_threshold = int(data.get('splice_threshold', 45))
143
- path_precision = int(data.get('path_precision', 3))
144
- except (ValueError, TypeError) as e:
145
- logger.error(f"Invalid parameter format: {str(e)}")
146
- return jsonify({'error': f'Invalid parameter format: {str(e)}'}), 400
147
-
148
- logger.info("Received request to /convert")
149
 
150
- # Convert to SVG
151
- svg_content = convert_to_vector(
152
- image,
153
- colormode=colormode,
154
- hierarchical=hierarchical,
155
- mode=mode,
156
- filter_speckle=filter_speckle,
157
- color_precision=color_precision,
158
- layer_difference=layer_difference,
159
- corner_threshold=corner_threshold,
160
- length_threshold=length_threshold,
161
- max_iterations=max_iterations,
162
- splice_threshold=splice_threshold,
163
- path_precision=path_precision
164
- )
165
 
166
- # Return SVG as JSON
167
- return jsonify({'svg': svg_content})
168
  except Exception as e:
169
- logger.error(f"Error in convert_image: {str(e)}")
170
  return jsonify({'error': str(e)}), 500
171
 
172
- # Health check endpoint
173
  @app.route('/')
174
- def health_check():
175
- logger.info("Health check requested")
176
- return jsonify({'status': 'Image to Vector Converter API is running'})
177
 
178
  if __name__ == '__main__':
179
  app.run(host='0.0.0.0', port=7860)
 
1
  from flask import Flask, request, jsonify
2
  from flask_cors import CORS
 
3
  from PIL import Image
4
+ import vtracer
5
  import io
6
  import os
 
 
 
 
 
 
 
7
 
8
  app = Flask(__name__)
9
+ CORS(app, resources={r"/convert-to-vector": {"origins": "*"}})
10
 
11
+ def convert_to_vector(image, colormode="color", hierarchical="stacked", mode="spline", filter_speckle=4, color_precision=6, layer_difference=16, corner_threshold=60, length_threshold=4.0, max_iterations=10, splice_threshold=45, path_precision=3):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  input_path = "temp_input.jpg"
13
  output_path = "svg_output.svg"
14
 
15
+ # Save the input image to a temporary file
16
+ image.save(input_path)
17
+
18
+ # Convert the image to SVG using VTracer
19
+ vtracer.convert_image_to_svg_py(
20
+ input_path,
21
+ output_path,
22
+ colormode=colormode,
23
+ hierarchical=hierarchical,
24
+ mode=mode,
25
+ filter_speckle=int(filter_speckle),
26
+ color_precision=int(color_precision),
27
+ layer_difference=int(layer_difference),
28
+ corner_threshold=int(corner_threshold),
29
+ length_threshold=float(length_threshold),
30
+ max_iterations=int(max_iterations),
31
+ splice_threshold=int(splice_threshold),
32
+ path_precision=int(path_precision)
33
+ )
34
+
35
+ # Read the SVG output
36
+ with open(output_path, "r") as f:
37
+ svg_content = f.read()
38
+
39
+ # Clean up temporary files
40
+ os.remove(input_path)
41
+ os.remove(output_path)
42
+
43
+ return svg_content
44
+
45
+ @app.route('/convert-to-vector', methods=['POST'])
46
+ def convert_to_vector_endpoint():
47
  try:
48
+ # Handle raw image data in the request body
49
+ if request.data:
50
+ image = Image.open(io.BytesIO(request.data)).convert('RGB')
51
+ else:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  return jsonify({'error': 'No image data provided'}), 400
53
 
54
+ # Process the image
55
+ svg_content = convert_to_vector(image)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
+ # Return the SVG content as plain text
58
+ return svg_content, 200, {'Content-Type': 'text/plain'}
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
 
 
60
  except Exception as e:
 
61
  return jsonify({'error': str(e)}), 500
62
 
 
63
  @app.route('/')
64
+ def index():
65
+ return jsonify({'status': 'Image to Vector API is running'})
 
66
 
67
  if __name__ == '__main__':
68
  app.run(host='0.0.0.0', port=7860)