Spaces:
Running
Running
import os | |
import gradio as gr | |
import base64 | |
from random import randint | |
from all_models import models | |
from io import BytesIO | |
from PIL import Image | |
from fastapi import FastAPI, Request | |
from deep_translator import GoogleTranslator | |
# CSS yang lebih lengkap dengan berbagai elemen styling | |
css_code = """ | |
/* General Styling */ | |
.gradio-container { | |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); | |
min-height: 100vh; | |
padding: 20px; | |
} | |
/* Textbox Styling */ | |
#custom_textbox { | |
min-height: 150px; | |
padding: 15px; | |
border-radius: 12px; | |
border: 2px solid #e0e0e0; | |
font-size: 16px; | |
background: rgba(255, 255, 255, 0.9); | |
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); | |
transition: all 0.3s ease; | |
} | |
#custom_textbox:focus { | |
border-color: #4facfe; | |
box-shadow: 0 0 0 3px rgba(79, 172, 254, 0.2); | |
outline: none; | |
} | |
/* Button Styling */ | |
#custom_gen_button { | |
background: linear-gradient(to right, #4facfe 0%, #00f2fe 100%); | |
color: white; | |
border: none; | |
border-radius: 12px; | |
padding: 12px 24px; | |
font-weight: 600; | |
font-size: 16px; | |
cursor: pointer; | |
transition: all 0.3s ease; | |
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
width: 100%; | |
margin-bottom: 10px; | |
} | |
#custom_gen_button:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); | |
} | |
#custom_stop_button { | |
background: linear-gradient(to right, #ff4d4d 0%, #f97878 100%); | |
color: white; | |
border: none; | |
border-radius: 12px; | |
padding: 12px 24px; | |
font-weight: 600; | |
font-size: 16px; | |
cursor: pointer; | |
transition: all 0.3s ease; | |
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
width: 100%; | |
} | |
#custom_stop_button:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); | |
} | |
/* Image Styling */ | |
#custom_image { | |
border-radius: 16px; | |
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); | |
transition: all 0.3s ease; | |
background: white; | |
padding: 10px; | |
max-width: 100%; | |
height: auto; | |
} | |
#custom_image:hover { | |
transform: scale(1.01); | |
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.15); | |
} | |
/* Dropdown Styling */ | |
.dark .dropdown-option { | |
background: #2d3748 !important; | |
} | |
.dark .dropdown-option:hover { | |
background: #4a5568 !important; | |
} | |
/* Panel Styling */ | |
.gr-box { | |
border-radius: 16px !important; | |
background: rgba(255, 255, 255, 0.8) !important; | |
backdrop-filter: blur(10px); | |
border: 1px solid rgba(255, 255, 255, 0.2) !important; | |
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1) !important; | |
padding: 20px !important; | |
} | |
/* Label Styling */ | |
.gr-label { | |
font-weight: 600 !important; | |
color: #2d3748 !important; | |
margin-bottom: 8px !important; | |
font-size: 16px !important; | |
} | |
/* Responsive Adjustments */ | |
@media (max-width: 768px) { | |
.gradio-container { | |
padding: 10px; | |
} | |
#custom_textbox { | |
min-height: 120px; | |
font-size: 14px; | |
} | |
#custom_gen_button, #custom_stop_button { | |
padding: 10px 15px; | |
font-size: 14px; | |
} | |
} | |
/* Animation for loading state */ | |
@keyframes pulse { | |
0% { opacity: 0.6; } | |
50% { opacity: 1; } | |
100% { opacity: 0.6; } | |
} | |
.loading { | |
animation: pulse 1.5s infinite; | |
} | |
""" | |
# Initialize translator | |
translator = GoogleTranslator(source='auto', target='en') | |
# Load models | |
models_load = {} | |
for model in models: | |
try: | |
models_load[model] = gr.load(f'models/{model}') | |
except Exception as error: | |
models_load[model] = gr.Interface(lambda txt: None, ['text'], ['image']) | |
app = FastAPI() | |
def gen_image(model_str, prompt): | |
if model_str == 'NA': | |
return None | |
# Translate prompt to English {noise} {klir} | |
translated_prompt = translator.translate(prompt) | |
noise = str(randint(0, 4294967296)) | |
klir = '| ultra detail, ultra elaboration, ultra quality, perfect' | |
return models_load[model_str](f'{translated_prompt}') | |
def image_to_base64(image): | |
buffered = BytesIO() | |
if isinstance(image, str): # if it's a file path | |
img = Image.open(image) | |
img.save(buffered, format="JPEG") | |
else: # if it's a PIL Image | |
image.save(buffered, format="JPEG") | |
return base64.b64encode(buffered.getvalue()).decode() | |
# API endpoint | |
async def api_generate(request: Request): | |
data = await request.json() | |
model = data.get('model', models[0]) | |
prompt = data.get('prompt', '') | |
if model not in models: | |
return {"error": "Model not found"} | |
# Translate prompt to English for API endpoint too | |
translated_prompt = translator.translate(prompt) | |
image = gen_image(model, translated_prompt) | |
if image is None: | |
return {"error": "Image generation failed"} | |
base64_str = image_to_base64(image) | |
return { | |
"status": "success", | |
"model": model, | |
"original_prompt": prompt, | |
"translated_prompt": translated_prompt, | |
"image_base64": base64_str, | |
"image_format": "jpeg" | |
} | |
# Gradio Interface | |
def make_me(): | |
with gr.Row(): | |
with gr.Column(scale=4): | |
txt_input = gr.Textbox( | |
label='Your prompt:', | |
lines=4, | |
container=False, | |
elem_id="custom_textbox", | |
placeholder="Describe the image you want to generate...", | |
interactive=True | |
) | |
with gr.Column(scale=1): | |
gen_button = gr.Button('Generate image', elem_id="custom_gen_button", variant="primary") | |
stop_button = gr.Button('Stop', variant='secondary', interactive=False, | |
elem_id="custom_stop_button") | |
def on_generate_click(): | |
return gr.Button('Generating...', interactive=False, elem_id="custom_gen_button", variant="stop"), gr.Button('Stop', variant='secondary', interactive=True, elem_id="custom_stop_button") | |
def on_stop_click(): | |
return gr.Button('Generate image', elem_id="custom_gen_button", variant="primary"), gr.Button('Stop', variant='secondary', interactive=False, elem_id="custom_stop_button") | |
gen_button.click(on_generate_click, inputs=None, outputs=[gen_button, stop_button]) | |
stop_button.click(on_stop_click, inputs=None, outputs=[gen_button, stop_button]) | |
with gr.Row(): | |
with gr.Column(): | |
model_dropdown = gr.Dropdown(models, label="Select Model", | |
value=models[0] if models else None, | |
interactive=True, | |
elem_classes=["model-selector"]) | |
output_image = gr.Image( | |
label="Generated Image", | |
width=512, | |
height=768, | |
elem_id="custom_image", | |
show_label=True, | |
interactive=False | |
) | |
# JSON output | |
json_output = gr.JSON(label="API Response", elem_id="api-response") | |
def generate_wrapper(model_str, prompt): | |
# Translate prompt to English | |
translated_prompt = translator.translate(prompt) | |
image = gen_image(model_str, translated_prompt) | |
if image is None: | |
return None, {"error": "Generation failed"} | |
base64_str = image_to_base64(image) | |
response = { | |
"status": "success", | |
"model": model_str, | |
"original_prompt": prompt, | |
"translated_prompt": translated_prompt, | |
"image_base64": base64_str, | |
"image_format": "jpeg" | |
} | |
return image, response | |
gen_event = gen_button.click(generate_wrapper, [model_dropdown, txt_input], | |
[output_image, json_output]) | |
stop_button.click(on_stop_click, inputs=None, | |
outputs=[gen_button, stop_button], cancels=[gen_event]) | |
# Create Gradio app | |
with gr.Blocks(css=css_code, theme=gr.themes.Soft()) as demo: | |
gr.Markdown("# AI Image Generator", elem_id="title") | |
gr.Markdown("Generate stunning images from text prompts using advanced AI models", elem_id="subtitle") | |
make_me() | |
# Enable queue before mounting | |
demo.queue() | |
# Mount Gradio app to FastAPI | |
app = gr.mount_gradio_app(app, demo, path="/") | |
if __name__ == "__main__": | |
import uvicorn | |
uvicorn.run(app, host="0.0.0.0", port=7860) |