File size: 3,733 Bytes
4a121a0
18a4938
 
 
 
a6a908a
f66d864
 
1b43408
 
 
4a121a0
1b43408
 
 
f66d864
 
 
 
a8aa56e
f66d864
 
 
 
 
 
 
 
 
 
 
 
 
a1bff88
 
 
f66d864
 
 
 
 
 
 
 
a8aa56e
a1bff88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f66d864
 
 
 
a1bff88
f66d864
a8aa56e
f66d864
 
 
07efcb2
 
a1bff88
07efcb2
 
 
 
f66d864
a1bff88
 
 
 
07efcb2
 
f66d864
 
a1bff88
f66d864
 
 
 
a1bff88
f66d864
 
07efcb2
f66d864
 
 
 
 
 
07efcb2
f66d864
 
 
a1bff88
f66d864
 
a1bff88
f66d864
07efcb2
 
 
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
import cairosvg
import gradio as gr
from PIL import Image
import os
import xml.etree.ElementTree as ET

def initial_render(svg_file):
    """Render SVG at a large size for preview and cropping."""
    if svg_file is None:
        return None, None
    
    # Read the SVG content
    with open(svg_file.name, 'rb') as f:
        svg_content = f.read()
    
    # Store SVG content in a temporary file for later use
    temp_svg_path = "./temp.svg"
    with open(temp_svg_path, 'wb') as f:
        f.write(svg_content)
    
    # Initial large render
    output_path = "./initial_preview.png"
    cairosvg.svg2png(
        bytestring=svg_content,
        write_to=output_path,
        output_width=3000,  # Large initial size to capture all content
        output_height=3000
    )
    
    # Load the preview image
    preview_image = Image.open(output_path)
    return preview_image, temp_svg_path

def final_convert(svg_path, crop_box, size_input):
    """Convert SVG to PNG using either crop box or user-specified dimensions."""
    if svg_path is None:
        return None, None
    
    # Read the stored SVG content
    with open(svg_path, 'rb') as f:
        svg_content = f.read()
    
    # Final output path
    output_path = "./final_output.png"
    
    # Determine output dimensions
    if size_input and size_input.strip():  # Check if size input is provided
        try:
            width, height = map(int, size_input.split('x'))
            if width <= 0 or height <= 0:
                raise ValueError("Width and height must be positive")
        except ValueError:
            return gr.Warning("Invalid size format. Use 'width x height' (e.g., '800x600')"), None
    elif crop_box and 'left' in crop_box:  # Use crop box if size input is empty
        left = crop_box['left']
        top = crop_box['top']
        width = crop_box['right'] - left
        height = crop_box['bottom'] - top
    else:
        # Fallback if neither is provided (shouldn't happen with UI flow)
        width, height = 2000, 2000
    
    # Convert SVG to PNG with determined dimensions
    cairosvg.svg2png(
        bytestring=svg_content,
        write_to=output_path,
        output_width=width,
        output_height=height
    )
    
    # Load the final PNG
    final_image = Image.open(output_path)
    return final_image, output_path

with gr.Blocks() as bl:
    gr.Markdown("# SVG to PNG Converter with Custom Crop or Size")
    
    with gr.Row():
        with gr.Column():
            svg_input = gr.File(label="Upload SVG File", file_types=[".svg"])
            preview_btn = gr.Button("Generate Preview")
            size_input = gr.Textbox(
                label="Output Size (width x height)",
                placeholder="e.g., 800x600 (optional, overrides crop)"
            )
        
        with gr.Column():
            preview_output = gr.Image(
                type='pil',
                label="Preview (Draw a box to crop if no size specified)",
                interactive=True,
                tool="sketch",
                height=800
            )
            crop_btn = gr.Button("Convert")
            final_output = gr.Image(type='pil', label="Final PNG", height=800)
            download_btn = gr.File(label="Download Final PNG")
    
    # State to store the temporary SVG path
    svg_state = gr.State()
    
    # Step 1: Generate initial preview
    preview_btn.click(
        fn=initial_render,
        inputs=svg_input,
        outputs=[preview_output, svg_state]
    )
    
    # Step 2: Convert using crop box or specified size
    crop_btn.click(
        fn=final_convert,
        inputs=[svg_state, preview_output, size_input],
        outputs=[final_output, download_btn]
    )

bl.launch()