DHEIVER commited on
Commit
77a1165
·
verified ·
1 Parent(s): 78bbf9c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -184
app.py CHANGED
@@ -1,184 +1,186 @@
1
- import json
2
- import os
3
- import time
4
- import uuid
5
- import tempfile
6
- from PIL import Image, ImageDraw, ImageFont
7
- import gradio as gr
8
- import base64
9
- import mimetypes
10
-
11
- from google import genai
12
- from google.genai import types
13
-
14
- def save_binary_file(file_name, data):
15
- with open(file_name, "wb") as f:
16
- f.write(data)
17
-
18
- def generate(text, file_name, api_key, model="gemini-2.0-flash-exp"):
19
- client = genai.Client(api_key=(api_key.strip() if api_key and api_key.strip() != ""
20
- else os.environ.get("GEMINI_API_KEY")))
21
-
22
- files = [ client.files.upload(file=file_name) ]
23
-
24
- contents = [
25
- types.Content(
26
- role="user",
27
- parts=[
28
- types.Part.from_uri(
29
- file_uri=files[0].uri,
30
- mime_type=files[0].mime_type,
31
- ),
32
- types.Part.from_text(text=text),
33
- ],
34
- ),
35
- ]
36
- generate_content_config = types.GenerateContentConfig(
37
- temperature=1,
38
- top_p=0.95,
39
- top_k=40,
40
- max_output_tokens=8192,
41
- response_modalities=["image", "text"],
42
- response_mime_type="text/plain",
43
- )
44
-
45
- text_response = ""
46
- image_path = None
47
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
48
- temp_path = tmp.name
49
- for chunk in client.models.generate_content_stream(
50
- model=model,
51
- contents=contents,
52
- config=generate_content_config,
53
- ):
54
- if not chunk.candidates or not chunk.candidates[0].content or not chunk.candidates[0].content.parts:
55
- continue
56
- candidate = chunk.candidates[0].content.parts[0]
57
- if candidate.inline_data:
58
- save_binary_file(temp_path, candidate.inline_data.data)
59
- print(f"Arquivo de tipo {candidate.inline_data.mime_type} salvo em: {temp_path} com prompt: {text}")
60
- image_path = temp_path
61
- break
62
- else:
63
- text_response += chunk.text + "\n"
64
-
65
- del files
66
- return image_path, text_response
67
-
68
- def process_image_and_prompt(composite_pil, prompt, gemini_api_key):
69
- try:
70
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
71
- composite_path = tmp.name
72
- composite_pil.save(composite_path)
73
-
74
- file_name = composite_path
75
- input_text = prompt
76
- model = "gemini-2.0-flash-exp"
77
-
78
- image_path, text_response = generate(text=input_text, file_name=file_name, api_key=gemini_api_key, model=model)
79
-
80
- if image_path:
81
- result_img = Image.open(image_path)
82
- if result_img.mode == "RGBA":
83
- result_img = result_img.convert("RGB")
84
- return [result_img], ""
85
- else:
86
- return None, text_response
87
- except Exception as e:
88
- raise gr.Error(f"Erro ao processar: {e}", duration=5)
89
-
90
- # Interface com Gradio
91
- with gr.Blocks(css="style.css") as demo:
92
- gr.HTML(
93
- """
94
- <div class="header-container">
95
- <div>
96
- <img src="https://www.gstatic.com/lamda/images/gemini_favicon_f069958c85030456e93de685481c559f160ea06b.png" alt="Logo Gemini">
97
- </div>
98
- <div>
99
- <h1>Gemini para Edição de Imagens</h1>
100
- <p>Desenvolvido com <a href="https://gradio.app/">Gradio</a> ⚡️ |
101
- <a href="https://huggingface.co/spaces/ameerazam08/Gemini-Image-Edit?duplicate=true">Duplique este Repositório</a> |
102
- <a href="https://aistudio.google.com/apikey">Obtenha uma Chave API</a> |
103
- Siga-me no Linkedin: <a href="https://www.linkedin.com/in/dheiver-santos/">dheiver-santos</a></p>
104
- </div>
105
- </div>
106
- """
107
- )
108
-
109
- with gr.Accordion("⚠️ Configuração da API ⚠️", open=False, elem_classes="config-accordion"):
110
- gr.Markdown("""
111
- - **Problema:** ❗ Às vezes, o modelo retorna texto em vez de uma imagem.
112
- ### 🔧 Solução:
113
- 1. **🛠️ Duplique o Repositório**
114
- - Crie uma cópia separada para modificações.
115
- 2. **🔑 Use Sua Própria Chave API Gemini**
116
- - É **obrigatório** configurar sua chave Gemini para geração!
117
- """)
118
-
119
- with gr.Accordion("📌 Instruções de Uso", open=False, elem_classes="instructions-accordion"):
120
- gr.Markdown("""
121
- ### 📌 Como Usar
122
- - Faça upload de uma imagem e insira um prompt para gerar resultados.
123
- - Se texto for retornado em vez de imagem, ele aparecerá na saída de texto.
124
- - Use apenas imagens PNG.
125
- - ❌ **Não use imagens NSFW!**
126
- """)
127
-
128
- with gr.Row(elem_classes="main-content"):
129
- with gr.Column(elem_classes="input-column"):
130
- image_input = gr.Image(
131
- type="pil",
132
- label="Carregar Imagem",
133
- image_mode="RGBA",
134
- elem_id="image-input",
135
- elem_classes="upload-box"
136
- )
137
- gemini_api_key = gr.Textbox(
138
- lines=1,
139
- placeholder="Insira a Chave API Gemini (opcional)",
140
- label="Chave API Gemini (opcional)",
141
- elem_classes="api-key-input"
142
- )
143
- prompt_input = gr.Textbox(
144
- lines=2,
145
- placeholder="Digite seu prompt aqui...",
146
- label="Prompt",
147
- elem_classes="prompt-input"
148
- )
149
- submit_btn = gr.Button("Gerar", elem_classes="generate-btn")
150
-
151
- with gr.Column(elem_classes="output-column"):
152
- output_gallery = gr.Gallery(label="Resultados Gerados", elem_classes="output-gallery")
153
- output_text = gr.Textbox(
154
- label="Saída do Gemini",
155
- placeholder="A resposta em texto aparecerá aqui se nenhuma imagem for gerada.",
156
- elem_classes="output-text"
157
- )
158
-
159
- submit_btn.click(
160
- fn=process_image_and_prompt,
161
- inputs=[image_input, prompt_input, gemini_api_key],
162
- outputs=[output_gallery, output_text],
163
- )
164
-
165
- gr.Markdown("## Experimente estes exemplos", elem_classes="gr-examples-header")
166
-
167
- examples = [
168
- ["data/1.webp", "change text to 'AMEER'", ""],
169
- ["data/2.webp", "remove the spoon from hand only", ""],
170
- ["data/3.webp", "change text to 'Make it'", ""],
171
- ["data/1.jpg", "add joker style only on face", ""],
172
- ["data/1777043.jpg", "add joker style only on face", ""],
173
- ["data/2807615.jpg", "add lipstick on lip only", ""],
174
- ["data/76860.jpg", "add lipstick on lip only", ""],
175
- ["data/2807615.jpg", "make it happy looking face only", ""],
176
- ]
177
-
178
- gr.Examples(
179
- examples=examples,
180
- inputs=[image_input, prompt_input],
181
- elem_id="examples-grid"
182
- )
183
-
184
- demo.queue(max_size=50).launch()
 
 
 
