Daniel251 commited on
Commit
bda20db
·
verified ·
1 Parent(s): 1f3a501

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +266 -127
app.py CHANGED
@@ -1,54 +1,103 @@
1
  """
2
  🎨 Basic Image Adjustments - App 2 do Photoshop AI Ecosystem
3
- Versão otimizada para Hugging Face Spaces com Gradio 6.2.0
4
  """
5
 
6
  import gradio as gr
7
  from PIL import Image, ImageEnhance, ImageOps
8
  import tempfile
9
  import numpy as np
 
 
 
 
 
 
 
 
 
 
10
 
11
  # ========== FUNÇÕES DE PROCESSAMENTO ==========
12
 
 
 
 
 
 
13
  def process_image(image, brightness=1.0, contrast=1.0, saturation=1.0, sharpness=1.0, auto_contrast=False):
14
  """Aplica ajustes básicos à imagem"""
15
- if image is None:
16
- return None
17
 
18
  try:
 
 
 
 
 
 
19
  # Converter para PIL Image se necessário
20
  if isinstance(image, np.ndarray):
21
- img = Image.fromarray(image)
22
- elif not isinstance(image, Image.Image):
23
- return None
 
 
 
 
 
 
 
24
  else:
25
- img = image.copy()
 
 
 
 
26
 
27
  # Aplicar contraste automático
28
  if auto_contrast:
 
29
  img = ImageOps.autocontrast(img, cutoff=2)
30
 
31
  # Aplicar ajustes na ordem correta
 
 
32
  if brightness != 1.0:
 
33
  img = ImageEnhance.Brightness(img).enhance(brightness)
 
34
 
35
  if contrast != 1.0:
 
36
  img = ImageEnhance.Contrast(img).enhance(contrast)
 
37
 
38
  if saturation != 1.0:
 
39
  img = ImageEnhance.Color(img).enhance(saturation)
 
40
 
41
  if sharpness != 1.0:
 
42
  img = ImageEnhance.Sharpness(img).enhance(sharpness)
 
 
 
 
 
 
43
 
44
  return img
45
 
46
  except Exception as e:
47
- print(f"Erro no processamento: {e}")
48
- return image
 
49
 
50
  def get_preset(preset_name):
51
  """Retorna valores para os presets"""
 
52
  presets = {
53
  'vibrant': (1.2, 1.3, 1.4, 1.1, False),
54
  'soft': (1.05, 0.9, 0.8, 0.9, False),
@@ -57,136 +106,216 @@ def get_preset(preset_name):
57
  'bw': (1.0, 1.2, 0.0, 1.1, False),
58
  'reset': (1.0, 1.0, 1.0, 1.0, False)
59
  }
60
- return presets.get(preset_name, presets['reset'])
 
 
61
 
62
  def save_image(image):
63
  """Salva imagem para download"""
64
- if image is None:
65
- return None
66
 
67
  try:
 
 
 
 
 
68
  temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png", prefix="adjusted_")
69
- image.save(temp_file.name, "PNG")
 
70
  return temp_file.name
 
71
  except Exception as e:
72
- print(f"Erro ao salvar: {e}")
 
73
  return None
74
 
75
- # ========== INTERFACE GRADIO 6.2.0 ==========
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
- # CSS customizado
78
- css = """
79
- .header {
80
- text-align: center;
81
- padding: 20px;
82
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
83
- border-radius: 10px;
84
- color: white;
85
- margin-bottom: 20px;
86
- }
87
- .slider-container {
88
- padding: 15px;
89
- background: #f8f9fa;
90
- border-radius: 8px;
91
- margin-bottom: 10px;
92
- }
93
- .preset-btn {
94
- margin: 5px;
95
- }
96
- .image-container {
97
- border: 2px solid #e0e0e0;
98
- border-radius: 10px;
99
- padding: 10px;
100
- background: white;
101
- }
102
- .download-btn {
103
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
104
- color: white;
105
- border: none;
106
- padding: 12px 24px;
107
- border-radius: 8px;
108
- font-weight: bold;
109
- }
110
- .control-label {
111
- font-weight: bold;
112
- color: #333;
113
- margin-bottom: 5px;
114
- }
115
- """
116
 
