Daniel251 commited on
Commit
2f0daa3
·
verified ·
1 Parent(s): eafe118

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +226 -109
app.py CHANGED
@@ -1,7 +1,6 @@
1
  """
2
- 🎨 Basic Image Adjustments
3
- Ajustes básicos de imagem
4
- Otimizado para Hugging Face Spaces
5
  """
6
 
7
  import gradio as gr
@@ -9,91 +8,121 @@ from PIL import Image, ImageEnhance, ImageOps
9
  import tempfile
10
  import numpy as np
11
 
12
- # ========== FUNÇÕES PRINCIPAIS ==========
13
 
14
  def process_image(image, brightness=1.0, contrast=1.0, saturation=1.0, sharpness=1.0, auto_contrast=False):
15
- """Processa imagem com ajustes básicos"""
16
  if image is None:
17
  return None
18
 
19
  try:
20
- # Converter para PIL Image
21
  if isinstance(image, np.ndarray):
22
  img = Image.fromarray(image)
 
 
23
  else:
24
- img = image
25
 
26
  # Aplicar contraste automático
27
  if auto_contrast:
28
  img = ImageOps.autocontrast(img, cutoff=2)
29
 
30
- # Aplicar ajustes
31
  if brightness != 1.0:
32
- enhancer = ImageEnhance.Brightness(img)
33
- img = enhancer.enhance(brightness)
34
 
35
  if contrast != 1.0:
36
- enhancer = ImageEnhance.Contrast(img)
37
- img = enhancer.enhance(contrast)
38
 
39
  if saturation != 1.0:
40
- enhancer = ImageEnhance.Color(img)
41
- img = enhancer.enhance(saturation)
42
 
43
  if sharpness != 1.0:
44
- enhancer = ImageEnhance.Sharpness(img)
45
- img = enhancer.enhance(sharpness)
46
 
47
  return img
48
 
49
  except Exception as e:
50
- print(f"Erro: {e}")
51
  return image
52
 
53
- def get_preset_values(preset_name):
54
- """Retorna valores de preset"""
55
  presets = {
56
- 'vibrant': {'brightness': 1.2, 'contrast': 1.3, 'saturation': 1.4, 'sharpness': 1.1, 'auto_contrast': False},
57
- 'soft': {'brightness': 1.05, 'contrast': 0.9, 'saturation': 0.8, 'sharpness': 0.9, 'auto_contrast': False},
58
- 'dramatic': {'brightness': 0.9, 'contrast': 1.4, 'saturation': 0.9, 'sharpness': 1.3, 'auto_contrast': False},
59
- 'retro': {'brightness': 1.0, 'contrast': 1.1, 'saturation': 0.6, 'sharpness': 1.0, 'auto_contrast': False},
60
- 'bw': {'brightness': 1.0, 'contrast': 1.2, 'saturation': 0.0, 'sharpness': 1.1, 'auto_contrast': False},
61
- 'reset': {'brightness': 1.0, 'contrast': 1.0, 'saturation': 1.0, 'sharpness': 1.0, 'auto_contrast': False}
62
  }
63
  return presets.get(preset_name, presets['reset'])
64
 
65
- def save_image_for_download(image):
66
  """Salva imagem para download"""
67
  if image is None:
68
  return None
69
 
70
  try:
71
  temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png", prefix="adjusted_")
72
- image.save(temp_file.name, "PNG", optimize=True)
73
  return temp_file.name
74
- except:
 
75
  return None
76
 
77
- # ========== INTERFACE GRADIO ==========
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
- # Criar interface sem parâmetros no construtor (compatível com Gradio 6+)
80
- with gr.Blocks(title="🎨 Basic Image Adjustments") as demo:
81
-
82
- # CSS customizado
83
- demo.css = """
84
- .header { text-align: center; padding: 20px; }
85
- .slider-label { font-weight: bold; margin-bottom: 5px; }
86
- .preset-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
87
- .image-box { border: 1px solid #ddd; border-radius: 8px; padding: 10px; }
88
- .download-btn { width: 100%; margin-top: 20px; }
89
- """
90
 