1
+ /* Paleta de cores */
2
+ :root {
3
+ --primary-color: #4A90E2; /* Azul suave */
4
+ --secondary-color: #50C878; /* Verde esmeralda */
5
+ --background-color: #F7F9FC; /* Cinza claro */
6
+ --text-color: #333333; /* Preto suave */
7
+ --accent-color: #F5A623; /* Laranja vibrante */
8
+ --border-color: #DDE4E9; /* Cinza claro */
9
+ --hover-color: #357ABD; /* Azul mais escuro */
10
+ }
11
+
12
+ /* Estilo geral */
13
+ body {
14
+ background-color: var(--background-color);
15
+ color: var(--text-color);
16
+ font-family: 'Arial', sans-serif;
17
+ padding: 20px;
18
+ }
19
+
20
+ /* Cabeçalho */
21
+ .header-container {
22
+ display: flex;
23
+ align-items: center;
24
+ padding: 15px 25px;
25
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
26
+ color: white;
27
+ border-radius: 10px;
28
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
29
+ margin-bottom: 20px;
30
+ }
31
+
32
+ .logo img {
33
+ width: 50px;
34
+ margin-right: 20px;
35
+ }
36
+
37
+ .header-text h1 {
38
+ margin: 0;
39
+ font-size: 28px;
40
+ font-weight: bold;
41
+ }
42
+
43
+ .header-text p {
44
+ margin: 5px 0 0;
45
+ font-size: 14px;
46
+ }
47
+
48
+ .header-text a {
49
+ color: var(--accent-color);
50
+ text-decoration: none;
51
+ transition: color 0.3s;
52
+ }
53
+
54
+ .header-text a:hover {
55
+ color: white;
56
+ }
57
+
58
+ /* Abas */
59
+ .gr-tabs {
60
+ background-color: white;
61
+ border-radius: 10px;
62
+ padding: 15px;
63
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
64
+ }
65
+
66
+ /* Acordeões */
67
+ .config-accordion, .instructions-accordion {
68
+ border: 1px solid var(--border-color);
69
+ border-radius: 8px;
70
+ padding: 10px;
71
+ background-color: #fff;
72
+ }
73
+
74
+ .config-accordion h3, .instructions-accordion h3 {
75
+ color: var(--primary-color);
76
+ font-size: 18px;
77
+ }
78
+
79
+ /* Entrada e Saída */
80
+ .upload-box {
81
+ border: 2px dashed var(--primary-color);
82
+ border-radius: 8px;
83
+ padding: 15px;
84
+ background-color: #fafafa;
85
+ transition: border-color 0.3s;
86
+ }
87
+
88
+ .upload-box:hover {
89
+ border-color: var(--hover-color);
90
+ }
91
+
92
+ .api-key-input, .prompt-input {
93
+ border: 1px solid var(--border-color);
94
+ border-radius: 6px;
95
+ padding: 10px;
96
+ font-size: 14px;
97
+ transition: border-color 0.3s;
98
+ }
99
+
100
+ .api-key-input:focus, .prompt-input:focus {
101
+ border-color: var(--primary-color);
102
+ outline: none;
103
+ }
104
+
105
+ .generate-btn {
106
+ background-color: var(--secondary-color);
107
+ color: white;
108
+ border: none;
109
+ padding: 12px 25px;
110
+ border-radius: 6px;
111
+ font-weight: bold;
112
+ cursor: pointer;
113
+ transition: background-color 0.3s;
114
+ }
115
+
116
+ .generate-btn:hover {
117
+ background-color: #45b065;
118
+ }
119
+
120
+ .gr-button.secondary {
121
+ background-color: #e0e0e0;
122
+ color: var(--text-color);
123
+ padding: 12px 25px;
124
+ border-radius: 6px;
125
+ }
126
+
127
+ .gr-button.secondary:hover {
128
+ background-color: #d0d0d0;
129
+ }
130
+
131
+ /* Galeria e texto de saída */
132
+ .output-gallery {
133
+ border: 1px solid var(--border-color);
134
+ border-radius: 8px;
135
+ padding: 10px;
136
+ background-color: #fff;
137
+ min-height: 200px;
138
+ }
139
+
140
+ .output-text {
141
+ border: 1px solid var(--border-color);
142
+ border-radius: 6px;
143
+ padding: 10px;
144
+ min-height: 100px;
145
+ font-size: 14px;
146
+ background-color: #fafafa;
147
+ }
148
+
149
+ /* Exemplos */
150
+ .gr-examples-header {
151
+ color: var(--primary-color);
152
+ font-size: 22px;
153
+ margin: 20px 0 10px;
154
+ text-align: center;
155
+ }
156
+
157
+ #examples-grid {
158
+ display: grid;
159
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
160
+ gap: 15px;
161
+ padding: 10px;
162
+ background-color: white;
163
+ border-radius: 8px;
164
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
165
+ }
166
+
167
+ /* Tooltips (personalizado) */
168
+ .gr-tooltip {
169
+ position: relative;
170
+ display: inline-block;
171
+ }
172
+
173
+ .gr-tooltip:hover::after {
174
+ content: attr(tooltips);
175
+ position: absolute;
176
+ bottom: 100%;
177
+ left: 50%;
178
+ transform: translateX(-50%);
179
+ background-color: #333;
180
+ color: white;
181
+ padding: 5px 10px;
182
+ border-radius: 4px;
183
+ font-size: 12px;
184
+ white-space: nowrap;
185
+ z-index: 10;
186
+ }