streamlit-design-toolkit / pages /1_Cloudinary_AI.py
Wkatir
feat: adding converter
065cb1a
import streamlit as st
import cloudinary
import cloudinary.uploader
import cloudinary.api
import requests
import io
import zipfile
import logging
# Configuración de la página y del logging
st.set_page_config(
page_title="Cloudinary AI Background Generator",
page_icon="🤖",
layout="wide"
)
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def init_cloudinary():
"""
Inicializa Cloudinary utilizando las credenciales definidas en st.secrets.
Registra en session_state si se inicializó correctamente y realiza una limpieza inicial.
"""
if 'cloudinary_initialized' not in st.session_state:
try:
cloudinary.config(url=st.secrets['CLOUDINARY_URL'])
st.session_state.cloudinary_initialized = True
cleanup_cloudinary() # Limpieza de recursos al iniciar
logging.info("Cloudinary inicializado correctamente.")
except Exception as e:
st.error("Error: No se encontraron las credenciales de Cloudinary en secrets.toml")
st.session_state.cloudinary_initialized = False
logging.error(f"Error al inicializar Cloudinary: {e}")
def check_file_size(file, max_size_mb=10):
"""
Verifica que el tamaño del archivo no exceda el límite especificado (en MB).
"""
file.seek(0, io.SEEK_END)
file_size = file.tell() / (1024 * 1024)
file.seek(0)
return file_size <= max_size_mb
def cleanup_cloudinary():
"""
Limpia todos los recursos almacenados en Cloudinary.
"""
if not st.session_state.get('cloudinary_initialized', False):
return
try:
result = cloudinary.api.resources()
if 'resources' in result and result['resources']:
public_ids = [resource['public_id'] for resource in result['resources']]
if public_ids:
cloudinary.api.delete_resources(public_ids)
logging.info("Recursos de Cloudinary limpiados correctamente.")
except Exception as e:
st.error(f"Error al limpiar recursos: {e}")
logging.error(f"Error al limpiar recursos: {e}")
def process_image(image, width, height, dpr):
"""
Procesa la imagen utilizando Cloudinary aplicando una transformación definida.
Parámetros:
- image: Objeto tipo BytesIO con la imagen a procesar.
- width, height: Dimensiones deseadas.
- dpr: Escalado de resolución.
Retorna:
- Tuple con la imagen procesada en bytes y la extensión del archivo.
"""
if not st.session_state.get('cloudinary_initialized', False):
st.error("Cloudinary no está inicializado correctamente")
return None, None
try:
image.seek(0)
if not check_file_size(image, 10):
st.error("La imagen excede el límite de 10MB")
return None, None
image_content = image.read()
response = cloudinary.uploader.upload(
image_content,
transformation=[{
"width": width,
"height": height,
"crop": "pad",
"background": "gen_fill",
"quality": 100,
"dpr": dpr,
"flags": "preserve_transparency"
}]
)
processed_url = response['secure_url']
processed_image = requests.get(processed_url).content
file_format = response.get('format', 'jpg')
logging.info("Imagen procesada correctamente.")
return processed_image, file_format
except Exception as e:
st.error(f"Error procesando imagen: {e}")
logging.error(f"Error en process_image: {e}")
return None, None
def main():
"""
Función principal que configura la interfaz de la aplicación y coordina el flujo de procesamiento.
"""
init_cloudinary()
st.title("🤖 Cloudinary AI Background Generator")
with st.expander("📌 ¿Cómo usar esta herramienta?", expanded=True):
st.markdown(
"""
**Transforma tus imágenes automáticamente con IA:**
- 🔄 Redimensiona manteniendo la relación de aspecto
- 🎨 Genera fondos coherentes usando IA
- 📥 Descarga múltiples imágenes en un ZIP
**Formatos soportados:**
- PNG, JPG, JPEG, WEBP
**Pasos para usar:**
1. Define las dimensiones deseadas (ancho y alto)
2. Sube tus imágenes (hasta 10MB cada una)
3. Haz clic en "Procesar Imágenes"
4. Descarga los resultados finales
**Características clave:**
- Preserva transparencia en PNGs
- Soporte para formatos modernos (WEBP)
- Calidad ultra HD (DPR configurable entre 1 y 3)
- Procesamiento por lotes
- Fondo generado por IA adaptado al contexto
**Notas:**
- Las imágenes subidas se borran automáticamente después del procesamiento
- Para mejores resultados, usa imágenes con sujetos bien definidos
- El tiempo de procesamiento varía según el tamaño y cantidad de imágenes
"""
)
# Sección de parámetros de configuración
col1, col2, col3 = st.columns(3)
with col1:
width = st.number_input("Ancho (px)", value=1000, min_value=100, max_value=3000)
with col2:
height = st.number_input("Alto (px)", value=460, min_value=100, max_value=3000)
with col3:
dpr = st.number_input("DPR", value=3, min_value=1, max_value=3, step=1)
# Carga de archivos de imagen
uploaded_files = st.file_uploader(
"Sube tus imágenes (máx. 10MB por archivo)",
type=['png', 'jpg', 'jpeg', 'webp'],
accept_multiple_files=True
)
if uploaded_files:
st.header("Imágenes Originales")
cols = st.columns(3)
original_images = []
for idx, file in enumerate(uploaded_files):
file_bytes = file.getvalue()
original_images.append((file.name, file_bytes))
with cols[idx % 3]:
st.image(file_bytes, caption=file.name, use_column_width=True)
if st.button("Procesar Imágenes"):
if not st.session_state.get('cloudinary_initialized', False):
st.error("Por favor, asegúrate de que Cloudinary esté correctamente configurado")
return
processed_images = []
progress_bar = st.progress(0)
for idx, (name, img_bytes) in enumerate(original_images):
img_io = io.BytesIO(img_bytes)
with st.spinner(f'Procesando imagen {idx + 1}/{len(original_images)}...'):
processed, file_format = process_image(img_io, width, height, dpr)
if processed:
processed_images.append((processed, file_format))
progress_bar.progress((idx + 1) / len(original_images))
if processed_images:
st.header("Imágenes Procesadas")
cols = st.columns(3)
for idx, (img_bytes, file_format) in enumerate(processed_images):
with cols[idx % 3]:
st.image(img_bytes, caption=f"Formato: {file_format}", use_column_width=True)
# Empaquetado en ZIP
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, 'w') as zip_file:
for idx, (img_bytes, file_format) in enumerate(processed_images):
zip_file.writestr(f'imagen_procesada_{idx}.{file_format}', img_bytes)
st.download_button(
label="Descargar todas las imágenes",
data=zip_buffer.getvalue(),
file_name="imagenes_procesadas.zip",
mime="application/zip"
)
if __name__ == "__main__":
main()