117
- # Criar interface
118
- with gr.Blocks(css=css, title="🎨 Basic Image Adjustments") as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
  # Cabeçalho
121
  gr.HTML("""
122
- <div class="header">
123
- <h1 style="margin: 0;">🎨 Basic Image Adjustments</h1>
124
- <p style="margin: 5px 0 0 0; opacity: 0.9;">App 2 do Photoshop AI Ecosystem</p>
125
- <p style="margin: 5px 0 0 0; font-size: 0.9em;">Ajuste brilho, contraste, saturação e nitidez</p>
126
  </div>
127
  """)
128
 
 
 
129
  with gr.Row():
130
- # Coluna 1: Upload
131
  with gr.Column(scale=1):
132
  gr.Markdown("### 📤 Upload da Imagem")
 
133
  image_input = gr.Image(
134
  type="pil",
135
- label="Clique ou arraste uma imagem",
136
- height=150,
137
- elem_classes="image-container"
138
  )
139
 
 
 
140
  gr.Markdown("### ⚙️ Controles de Ajuste")
141
 
142
- with gr.Column(elem_classes="slider-container"):
143
  brightness = gr.Slider(
144
- 0.0, 2.0, 1.0,
 
 
145
  step=0.1,
146
  label="☀️ Brilho",
147
- info="0 = Escuro | 1 = Normal | 2 = Brilhante"
148
  )
149
 
150
  contrast = gr.Slider(
151
- 0.0, 2.0, 1.0,
 
 
152
  step=0.1,
153
  label="🎭 Contraste",
154
- info="0 = Baixo | 1 = Normal | 2 = Alto"
155
  )
156
 
157
  saturation = gr.Slider(
158
- 0.0, 2.0, 1.0,
 
 
159
  step=0.1,
160
  label="🌈 Saturação",
161
- info="0 = P&B | 1 = Normal | 2 = Intenso"
162
  )
163
 
164
  sharpness = gr.Slider(
165
- 0.0, 2.0, 1.0,
 
 
166
  step=0.1,
167
  label="🔍 Nitidez",
168
- info="0 = Borrado | 1 = Normal | 2 = Nítido"
169
  )
170
 
171
  auto_contrast = gr.Checkbox(
172
- label="⚡ Aplicar Contraste Automático",
173
  value=False,
174
  info="Otimiza automaticamente o contraste da imagem"
175
  )
 
 
176
 
177
  # Coluna 2: Presets e Visualização
178
  with gr.Column(scale=1):
179
  gr.Markdown("### 🎨 Presets Rápidos")
180
 
181
  with gr.Row():
182
- vibrant_btn = gr.Button("✨ Vibrante", variant="secondary", size="sm", min_width=100)
183
- soft_btn = gr.Button("🌸 Suave", variant="secondary", size="sm", min_width=100)
184
- dramatic_btn = gr.Button("🌑 Dramático", variant="secondary", size="sm", min_width=100)
185
 
186
  with gr.Row():
187
- retro_btn = gr.Button("📻 Retrô", variant="secondary", size="sm", min_width=100)
188
- bw_btn = gr.Button("⚫ P&B", variant="secondary", size="sm", min_width=100)
189
- reset_btn = gr.Button("🔄 Resetar", variant="stop", size="sm", min_width=100)
 
 
190
 
191
  # Visualização
192
  gr.Markdown("### 👁️ Visualização")
@@ -197,8 +326,9 @@ with gr.Blocks(css=css, title="🎨 Basic Image Adjustments") as demo:
197
  original_display = gr.Image(
198
  type="pil",
199
  interactive=False,
200
- height=200,
201
- elem_classes="image-container"
 
202
  )
