Spaces:
Sleeping
Sleeping
| """ | |
| 🎨 Basic Image Adjustments - App 2 do Photoshop AI Ecosystem | |
| Versão otimizada para Hugging Face Spaces com Gradio 6.2.0 | |
| """ | |
| import gradio as gr | |
| from PIL import Image, ImageEnhance, ImageOps | |
| import tempfile | |
| import numpy as np | |
| import sys | |
| print("=" * 50) | |
| print("🚀 INICIANDO APP BASIC ADJUSTMENTS") | |
| print(f"Python version: {sys.version}") | |
| print(f"Gradio version: {gr.__version__}") | |
| print(f"PIL version: {Image.__version__}") | |
| print("=" * 50) | |
| # ========== FUNÇÕES DE PROCESSAMENTO ========== | |
| def process_image(image, brightness=1.0, contrast=1.0, saturation=1.0, sharpness=1.0, auto_contrast=False): | |
| """Aplica ajustes básicos à imagem""" | |
| try: | |
| if image is None: | |
| return None | |
| # Converter para PIL Image se necessário | |
| if isinstance(image, np.ndarray): | |
| img = Image.fromarray(image.astype('uint8')) | |
| elif isinstance(image, dict) and 'image' in image: | |
| img = Image.fromarray(image['image']) | |
| else: | |
| img = image | |
| # Converter para RGB se necessário | |
| if img.mode != 'RGB': | |
| img = img.convert('RGB') | |
| # Aplicar contraste automático | |
| if auto_contrast: | |
| img = ImageOps.autocontrast(img, cutoff=2) | |
| # Aplicar ajustes | |
| if brightness != 1.0: | |
| img = ImageEnhance.Brightness(img).enhance(brightness) | |
| if contrast != 1.0: | |
| img = ImageEnhance.Contrast(img).enhance(contrast) | |
| if saturation != 1.0: | |
| img = ImageEnhance.Color(img).enhance(saturation) | |
| if sharpness != 1.0: | |
| img = ImageEnhance.Sharpness(img).enhance(sharpness) | |
| return img | |
| except Exception as e: | |
| print(f"❌ ERRO em process_image: {str(e)}") | |
| return None | |
| def get_preset(preset_name): | |
| """Retorna valores para os presets""" | |
| presets = { | |
| 'vibrant': (1.2, 1.3, 1.4, 1.1, False), | |
| 'soft': (1.05, 0.9, 0.8, 0.9, False), | |
| 'dramatic': (0.9, 1.4, 0.9, 1.3, False), | |
| 'retro': (1.0, 1.1, 0.6, 1.0, False), | |
| 'bw': (1.0, 1.2, 0.0, 1.1, False), | |
| 'reset': (1.0, 1.0, 1.0, 1.0, False) | |
| } | |
| return presets.get(preset_name, presets['reset']) | |
| def save_image(image): | |
| """Salva imagem para download""" | |
| try: | |
| if image is None: | |
| return None | |
| temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png", prefix="adjusted_") | |
| image.save(temp_file.name, "PNG", optimize=True) | |
| return temp_file.name | |
| except Exception as e: | |
| print(f"❌ ERRO em save_image: {str(e)}") | |
| return None | |
| def update_on_load(image): | |
| """Atualiza displays quando imagem é carregada""" | |
| if image is None: | |
| return None, None | |
| processed = process_image(image) | |
| return image, processed | |
| def update_on_change(image, b, c, s, sh, ac): | |
| """Atualiza imagem quando controles mudam""" | |
| if image is None: | |
| return None | |
| return process_image(image, b, c, s, sh, ac) | |
| # ========== INTERFACE GRADIO ========== | |
| with gr.Blocks(title="🎨 Basic Image Adjustments") as demo: | |
| # Cabeçalho | |
| gr.HTML(""" | |
| <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 10px; color: white; margin-bottom: 20px;"> | |
| <h1 style="margin: 0; font-size: 2.2em;">🎨 Basic Image Adjustments</h1> | |
| <p style="margin: 5px 0 0 0; opacity: 0.9; font-size: 1.1em;">App 2 do Photoshop AI Ecosystem</p> | |
| <p style="margin: 5px 0 0 0; font-size: 0.95em;">Ajuste brilho, contraste, saturação e nitidez em tempo real</p> | |
| </div> | |
| """) | |
| with gr.Row(): | |
| # Coluna 1: Upload e Controles | |
| with gr.Column(scale=1): | |
| gr.Markdown("### 📤 Upload da Imagem") | |
| image_input = gr.Image( | |
| type="pil", | |
| label="Clique ou arraste uma imagem aqui", | |
| height=180 | |
| ) | |
| gr.Markdown("### ⚙️ Controles de Ajuste") | |
| with gr.Group(): | |
| brightness = gr.Slider( | |
| minimum=0.0, | |
| maximum=2.0, | |
| value=1.0, | |
| step=0.1, | |
| label="☀️ Brilho", | |
| info="Controla a luminosidade geral" | |
| ) | |
| contrast = gr.Slider( | |
| minimum=0.0, | |
| maximum=2.0, | |
| value=1.0, | |
| step=0.1, | |
| label="🎭 Contraste", | |
| info="Controla a diferença entre cores" | |
| ) | |
| saturation = gr.Slider( | |
| minimum=0.0, | |
| maximum=2.0, | |
| value=1.0, | |
| step=0.1, | |
| label="🌈 Saturação", | |
| info="Controla a intensidade das cores" | |
| ) | |
| sharpness = gr.Slider( | |
| minimum=0.0, | |
| maximum=2.0, | |
| value=1.0, | |
| step=0.1, | |
| label="🔍 Nitidez", | |
| info="Controla a definição dos detalhes" | |
| ) | |
| auto_contrast = gr.Checkbox( | |
| label="⚡ Contraste Automático", | |
| value=False, | |
| info="Otimiza automaticamente o contraste" | |
| ) | |
| # Coluna 2: Presets e Visualização | |
| with gr.Column(scale=1): | |
| gr.Markdown("### 🎨 Presets Rápidos") | |
| with gr.Row(): | |
| vibrant_btn = gr.Button("✨ Vibrante", size="sm") | |
| soft_btn = gr.Button("🌸 Suave", size="sm") | |
| dramatic_btn = gr.Button("🌑 Dramático", size="sm") | |
| with gr.Row(): | |
| retro_btn = gr.Button("📻 Retrô", size="sm") | |
| bw_btn = gr.Button("⚫ P&B", size="sm") | |
| reset_btn = gr.Button("🔄 Resetar", size="sm") | |
| gr.Markdown("### 👁️ Visualização") | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("**Original**") | |
| original_display = gr.Image( | |
| type="pil", | |
| interactive=False, | |
| height=220, | |
| show_label=False | |
| ) | |
| with gr.Column(): | |
| gr.Markdown("**Ajustada**") | |
| processed_display = gr.Image( | |
| type="pil", | |
| interactive=False, | |
| height=220, | |
| show_label=False | |
| ) | |
| # Download | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("### 💾 Exportar Imagem") | |
| download_btn = gr.Button( | |
| "📥 Baixar Imagem Ajustada", | |
| variant="primary", | |
| size="lg" | |
| ) | |
| download_file = gr.File( | |
| label="Arquivo para download", | |
| interactive=False | |
| ) | |
| # ========== EVENTOS ========== | |
| # Quando imagem é carregada | |
| image_input.change( | |
| fn=update_on_load, | |
| inputs=[image_input], | |
| outputs=[original_display, processed_display] | |
| ) | |
| # Quando controles mudam | |
| controls = [brightness, contrast, saturation, sharpness, auto_contrast] | |
| for control in controls: | |
| control.change( | |
| fn=update_on_change, | |
| inputs=[image_input] + controls, | |
| outputs=[processed_display] | |
| ) | |
| # Presets | |
| vibrant_btn.click( | |
| fn=lambda: get_preset('vibrant'), | |
| outputs=controls | |
| ) | |
| soft_btn.click( | |
| fn=lambda: get_preset('soft'), | |
| outputs=controls | |
| ) | |
| dramatic_btn.click( | |
| fn=lambda: get_preset('dramatic'), | |
| outputs=controls | |
| ) | |
| retro_btn.click( | |
| fn=lambda: get_preset('retro'), | |
| outputs=controls | |
| ) | |
| bw_btn.click( | |
| fn=lambda: get_preset('bw'), | |
| outputs=controls | |
| ) | |
| reset_btn.click( | |
| fn=lambda: get_preset('reset'), | |
| outputs=controls | |
| ) | |
| # Download | |
| download_btn.click( | |
| fn=save_image, | |
| inputs=[processed_display], | |
| outputs=[download_file] | |
| ) | |
| # Guia de uso | |
| with gr.Accordion("📖 Guia de Uso & Dicas", open=False): | |
| gr.Markdown(""" | |
| ## 🚀 Como usar: | |
| 1. **Upload** da imagem | |
| 2. **Ajuste** os controles deslizantes | |
| 3. **Use presets** para efeitos rápidos | |
| 4. **Compare** original vs ajustada | |
| 5. **Baixe** o resultado | |
| ## 💡 Dicas por tipo de foto: | |
| **Retratos**: Brilho 1.05, Contraste 1.1, Saturação 0.9 | |
| **Paisagens**: Brilho 1.1, Contraste 1.2, Saturação 1.2 | |
| **Produtos**: Brilho 1.0, Contraste 1.3, Nitidez 1.2 | |
| ## 🎨 Presets: | |
| - **Vibrante**: Cores intensas para natureza | |
| - **Suave**: Tons delicados para retratos | |
| - **Dramático**: Alto contraste | |
| - **Retrô**: Efeito vintage | |
| - **P&B**: Preto e branco | |
| """) | |
| # Rodapé | |
| gr.HTML(f""" | |
| <div style="text-align: center; margin-top: 30px; padding: 15px; background: #f8f9fa; border-radius: 8px;"> | |
| <p style="margin: 0; font-weight: bold;">🎨 Basic Image Adjustments - Photoshop AI Ecosystem</p> | |
| <p style="margin: 5px 0 0 0; font-size: 0.9em; color: #666;"> | |
| Gradio {gr.__version__} • Python {sys.version.split()[0]} | |
| </p> | |
| </div> | |
| """) | |
| print("✅ Interface criada com sucesso") | |
| print("🏁 App pronto para Hugging Face Spaces") | |
| # Launch explícito para Hugging Face Spaces | |
| if __name__ == "__main__": | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| show_error=True | |
| ) |