File size: 11,523 Bytes
17a3958
f1ebcf1
 
 
 
 
17a3958
f1ebcf1
 
 
17a3958
f1ebcf1
 
 
 
 
 
 
 
17a3958
f1ebcf1
 
17a3958
f1ebcf1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17a3958
f1ebcf1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17a3958
f1ebcf1
 
 
 
 
 
 
 
 
 
 
 
 
 
17a3958
f1ebcf1
 
 
 
 
17a3958
f1ebcf1
 
 
 
 
17a3958
f1ebcf1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17a3958
f1ebcf1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17a3958
 
f1ebcf1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
"""
FLUX Image Generator - Nineteen.ai API (Versione HF Spaces)
--------------------------------------
Questo script utilizza l'API di Nineteen.ai per generare immagini
con il modello FLUX.1-schnell, offrendo un'interfaccia grafica intuitiva.
Versione ottimizzata per Hugging Face Spaces con autenticazione.

Autore: Utente
Data: 09/03/2025
"""

import os
import io
import time
import base64
import requests
import gradio as gr
from PIL import Image
from dotenv import load_dotenv

# Carica le variabili d'ambiente (se presenti)
load_dotenv()

class FluxNineteenGenerator:
    """
    Classe per generare immagini utilizzando il modello FLUX.1-schnell
    attraverso l'API di Nineteen.ai.
    """
    
    def __init__(self):
        """
        Inizializza il generatore di immagini FLUX tramite API Nineteen.ai.
        """
        print("Inizializzazione del generatore di immagini FLUX Nineteen.ai...")
        
        # Ottieni l'API key da variabile d'ambiente o usa quella predefinita
        self.api_key = os.getenv("NINETEEN_API_KEY", "rayon_6nzcBRzaq8f7iRzFUX2IsscMBGKgmJcO")
        
        # Configurazione dell'API
        self.api_endpoint = "https://api.nineteen.ai/v1/text-to-image"
        self.headers = {
            "Authorization": f"Bearer {self.api_key}",
            "accept": "application/json",
            "Content-Type": "application/json"
        }
        
        # Modelli disponibili
        self.models = ["black-forest-labs/FLUX.1-schnell", "black-forest-labs/FLUX.1-dev"]
        self.default_model = "black-forest-labs/FLUX.1-schnell"
        
        print(f"Generatore inizializzato con modello predefinito: {self.default_model}")
    
    def generate_image(self, prompt, model=None, steps=8, cfg_scale=3, 
                      height=1024, width=1024, negative_prompt=""):
        """
        Genera un'immagine utilizzando l'API di Nineteen.ai.
        
        Args:
            prompt (str): Descrizione testuale dell'immagine da generare
            model (str, optional): Modello da utilizzare
            steps (int): Numero di passi di inferenza
            cfg_scale (float): Scala di guidance per la generazione
            height (int): Altezza dell'immagine in pixel
            width (int): Larghezza dell'immagine in pixel
            negative_prompt (str): Prompt negativo per escludere elementi indesiderati
            
        Returns:
            PIL.Image: L'immagine generata
            str: Messaggio di stato
        """
        if not model:
            model = self.default_model
            
        try:
            # Prepara il payload
            data = {
                "prompt": prompt,
                "model": model,
                "steps": steps,
                "cfg_scale": cfg_scale,
                "height": height,
                "width": width,
                "negativePrompt": negative_prompt
            }
            
            # Log della richiesta
            print(f"Generazione immagine con prompt: '{prompt}'")
            print(f"Parametri: modello={model}, steps={steps}, cfg_scale={cfg_scale}, dimensioni={width}x{height}")
            
            # Effettua la chiamata API
            start_time = time.time()
            response = requests.post(self.api_endpoint, headers=self.headers, json=data)
            end_time = time.time()
            
            # Gestione degli errori
            if response.status_code != 200:
                error_message = f"Errore API: {response.status_code} - {response.text}"
                print(error_message)
                return None, error_message
            
            # Estrai l'immagine in formato base64 dalla risposta
            try:
                image_b64 = response.json()["image_b64"]
                image_data = base64.b64decode(image_b64)
                image = Image.open(io.BytesIO(image_data))
                
                print(f"Immagine generata in {end_time - start_time:.2f} secondi")
                return image, f"Immagine generata in {end_time - start_time:.2f} secondi"
            except KeyError:
                return None, f"Errore: La risposta API non contiene il campo 'image_b64'. Risposta: {response.json()}"
            except Exception as e:
                return None, f"Errore nel decodificare l'immagine: {str(e)}"
                
        except Exception as e:
            error_message = f"Errore durante la generazione dell'immagine: {str(e)}"
            print(error_message)
            return None, error_message