203
 
204
  with gr.Column():
@@ -206,36 +336,37 @@ with gr.Blocks(css=css, title="🎨 Basic Image Adjustments") as demo:
206
  processed_display = gr.Image(
207
  type="pil",
208
  interactive=False,
209
- height=200,
210
- elem_classes="image-container"
 
211
  )
 
 
212
 
213
  # Download
214
  with gr.Row():
215
  with gr.Column():
216
- gr.Markdown("### 💾 Exportação")
217
 
218
- with gr.Row():
219
- download_btn = gr.Button(
220
- "📥 Baixar Imagem Ajustada",
221
- variant="primary",
222
- size="lg",
223
- elem_classes="download-btn"
224
- )
225
 
226
  download_file = gr.File(
227
  label="Arquivo para download",
228
  interactive=False
229
  )
 
 
230
 
231
- # ========== EVENT HANDLERS ==========
232
 
233
- # Quando imagem é carregada
234
- def update_on_load(image):
235
- if image is None:
236
- return None, None
237
- return image, process_image(image)
238
 
 
239
  image_input.change(
240
  fn=update_on_load,
241
  inputs=[image_input],
@@ -243,13 +374,9 @@ with gr.Blocks(css=css, title="🎨 Basic Image Adjustments") as demo:
243
  )
244
 
245
  # Quando controles mudam
246
- def update_on_change(image, b, c, s, sh, ac):
247
- if image is None:
248
- return None
249
- return process_image(image, b, c, s, sh, ac)
250
 
251
- # Conectar todos os controles
252
- for control in [brightness, contrast, saturation, sharpness, auto_contrast]:
253
  control.change(
254
  fn=update_on_change,
255
  inputs=[image_input, brightness, contrast, saturation, sharpness, auto_contrast],
@@ -257,36 +384,37 @@ with gr.Blocks(css=css, title="🎨 Basic Image Adjustments") as demo:
257
  )
258
 
259
  # Presets
260
- def apply_preset(preset_name):
 
261
  return get_preset(preset_name)
262
 
263
  vibrant_btn.click(
264
- fn=lambda: apply_preset('vibrant'),
265
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
266
  )
267
 
268
  soft_btn.click(
269
- fn=lambda: apply_preset('soft'),
270
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
271
  )
272
 
273
  dramatic_btn.click(
274
- fn=lambda: apply_preset('dramatic'),
275
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
276
  )
277
 
278
  retro_btn.click(
279
- fn=lambda: apply_preset('retro'),
280
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
281
  )
282
 
283
  bw_btn.click(
284
- fn=lambda: apply_preset('bw'),
285
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
286
  )
287
 
288
  reset_btn.click(
289
- fn=lambda: apply_preset('reset'),
290
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
291
  )
292
 
@@ -297,10 +425,12 @@ with gr.Blocks(css=css, title="🎨 Basic Image Adjustments") as demo:
297
  outputs=[download_file]
298
  )
299
 
300
- # Guia de uso
 
 
301
  with gr.Accordion("📖 Guia de Uso & Dicas", open=False):
302
  gr.Markdown("""
303
- ## 🚀 Como usar:
304
 
305
  1. **Faça upload** de uma imagem clicando na área acima
306
  2. **Ajuste os controles** deslizantes para modificar a imagem
@@ -328,13 +458,6 @@ with gr.Blocks(css=css, title="🎨 Basic Image Adjustments") as demo:
328
  - Saturação: 1.0
329
  - Nitidez: 1.2
330
 
331
- ## ⚙️ Sobre os controles:
332
- - **Brilho**: Controla a luminosidade geral da imagem
333
- - **Contraste**: Aumenta ou diminui a diferença entre cores claras e escuras
334
- - **Saturação**: Controla a intensidade das cores (0 = Preto e Branco)
335
- - **Nitidez**: Melhora a definição dos detalhes da imagem
336
- - **Contraste Automático**: Ajusta automaticamente o contraste para melhor visualização
337
-
338
  ## 🎨 Sobre os presets:
339
  - **Vibrante**: Realça cores para fotos de natureza e paisagens
340
  - **Suave**: Tons sutis e delicados, ideal para retratos
@@ -342,14 +465,14 @@ with gr.Blocks(css=css, title="🎨 Basic Image Adjustments") as demo:
342
  - **Retrô**: Efeito vintage com cores desbotadas
343
  - **Preto & Branco**: Converte para escala de cinza
344
 
345
- ## 💾 Formato de exportação:
346
- - As imagens são exportadas em formato **PNG**
347
- - Qualidade máxima preservada
348
- - Transparência mantida (se aplicável)
349
  """)