91
  # Cabeçalho
92
  gr.HTML("""
93
  <div class="header">
94
- <h1 style="color: #4a6fa5;">🎨 Basic Image Adjustments</h1>
95
- <p style="font-size: 1.1em;"><strong>App 2 do Photoshop AI Ecosystem</strong></p>
96
- <p style="color: #666;">Ajuste brilho, contraste, saturação e nitidez</p>
97
  </div>
98
  """)
99
 
@@ -101,86 +130,135 @@ with gr.Blocks(title="🎨 Basic Image Adjustments") as demo:
101
  # Coluna 1: Upload
102
  with gr.Column(scale=1):
103
  gr.Markdown("### 📤 Upload da Imagem")
104
- image_input = gr.Image(type="pil", label="Clique ou arraste uma imagem", height=150)
 
 
 
 
 
105
 
106
- gr.Markdown("### ⚙️ Controles")
107
 
108
- brightness = gr.Slider(0.0, 2.0, 1.0, step=0.1, label="☀️ Brilho")
109
- contrast = gr.Slider(0.0, 2.0, 1.0, step=0.1, label="🎭 Contraste")
110
- saturation = gr.Slider(0.0, 2.0, 1.0, step=0.1, label="🌈 Saturação")
111
- sharpness = gr.Slider(0.0, 2.0, 1.0, step=0.1, label="🔍 Nitidez")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
- auto_contrast = gr.Checkbox(label="⚡ Contraste Automático", value=False)
 
 
 
 
114
 
115
- # Coluna 2: Presets
116
  with gr.Column(scale=1):
117
  gr.Markdown("### 🎨 Presets Rápidos")
118
 
119
  with gr.Row():
120
- vibrant_btn = gr.Button("Vibrante", variant="secondary")
121
- soft_btn = gr.Button("Suave", variant="secondary")
122
- dramatic_btn = gr.Button("Dramático", variant="secondary")
123
 
124
  with gr.Row():
125
- retro_btn = gr.Button("Retrô", variant="secondary")
126
- bw_btn = gr.Button("P&B", variant="secondary")
127
- reset_btn = gr.Button("Resetar", variant="stop")
128
-
129
- # Visualização
130
- with gr.Row():
131
- with gr.Column():
132
- gr.Markdown("### 👁️ Original")
133
- original_display = gr.Image(type="pil", interactive=False, height=250, label="Original")
134
-
135
- with gr.Column():
136
- gr.Markdown("### ✨ Ajustada")
137
- processed_display = gr.Image(type="pil", interactive=False, height=250, label="Ajustada")
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
  # Download
140
  with gr.Row():
141
  with gr.Column():
142
- gr.Markdown("### 💾 Download")
143
- download_btn = gr.Button("📥 Baixar Imagem Ajustada", variant="primary", size="lg")
144
- download_file = gr.File(label="Arquivo para download", interactive=False)
 
 
 
 
 
 
 
 
 
 
 
145
 
146
  # ========== EVENT HANDLERS ==========
147
 
148
  # Quando imagem é carregada
149
- def update_displays(image):
150
  if image is None:
151
  return None, None
152
- return image, process_image(image, 1.0, 1.0, 1.0, 1.0, False)
153
 
154
  image_input.change(
155
- fn=update_displays,
156
  inputs=[image_input],
157
  outputs=[original_display, processed_display]
158
  )
159
 
160
- # Processar quando controles mudam
161
- def update_processed(img, b, c, s, sh, ac):
162
- return process_image(img, b, c, s, sh, ac)
 
 
163
 
164
  # Conectar todos os controles
165
- controls = [brightness, contrast, saturation, sharpness, auto_contrast]
166
-
167
- for control in controls:
168
  control.change(
169
- fn=update_processed,
170
  inputs=[image_input, brightness, contrast, saturation, sharpness, auto_contrast],
171
  outputs=[processed_display]
172
  )
173
 
174
  # Presets
175
  def apply_preset(preset_name):
