File size: 4,082 Bytes
4a51a09
713d623
f63ea57
4a51a09
bd3a491
f63ea57
cff54b7
a8a350d
b3f1777
bd3a491
f63ea57
cff54b7
f1c89fe
cff54b7
5320d53
17bf38b
470bbd3
f63ea57
cff54b7
f1c89fe
 
cff54b7
 
f1c89fe
cff54b7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f63ea57
f1c89fe
 
cff54b7
 
f4c1ac5
f1c89fe
cff54b7
f1c89fe
cff54b7
5320d53
f1c89fe
cff54b7
f63ea57
cff54b7
f1c89fe
cff54b7
f1c89fe
 
 
f63ea57
bd3a491
 
4c9a049
f1c89fe
5320d53
cff54b7
17bf38b
 
 
 
 
 
f4c1ac5
cff54b7
f4c1ac5
17bf38b
 
 
 
 
8e448c7
cff54b7
f63ea57
 
17bf38b
 
 
 
 
 
 
 
 
 
f1c89fe
cff54b7
083e606
f63ea57
f1c89fe
cff54b7
f4c1ac5
083e606
 
f4c1ac5
083e606
f4c1ac5
a8a350d
f1c89fe
c956e8d
 
8e448c7
c956e8d
bd3a491
c956e8d
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
from flask import Flask, request, jsonify, send_file
from flask_cors import CORS
from PIL import Image
import vtracer
import io
import os
import logging

app = Flask(__name__)
CORS(app, resources={r"/convert-to-vector": {"origins": "*"}})

# Configure logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

def convert_to_vector(image):
    input_path = "temp_input.png"  # Use .png to support PNG inputs
    output_svg_path = "temp_output.svg"

    try:
        # Save the input image
        app.logger.debug(f"Saving input image to {input_path}")
        image.save(input_path)

        # Convert to SVG using VTracer
        app.logger.debug("Converting image to SVG")
        vtracer.convert_image_to_svg_py(
            input_path,
            output_svg_path,
            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
        )

        # Read the SVG
        app.logger.debug(f"Reading SVG from {output_svg_path}")
        with open(output_svg_path, "r") as f:
            svg_content = f.read()

        # Validate SVG
        if not svg_content.startswith('<?xml') or '<svg' not in svg_content:
            app.logger.error(f"Invalid SVG content: {svg_content[:100]}")
            raise ValueError("Generated SVG is invalid")

        app.logger.debug(f"SVG content length: {len(svg_content)}, first 100 chars: {svg_content[:100]}")
        return svg_content

    finally:
        # Clean up
        app.logger.debug("Cleaning up temporary files")
        for path in [input_path, output_svg_path]:
            if os.path.exists(path):
                os.remove(path)

@app.route('/convert-to-vector', methods=['POST'])
def convert_to_vector_endpoint():
    try:
        # Handle image data
        if request.data:
            app.logger.debug("Received raw image data")
            # Try to open the image without assuming format
            try:
                image = Image.open(io.BytesIO(request.data))
            except Exception as e:
                app.logger.error(f"Failed to open image: {str(e)}")
                return jsonify({'error': f"Invalid image data: {str(e)}"}), 400
        elif 'image' in request.files:
            app.logger.debug("Received multipart image data")
            file = request.files['image']
            try:
                image = Image.open(file)
            except Exception as e:
                app.logger.error(f"Failed to open image: {str(e)}")
                return jsonify({'error': f"Invalid image data: {str(e)}"}), 400
        else:
            app.logger.error("No image data provided")
            return jsonify({'error': 'No image data provided'}), 400

        # Log image format and mode
        app.logger.debug(f"Image format: {image.format}, mode: {image.mode}")

        # Convert to RGB if needed (for vtracer compatibility)
        if image.mode not in ['RGB', 'RGBA']:
            image = image.convert('RGB')
        elif image.mode == 'RGBA':
            # Optionally convert RGBA to RGB to avoid alpha channel issues
            image = image.convert('RGB')

        # Process image
        app.logger.debug("Processing image")
        svg_content = convert_to_vector(image)

        # Return SVG
        app.logger.debug("Sending SVG response")
        return send_file(
            io.BytesIO(svg_content.encode('utf-8')),
            mimetype='image/svg+xml',
            as_attachment=True,
            download_name='vector_output.svg'
        )
    except Exception as e:
        app.logger.error(f"Error processing request: {str(e)}")
        return jsonify({'error': str(e)}), 500

@app.route('/')
def index():
    return jsonify({'status': 'Image to Vector Converter API is running'})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=7860)