350
 
351
  # Rodapé
352
- gr.HTML("""
353
  <div style="
354
  text-align: center;
355
  margin-top: 30px;
@@ -362,10 +485,26 @@ with gr.Blocks(css=css, title="🎨 Basic Image Adjustments") as demo:
362
  🎨 Basic Image Adjustments - App 2 do Photoshop AI Ecosystem
363
  </p>
364
  <p style="margin: 5px 0 0 0; font-size: 0.9em; color: #666;">
 
 
 
365
  Cada app tem uma função específica • Este app apenas ajusta brilho, contraste, saturação e nitidez
366
  </p>
367
  </div>
368
  """)
 
 
 
 
 
 
 
 
 
 
 
369
 
370
- # ========== FIM DO APLICATIVO ==========
371
- # Nota: Não chame demo.launch() - O Hugging Face Spaces cuida disso automaticamente
 
 
 
1
  """
2
  🎨 Basic Image Adjustments - App 2 do Photoshop AI Ecosystem
3
+ Versão definitiva para Hugging Face Spaces com Gradio 6.2.0
4
  """
5
 
6
  import gradio as gr
7
  from PIL import Image, ImageEnhance, ImageOps
8
  import tempfile
9
  import numpy as np
10
+ import traceback
11
+ import sys
12
+ import os
13
+
14
+ print("=" * 50)
15
+ print("🚀 INICIANDO APP BASIC ADJUSTMENTS")
16
+ print(f"Python version: {sys.version}")
17
+ print(f"Gradio version: {gr.__version__}")
18
+ print(f"PIL version: {Image.__version__}")
19
+ print("=" * 50)
20
 
21
  # ========== FUNÇÕES DE PROCESSAMENTO ==========
22
 
23
+ def log_function_call(func_name, *args):
24
+ """Registra chamadas de função para debug"""
25
+ print(f"📝 [{func_name}] Chamada com {len(args)} argumentos")
26
+ return True
27
+
28
  def process_image(image, brightness=1.0, contrast=1.0, saturation=1.0, sharpness=1.0, auto_contrast=False):
29
  """Aplica ajustes básicos à imagem"""
30
+ log_function_call("process_image", brightness, contrast, saturation, sharpness, auto_contrast)
 
31
 
32
  try:
33
+ if image is None:
34
+ print("⚠️ process_image: imagem é None")
35
+ return None
36
+
37
+ print(f"📊 process_image: tipo da entrada: {type(image)}")
38
+
39
  # Converter para PIL Image se necessário
40
  if isinstance(image, np.ndarray):
41
+ print("🔧 Convertendo numpy array para PIL Image")
42
+ img = Image.fromarray(image.astype('uint8'))
43
+ elif isinstance(image, dict):
44
+ # Gradio 6+ pode retornar dict
45
+ print("🔧 Convertendo dict para PIL Image")
46
+ if 'image' in image:
47
+ img = Image.fromarray(image['image'])
48
+ else:
49
+ print("❌ Dict não contém 'image' key")
50
+ return None
51
  else:
52
+ print("🔧 Usando imagem como está")
53
+ img = image
54
+
55
+ print(f"📏 process_image: tamanho da imagem: {img.size}")
56
+ print(f"🎨 process_image: modo da imagem: {img.mode}")
57
 