def create_ui(generator):
    """
    Crea l'interfaccia utente Gradio.
    
    Args:
        generator (FluxNineteenGenerator): Istanza del generatore
    
    Returns:
        gradio.Interface: L'interfaccia Gradio
    """
    
    def generate_image_ui(prompt, model, steps, cfg_scale, height, width, negative_prompt):
        """Funzione per generare immagini dall'interfaccia"""
        # Validazione dei parametri
        if not prompt or len(prompt.strip()) == 0:
            return None, "Il prompt non può essere vuoto."
        
        try:
            # Converti i parametri al tipo corretto
            steps = int(steps)
            cfg_scale = float(cfg_scale)
            height = int(height)
            width = int(width)
            
            # Validazione dei valori
            if steps < 1 or steps > 50:
                return None, "Il numero di passi deve essere compreso tra 1 e 50."
            if cfg_scale < 1 or cfg_scale > 30:
                return None, "La guidance scale deve essere compresa tra 1 e 30."
            if height < 512 or height > 1536:
                return None, "L'altezza deve essere compresa tra 512 e 1536 pixel."
            if width < 512 or width > 1536:
                return None, "La larghezza deve essere compresa tra 512 e 1536 pixel."
            
            # Genera l'immagine
            return generator.generate_image(
                prompt=prompt,
                model=model,
                steps=steps,
                cfg_scale=cfg_scale,
                height=height,
                width=width,
                negative_prompt=negative_prompt
            )
        except Exception as e:
            return None, f"Errore: {str(e)}"
    
    # Crea i componenti dell'interfaccia
    with gr.Blocks(title="FLUX Nineteen.ai Image Generator") as interface:
        gr.Markdown("# FLUX Nineteen.ai Image Generator")
        gr.Markdown("Genera immagini utilizzando il modello FLUX.1-schnell tramite l'API di Nineteen.ai")
        
        with gr.Row():
            with gr.Column(scale=3):
                prompt_input = gr.Textbox(
                    label="Prompt",
                    placeholder="Descrivi l'immagine che desideri generare...",
                    lines=3
                )
                
                negative_prompt_input = gr.Textbox(
                    label="Prompt Negativo (opzionale)",
                    placeholder="Elementi da escludere dall'immagine...",
                    lines=2
                )
                
                model_input = gr.Dropdown(
                    generator.models,
                    label="Modello",
                    value=generator.default_model
                )
                
                with gr.Row():
                    steps_input = gr.Slider(
                        minimum=1,
                        maximum=50,
                        value=8,
                        step=1,
                        label="Passi di Inferenza"
                    )
                    cfg_input = gr.Slider(
                        minimum=1.0,
                        maximum=30.0,
                        value=3.0,
                        step=0.1,
                        label="Guidance Scale (CFG)"
                    )
                
                with gr.Row():
                    height_input = gr.Slider(
                        minimum=512,
                        maximum=1536,
                        value=1024,
                        step=64,
                        label="Altezza (px)"
                    )
                    width_input = gr.Slider(
                        minimum=512,
                        maximum=1536,
                        value=1024,
                        step=64,
                        label="Larghezza (px)"
                    )
                
                generate_button = gr.Button("Genera Immagine", variant="primary")
            
            with gr.Column(scale=4):
                output_image = gr.Image(label="Immagine Generata", type="pil")
                output_status = gr.Textbox(label="Stato", interactive=False)
        
        # Esempi di prompt
        with gr.Accordion("Esempi di Prompt", open=False):
            gr.Markdown("""
            ### Esempi di prompt ottimizzati per FLUX.1-schnell
            
            Clicca su uno degli esempi per utilizzarlo:
            """)
            
            examples = [
                ["A breathtaking view of the Dolomites at sunrise, golden light illuminating the jagged peaks, morning mist rising from the valley below, ultra-detailed, cinematic, 8K resolution, photorealistic"],
                ["Futuristic Tokyo cityscape at night, neon lights reflecting on wet streets after rain, towering skyscrapers with holographic advertisements, flying vehicles, photorealistic, cinematic lighting, 8K"],
                ["Portrait of a weathered old fisherman with deep wrinkles and piercing blue eyes, wearing a cable-knit sweater, salt and pepper beard, golden hour lighting, ultra-detailed skin texture, photorealistic"],
                ["Massive space station orbiting Jupiter, with Earth visible in the distance, detailed mechanical structures, solar panels, docking bays with spacecraft, photorealistic, NASA quality, 8K"],
                ["Bioluminescent forest at night with giant mushrooms, glowing plants, mystical atmosphere, small magical creatures, ultra-detailed vegetation, photorealistic textures, fantasy world with realistic lighting"]
            ]
            
            gr.Examples(
                examples=examples,
                inputs=prompt_input
            )
        
        # Collega il pulsante di generazione
        generate_button.click(
            generate_image_ui,
            inputs=[
                prompt_input, 
                model_input, 
                steps_input, 
                cfg_input, 
                height_input, 
                width_input, 
                negative_prompt_input
            ],
            outputs=[output_image, output_status]
        )
    
    return interface

# Funzione principale
def main():
    """Funzione principale"""
    # Crea il generatore
    generator = FluxNineteenGenerator()
    
    # Crea l'interfaccia
    interface = create_ui(generator)
    
    # Configura l'autenticazione
    username = os.getenv("GRADIO_USERNAME")
    password = os.getenv("GRADIO_PASSWORD")
    
    # Verifica se le credenziali sono disponibili
    if username and password:
        auth = (username, password)
        print(f"Autenticazione configurata con username: {username}")
    else:
        # Per test locali, disabilitiamo l'autenticazione
        auth = None
        print("Autenticazione disabilitata per test locali. Su HF Spaces, imposta GRADIO_USERNAME e GRADIO_PASSWORD.")
    
    # Avvia l'interfaccia con o senza autenticazione
    interface.launch(auth=auth)

if __name__ == "__main__":
    main()