import io
import gradio as gr
from PIL import Image
import vtracer
import tempfile
def convert_image(image, color_mode, hierarchical, mode, filter_speckle,
color_precision, layer_difference, corner_threshold,
length_threshold, max_iterations, splice_threshold, path_precision):
"""Converts an image to SVG using vtracer with customizable parameters."""
# Convert Gradio image to bytes for vtracer compatibility
img_byte_array = io.BytesIO()
image.save(img_byte_array, format='PNG')
img_bytes = img_byte_array.getvalue()
# Perform the conversion
svg_str = vtracer.convert_raw_image_to_svg(
img_bytes,
img_format='png',
colormode=color_mode.lower(),
hierarchical=hierarchical.lower(),
mode=mode.lower(),
filter_speckle=int(filter_speckle),
color_precision=int(color_precision),
layer_difference=int(layer_difference),
corner_threshold=int(corner_threshold),
length_threshold=float(length_threshold),
max_iterations=int(max_iterations),
splice_threshold=int(splice_threshold),
path_precision=int(path_precision)
)
# Save the SVG string to a temporary file
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.svg')
temp_file.write(svg_str.encode('utf-8'))
temp_file.close()
return gr.HTML(f''), temp_file.name
# Estilos: oculta el pie "Built with Gradio" y usa el azul del CRM en el botón principal
css = """
footer { display: none !important; }
button.primary {
background: #159bd8 !important;
border-color: #5bb6d6 !important;
color: #fff !important;
}
button.primary:hover, button.primary:focus, button.primary:active {
background: #147191 !important;
border-color: #159bd8 !important;
}
h1 { font-size: 22px !important; }
.gradio-container { min-height: 0 !important; }
"""
# Embebido en un iframe (app.iagestion.com): avisa a la página padre del alto real del
# contenido para que el iframe crezca y no haya un segundo scroll.
# El scroll propio solo se oculta cuando el padre confirma con 'gradio_alto_ok' que está
# aplicando ese alto; si no hay respuesta, se conserva y nada queda inalcanzable.
head = """
"""
# Las opciones de los Radio son pares (etiqueta, valor): la etiqueta se muestra en castellano
# y el valor es el que espera vtracer.
iface = gr.Interface(
fn=convert_image,
inputs=[
gr.Image(type="pil", label="Subir imagen"),
gr.Radio(choices=[("Color", "Color"), ("Binario", "Binary")], value="Color", label="Modo de color"),
gr.Radio(choices=[("Apilado", "Stacked"), ("Recorte", "Cutout")], value="Stacked", label="Jerarquía"),
gr.Radio(choices=[("Curvas", "Spline"), ("Polígonos", "Polygon"), ("Ninguno", "None")], value="Spline", label="Modo"),
gr.Slider(minimum=1, maximum=10, value=4, step=1, label="Filtro de motas"),
gr.Slider(minimum=1, maximum=8, value=6, step=1, label="Precisión de color"),
gr.Slider(minimum=1, maximum=32, value=16, step=1, label="Diferencia entre capas"),
gr.Slider(minimum=10, maximum=90, value=60, step=1, label="Umbral de esquinas"),
gr.Slider(minimum=3.5, maximum=10, value=4.0, step=0.5, label="Umbral de longitud"),
gr.Slider(minimum=1, maximum=20, value=10, step=1, label="Iteraciones máximas"),
gr.Slider(minimum=10, maximum=90, value=45, step=1, label="Umbral de empalme"),
gr.Slider(minimum=1, maximum=10, value=8, step=1, label="Precisión del trazado")
],
outputs=[
gr.HTML(label="Resultado SVG"),
gr.File(label="Descargar SVG")
],
title="Convertir imagen a vector SVG",
description="Sube una imagen y ajusta los parámetros de conversión según necesites.",
submit_btn="Convertir",
clear_btn="Limpiar",
allow_flagging="never",
css=css,
head=head,
)
iface.launch(show_api=False)