58
  # Aplicar contraste automático
59
  if auto_contrast:
60
+ print("⚡ Aplicando contraste automático")
61
  img = ImageOps.autocontrast(img, cutoff=2)
62
 
63
  # Aplicar ajustes na ordem correta
64
+ adjustments_applied = []
65
+
66
  if brightness != 1.0:
67
+ print(f"☀️ Aplicando brilho: {brightness}")
68
  img = ImageEnhance.Brightness(img).enhance(brightness)
69
+ adjustments_applied.append(f"brilho={brightness}")
70
 
71
  if contrast != 1.0:
72
+ print(f"🎭 Aplicando contraste: {contrast}")
73
  img = ImageEnhance.Contrast(img).enhance(contrast)
74
+ adjustments_applied.append(f"contraste={contrast}")
75
 
76
  if saturation != 1.0:
77
+ print(f"🌈 Aplicando saturação: {saturation}")
78
  img = ImageEnhance.Color(img).enhance(saturation)
79
+ adjustments_applied.append(f"saturação={saturation}")
80
 
81
  if sharpness != 1.0:
82
+ print(f"🔍 Aplicando nitidez: {sharpness}")
83
  img = ImageEnhance.Sharpness(img).enhance(sharpness)
84
+ adjustments_applied.append(f"nitidez={sharpness}")
85
+
86
+ if adjustments_applied:
87
+ print(f"✅ Ajustes aplicados: {', '.join(adjustments_applied)}")
88
+ else:
89
+ print("ℹ️ Nenhum ajuste aplicado (valores padrão)")
90
 
91
  return img
92
 
93
  except Exception as e:
94
+ print(f" ERRO em process_image: {str(e)}")
95
+ print(traceback.format_exc())
96
+ return None
97
 
98
  def get_preset(preset_name):
99
  """Retorna valores para os presets"""
100
+ print(f"🎯 get_preset: {preset_name}")
101
  presets = {
102
  'vibrant': (1.2, 1.3, 1.4, 1.1, False),
103
  'soft': (1.05, 0.9, 0.8, 0.9, False),
 
106
  'bw': (1.0, 1.2, 0.0, 1.1, False),
107
  'reset': (1.0, 1.0, 1.0, 1.0, False)
108
  }
109
+ result = presets.get(preset_name, presets['reset'])
110
+ print(f"📋 Preset {preset_name}: {result}")
111
+ return result
112
 
113
  def save_image(image):
114
  """Salva imagem para download"""
115
+ log_function_call("save_image")
 
116
 
117
  try:
118
+ if image is None:
119
+ print("❌ save_image: imagem é None")
120
+ return None
121
+
122
+ print(f"💾 Salvando imagem para download")
123
  temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png", prefix="adjusted_")
124
+ image.save(temp_file.name, "PNG", optimize=True)
125
+ print(f"✅ Imagem salva em: {temp_file.name}")
126
  return temp_file.name
127
+
128
  except Exception as e:
129
+ print(f" ERRO em save_image: {str(e)}")
130
+ print(traceback.format_exc())
131
  return None
132
 
133
+ def update_on_load(image):
134
+ """Atualiza displays quando imagem é carregada"""
135
+ print("🔄 update_on_load chamado")
136
+ log_function_call("update_on_load")
137
+
138
+ try:
139
+ if image is None:
140
+ print("⚠️ update_on_load: imagem é None")
141
+ return None, None
142
+
143
+ print(f"📥 Imagem carregada, tipo: {type(image)}")
144
+ processed = process_image(image)
145
+ print("✅ update_on_load concluído")
146
+ return image, processed
147
+
148
+ except Exception as e:
149
+ print(f"❌ ERRO em update_on_load: {str(e)}")
150
+ return None, None
151
 