176
- preset = get_preset_values(preset_name)
177
- return [
178
- preset['brightness'],
179
- preset['contrast'],
180
- preset['saturation'],
181
- preset['sharpness'],
182
- preset['auto_contrast']
183
- ]
184
 
185
  vibrant_btn.click(
186
  fn=lambda: apply_preset('vibrant'),
@@ -214,41 +292,80 @@ with gr.Blocks(title="🎨 Basic Image Adjustments") as demo:
214
 
215
  # Download
216
  download_btn.click(
217
- fn=save_image_for_download,
218
  inputs=[processed_display],
219
  outputs=[download_file]
220
  )
221
 
222
  # Guia de uso
223
- with gr.Accordion("📖 Como usar", open=False):
224
  gr.Markdown("""
225
- ## Instruções:
226
- 1. **Faça upload** de uma imagem
227
- 2. **Ajuste os controles** deslizantes
228
- 3. **Use presets** para efeitos rápidos
229
- 4. **Compare** original vs. ajustada
230
- 5. **Baixe** o resultado
 
 
 
231
 
232
- ## Dicas:
233
- - **Retratos**: Brilho 1.05, Contraste 1.1, Saturação 0.9
234
- - **Paisagens**: Brilho 1.1, Contraste 1.2, Saturação 1.2
235
- - **Produtos**: Brilho 1.0, Contraste 1.3, Saturação 1.0
 
236
 
237
- ## Valores:
238
- - **0.0** = Mínimo efeito
239
- - **1.0** = Normal (padrão)
240
- - **2.0** = Máximo efeito
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  """)
242
 
243
  # Rodapé
244
  gr.HTML("""
245
- <div style="text-align: center; margin-top: 30px; padding: 15px; background: #f8f9fa; border-radius: 8px;">
246
- <p><strong>🎨 Basic Image Adjustments</strong> - App 2 do Photoshop AI Ecosystem</p>
247
- <p style="color: #666; font-size: 0.9em;">
248
- Cada app tem uma função específica • Este app apenas ajusta brilho, contraste, saturação e nitidez
 
 
 
 
 
 
 
 
 
249
  </p>
250
  </div>
251
  """)
252
 
253
  # ========== FIM DO APLICATIVO ==========
254
- # Não chame demo.launch() - O Hugging Face cuida disso
 
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
 
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),
55
+ 'dramatic': (0.9, 1.4, 0.9, 1.3, False),
56
+ 'retro': (1.0, 1.1, 0.6, 1.0, False),
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
 
 
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")
193
+
194
+ with gr.Row():
195
+ with gr.Column():
196
+ gr.Markdown("**Original**")
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():
205
+ gr.Markdown("**Ajustada**")
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],
242
  outputs=[original_display, processed_display]
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],
256
  outputs=[processed_display]
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'),
 
292
 
293
  # Download
294
  download_btn.click(
295
+ fn=save_image,
296
  inputs=[processed_display],
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
307
+ 3. **Use presets** para efeitos rápidos e pré-definidos
308
+ 4. **Compare** a imagem original com a ajustada
309
+ 5. **Baixe** o resultado final
310
+
311
+ ## 💡 Dicas de ajuste:
312
 
313
+ ### Para **Retratos**:
314
+ - Brilho: 1.05
315
+ - Contraste: 1.1
316
+ - Saturação: 0.9
317
+ - Nitidez: 1.0
318
 
319
+ ### Para **Paisagens**:
320
+ - Brilho: 1.1
321
+ - Contraste: 1.2
322
+ - Saturação: 1.2
323
+ - Nitidez: 1.1
324
+
325
+ ### Para **Produtos**:
326
+ - Brilho: 1.0
327
+ - Contraste: 1.3
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
341
+ - **Dramático**: Alto contraste para impacto visual
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;
356
+ padding: 15px;
357
+ background: #f8f9fa;
358
+ border-radius: 8px;
359
+ border-top: 3px solid #667eea;
360
+ ">
361
+ <p style="margin: 0; font-weight: bold; color: #333;">
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