152
+ def update_on_change(image, b, c, s, sh, ac):
153
+ """Atualiza imagem quando controles mudam"""
154
+ log_function_call("update_on_change", b, c, s, sh, ac)
155
+
156
+ try:
157
+ if image is None:
158
+ print("⚠️ update_on_change: imagem é None")
159
+ return None
160
+
161
+ print(f"🔄 Atualizando com parâmetros: brilho={b}, contraste={c}, saturação={s}, nitidez={sh}, auto={ac}")
162
+ result = process_image(image, b, c, s, sh, ac)
163
+ print("✅ update_on_change concluído")
164
+ return result
165
+
166
+ except Exception as e:
167
+ print(f"❌ ERRO em update_on_change: {str(e)}")
168
+ return None
169
+
170
+ # ========== INTERFACE GRADIO ==========
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
+ print("🎨 Criando interface Gradio...")
173
+
174
+ # Criar interface SEM css no construtor (corrige warning do Gradio 6+)
175
+ with gr.Blocks(title="🎨 Basic Image Adjustments") as demo:
176
+
177
+ # Aplicar CSS depois
178
+ demo.css = """
179
+ .header-box {
180
+ text-align: center;
181
+ padding: 20px;
182
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
183
+ border-radius: 10px;
184
+ color: white;
185
+ margin-bottom: 20px;
186
+ }
187
+ .control-box {
188
+ padding: 15px;
189
+ background: #f8f9fa;
190
+ border-radius: 8px;
191
+ margin-bottom: 10px;
192
+ border: 1px solid #dee2e6;
193
+ }
194
+ .preset-btn {
195
+ margin: 5px;
196
+ transition: all 0.3s;
197
+ }
198
+ .preset-btn:hover {
199
+ transform: translateY(-2px);
200
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
201
+ }
202
+ .image-box {
203
+ border: 2px solid #e0e0e0;
204
+ border-radius: 10px;
205
+ padding: 10px;
206
+ background: white;
207
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
208
+ }
209
+ .download-btn {
210
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
211
+ color: white;
212
+ border: none;
213
+ padding: 12px 24px;
214
+ border-radius: 8px;
215
+ font-weight: bold;
216
+ transition: all 0.3s;
217
+ }
218
+ .download-btn:hover {
219
+ transform: translateY(-2px);
220
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
221
+ }
222
+ .slider-label {
223
+ font-weight: bold;
224
+ color: #333;
225
+ margin-bottom: 5px;
226
+ display: block;
227
+ }
228
+ """
229
+
230
+ print("✅ CSS aplicado")
231
 
232
  # Cabeçalho
233
  gr.HTML("""
234
+ <div class="header-box">
235
+ <h1 style="margin: 0; font-size: 2.2em;">🎨 Basic Image Adjustments</h1>
236
+ <p style="margin: 5px 0 0 0; opacity: 0.9; font-size: 1.1em;">App 2 do Photoshop AI Ecosystem</p>
237
+ <p style="margin: 5px 0 0 0; font-size: 0.95em;">Ajuste brilho, contraste, saturação e nitidez em tempo real</p>
238
  </div>
239
  """)
240
 
241
+ print("✅ Cabeçalho criado")
242
+
243
  with gr.Row():
244
+ # Coluna 1: Upload e Controles
245
  with gr.Column(scale=1):
246
  gr.Markdown("### 📤 Upload da Imagem")
247
+
248
  image_input = gr.Image(
249
  type="pil",
250
+ label="Clique ou arraste uma imagem aqui",
251
+ height=180,
252
+ elem_classes="image-box"
253
  )
254
 
255
+ print("✅ Componente de upload criado")
256
+
257
  gr.Markdown("### ⚙️ Controles de Ajuste")
258
 
259
+ with gr.Column(elem_classes="control-box"):
260
  brightness = gr.Slider(
261
+ minimum=0.0,
262
+ maximum=2.0,
263
+ value=1.0,
264
  step=0.1,
265
  label="☀️ Brilho",
266
+ info="Controla a luminosidade geral (0=escuro, 1=normal, 2=brilhante)"
267
  )
268
 
269
  contrast = gr.Slider(
270
+ minimum=0.0,
271
+ maximum=2.0,
272
+ value=1.0,
273
  step=0.1,
274
  label="🎭 Contraste",
275
+ info="Controla a diferença entre cores claras e escuras"
276
  )
277
 
278
  saturation = gr.Slider(
279
+ minimum=0.0,
280
+ maximum=2.0,
281
+ value=1.0,
282
  step=0.1,
283
  label="🌈 Saturação",
284
+ info="Controla a intensidade das cores (0=preto e branco)"
285
  )
286
 
287
  sharpness = gr.Slider(
288
+ minimum=0.0,
289
+ maximum=2.0,
290
+ value=1.0,
291
  step=0.1,
292
  label="🔍 Nitidez",
293
+ info="Controla a definição dos detalhes"
294
  )
295
 
296
  auto_contrast = gr.Checkbox(
297
+ label="⚡ Contraste Automático",
298
  value=False,
299
  info="Otimiza automaticamente o contraste da imagem"
300
  )
301
+
302
+ print("✅ Controles criados")
303
 
304
  # Coluna 2: Presets e Visualização
305
  with gr.Column(scale=1):
306
  gr.Markdown("### 🎨 Presets Rápidos")
307
 
308
  with gr.Row():
309
+ vibrant_btn = gr.Button("✨ Vibrante", variant="secondary", size="sm", elem_classes="preset-btn")
310
+ soft_btn = gr.Button("🌸 Suave", variant="secondary", size="sm", elem_classes="preset-btn")
311
+ dramatic_btn = gr.Button("🌑 Dramático", variant="secondary", size="sm", elem_classes="preset-btn")
312
 
313
  with gr.Row():
314
+ retro_btn = gr.Button("📻 Retrô", variant="secondary", size="sm", elem_classes="preset-btn")
315
+ bw_btn = gr.Button("⚫ Preto & Branco", variant="secondary", size="sm", elem_classes="preset-btn")
316
+ reset_btn = gr.Button("🔄 Resetar", variant="stop", size="sm", elem_classes="preset-btn")
317
+
318
+ print("✅ Botões de preset criados")
319
 
320
  # Visualização
321
  gr.Markdown("### 👁️ Visualização")
 
326
  original_display = gr.Image(
327
  type="pil",
328
  interactive=False,
329
+ height=220,
330
+ elem_classes="image-box",
331
+ show_label=False
332
  )
333
 
334
  with gr.Column():
 
336
  processed_display = gr.Image(
337
  type="pil",
338
  interactive=False,
339
+ height=220,
340
+ elem_classes="image-box",
341
+ show_label=False
342
  )
343
+
344
+ print("✅ Displays de imagem criados")
345
 
346
  # Download
347
  with gr.Row():
348
  with gr.Column():
349
+ gr.Markdown("### 💾 Exportar Imagem")
350
 
351
+ download_btn = gr.Button(
352
+ "📥 Baixar Imagem Ajustada",
353
+ variant="primary",
354
+ size="lg",
355
+ elem_classes="download-btn"
356
+ )
 
357
 
358
  download_file = gr.File(
359
  label="Arquivo para download",
360
  interactive=False
361
  )
362
+
363
+ print("✅ Botão de download criado")
364
 
365
+ # ========== CONECTAR EVENTOS ==========
366
 
367
+ print("🔗 Conectando eventos...")
 
 
 
 
368
 
369
+ # Quando imagem é carregada
370
  image_input.change(
371
  fn=update_on_load,
372
  inputs=[image_input],
 
374
  )
375
 
376
  # Quando controles mudam
377
+ controls_list = [brightness, contrast, saturation, sharpness, auto_contrast]
 
 
 
378
 
379
+ for control in controls_list:
 
380
  control.change(
381
  fn=update_on_change,
382
  inputs=[image_input, brightness, contrast, saturation, sharpness, auto_contrast],
 
384
  )
385
 
386
  # Presets
387
+ def apply_preset_wrapper(preset_name):
388
+ print(f"🎯 Aplicando preset: {preset_name}")
389
  return get_preset(preset_name)
390
 
391
  vibrant_btn.click(
392
+ fn=lambda: apply_preset_wrapper('vibrant'),
393
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
394
  )
395
 
396
  soft_btn.click(
397
+ fn=lambda: apply_preset_wrapper('soft'),
398
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
399
  )
400
 
401
  dramatic_btn.click(
402
+ fn=lambda: apply_preset_wrapper('dramatic'),
403
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
404
  )
405
 
406
  retro_btn.click(
407
+ fn=lambda: apply_preset_wrapper('retro'),
408
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
409
  )
410
 
411
  bw_btn.click(
412
+ fn=lambda: apply_preset_wrapper('bw'),
413
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
414
  )
415
 
416
  reset_btn.click(
417
+ fn=lambda: apply_preset_wrapper('reset'),
418
  outputs=[brightness, contrast, saturation, sharpness, auto_contrast]
419
  )
420
 
 
425
  outputs=[download_file]
426
  )
427
 
428
+ print("✅ Todos os eventos conectados")
429
+
430
+ # Informações
431
  with gr.Accordion("📖 Guia de Uso & Dicas", open=False):
432
  gr.Markdown("""
433
+ ## 🚀 Como usar este app:
434
 
435
  1. **Faça upload** de uma imagem clicando na área acima
436
  2. **Ajuste os controles** deslizantes para modificar a imagem
 
458
  - Saturação: 1.0
459
  - Nitidez: 1.2
460
 
 
 
 
 
 
 
 
461
  ## 🎨 Sobre os presets:
462
  - **Vibrante**: Realça cores para fotos de natureza e paisagens
463
  - **Suave**: Tons sutis e delicados, ideal para retratos
 
465
  - **Retrô**: Efeito vintage com cores desbotadas
466
  - **Preto & Branco**: Converte para escala de cinza
467
 
468
+ ## ⚠️ Problemas comuns:
469
+ - **Imagem não aparece**: Verifique se o formato é suportado (JPG, PNG, WEBP)
470
+ - **Download não funciona**: Tente usar outra imagem
471
+ - **Ajustes lentos**: Imagens muito grandes podem processar mais devagar
472
  """)
473
 
474
  # Rodapé
475
+ gr.HTML(f"""
476
  <div style="
477
  text-align: center;
478
  margin-top: 30px;
 
485
  🎨 Basic Image Adjustments - App 2 do Photoshop AI Ecosystem
486
  </p>
487
  <p style="margin: 5px 0 0 0; font-size: 0.9em; color: #666;">
488
+ Gradio {gr.__version__} • Python {sys.version.split()[0]} • PIL {Image.__version__}
489
+ </p>
490
+ <p style="margin: 5px 0 0 0; font-size: 0.85em; color: #888;">
491
  Cada app tem uma função específica • Este app apenas ajusta brilho, contraste, saturação e nitidez
492
  </p>
493
  </div>
494
  """)
495
+
496
+ print("✅ Interface completa criada")
497
+
498
+ print("=" * 50)
499
+ print("✅ APLICATIVO PRONTO PARA EXECUÇÃO")
500
+ print("=" * 50)
501
+
502
+ # ========== INICIALIZAÇÃO PARA HUGGING FACE ==========
503
+ # O Hugging Face Spaces detecta automaticamente a variável 'demo'
504
+ # e chama demo.launch() por conta própria
505
+ # NÃO chame demo.launch() manualmente aqui
506
 
507
+ # Para debug: verificar se o app está pronto
508
+ print("🎯 App inicializado com sucesso!")
509
+ print("📊 Estado da interface:", "OK" if demo else "ERRO")
510
+ print("🏁 Aguardando conexões do Hugging Face Spaces...")