|
import gradio as gr |
|
import os |
|
from PIL import Image, ImageDraw, ImageFont, ImageEnhance |
|
import requests |
|
import io |
|
import json |
|
|
|
|
|
PRO_STYLES = { |
|
"Neo Vintage": { |
|
"prompt_prefix": "professional high-end vintage poster, screen printing style, halftone textures, limited color palette", |
|
"guidance": 13.5, |
|
"steps": 75, |
|
"negative": "photorealistic, 3d, oversaturated, amateur", |
|
"reference": "modern vintage illustration masters" |
|
}, |
|
"Art Contemporain": { |
|
"prompt_prefix": "contemporary art poster, bold artistic composition, professional design, gallery quality", |
|
"guidance": 12.5, |
|
"steps": 70, |
|
"negative": "basic, simple, childish", |
|
"reference": "modern art gallery style" |
|
}, |
|
"Illustration Éditoriale": { |
|
"prompt_prefix": "professional editorial illustration, sophisticated art style, magazine quality", |
|
"guidance": 14.0, |
|
"steps": 80, |
|
"negative": "basic drawing, sketchy, unrefined", |
|
"reference": "high-end magazine art" |
|
}, |
|
"Design Minimaliste Plus": { |
|
"prompt_prefix": "premium minimalist design, refined composition, luxury poster style", |
|
"guidance": 11.5, |
|
"steps": 65, |
|
"negative": "cluttered, busy, complex", |
|
"reference": "scandinavian design principles" |
|
} |
|
} |
|
|
|
|
|
ARTISTIC_COLLECTIONS = { |
|
"Portraits Animaliers Pro": { |
|
"base_prompts": [ |
|
"majestic animal portrait", |
|
"artistic wildlife illustration", |
|
"powerful animal character" |
|
], |
|
"style_elements": [ |
|
"dramatic lighting", |
|
"expressive eyes", |
|
"detailed textures", |
|
"strong personality" |
|
], |
|
"negative": "cute, cartoon, realistic photo", |
|
"compositions": [ |
|
"centered portrait", |
|
"dramatic angle", |
|
"close-up detail" |
|
] |
|
}, |
|
"Nature Graphique": { |
|
"base_prompts": [ |
|
"graphic botanical art", |
|
"stylized nature elements", |
|
"organic patterns" |
|
], |
|
"style_elements": [ |
|
"decorative details", |
|
"flowing lines", |
|
"dynamic composition" |
|
], |
|
"negative": "photographic, plain, realistic", |
|
"compositions": [ |
|
"geometric arrangement", |
|
"pattern layout", |
|
"abstract interpretation" |
|
] |
|
}, |
|
"Urban Art Plus": { |
|
"base_prompts": [ |
|
"sophisticated urban art", |
|
"street art fusion", |
|
"modern city aesthetic" |
|
], |
|
"style_elements": [ |
|
"street art textures", |
|
"urban patterns", |
|
"graffiti elements" |
|
], |
|
"negative": "amateur graffiti, messy, unrefined", |
|
"compositions": [ |
|
"dynamic urban composition", |
|
"street art layout", |
|
"modern city vibes" |
|
] |
|
} |
|
} |
|
|
|
|
|
PRO_DIMENSIONS = { |
|
"A4+": (1152, 1634), |
|
"A3+": (1634, 2314), |
|
"A2+": (2314, 3271), |
|
"A1+": (3271, 4628), |
|
"A0+": (4628, 6544) |
|
} |
|
|
|
class EquityArtisanPro: |
|
def __init__(self): |
|
self.model_url = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0" |
|
self.headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_TOKEN')}"} |
|
|
|
def generate_artwork(self, format_size, orientation, style, collection, prompt, quality, creativity): |
|
try: |
|
|
|
width, height = PRO_DIMENSIONS[format_size] |
|
if orientation == "Paysage": |
|
width, height = height, width |
|
|
|
|
|
style_config = PRO_STYLES[style] |
|
collection_config = ARTISTIC_COLLECTIONS.get(collection) |
|
|
|
|
|
enhanced_prompt = self._build_enhanced_prompt( |
|
base_prompt=prompt, |
|
style_config=style_config, |
|
collection_config=collection_config |
|
) |
|
|
|
|
|
payload = { |
|
"inputs": enhanced_prompt, |
|
"parameters": { |
|
"negative_prompt": self._build_negative_prompt(style_config, collection_config), |
|
"num_inference_steps": self._calculate_steps(style_config, quality), |
|
"guidance_scale": self._calculate_guidance(style_config, creativity), |
|
"width": width, |
|
"height": height, |
|
"seed": int(creativity * 1000) |
|
} |
|
} |
|
|
|
print(f"Generating with enhanced prompt: {enhanced_prompt[:100]}...") |
|
|
|
response = requests.post( |
|
self.model_url, |
|
headers=self.headers, |
|
json=payload, |
|
timeout=60 |
|
) |
|
|
|
if response.status_code == 200: |
|
image = Image.open(io.BytesIO(response.content)) |
|
image = self._post_process_image(image, quality) |
|
return image, "✨ Chef d'œuvre créé avec succès!" |
|
else: |
|
return None, f"⚠️ Erreur {response.status_code}: {response.text}" |
|
|
|
except Exception as e: |
|
print(f"Error: {str(e)}") |
|
return None, f"⚠️ Erreur: {str(e)}" |
|
|
|
def _build_enhanced_prompt(self, base_prompt, style_config, collection_config=None): |
|
prompt_parts = [ |
|
style_config["prompt_prefix"], |
|
base_prompt |
|
] |
|
|
|
if collection_config: |
|
prompt_parts.extend([ |
|
f"in style of {', '.join(collection_config['style_elements'])}", |
|
f"with {', '.join(collection_config['base_prompts'])}", |
|
f"featuring {', '.join(collection_config['compositions'])}" |
|
]) |
|
|
|
return ", ".join(prompt_parts) + ", professional poster design, masterpiece quality" |
|
|
|
def _build_negative_prompt(self, style_config, collection_config=None): |
|
negative_parts = [ |
|
style_config["negative"], |
|
"poor quality, amateur design, basic composition" |
|
] |
|
|
|
if collection_config: |
|
negative_parts.append(collection_config["negative"]) |
|
|
|
return ", ".join(negative_parts) |
|
|
|
def _calculate_steps(self, style_config, quality): |
|
base_steps = style_config["steps"] |
|
return int(base_steps * (quality/85)) |
|
|
|
def _calculate_guidance(self, style_config, creativity): |
|
base_guidance = style_config["guidance"] |
|
return base_guidance * (creativity/10) |
|
|
|
def _post_process_image(self, image, quality): |
|
if quality > 85: |
|
enhancer = ImageEnhance.Contrast(image) |
|
image = enhancer.enhance(1.2) |
|
enhancer = ImageEnhance.Sharpness(image) |
|
image = enhancer.enhance(1.3) |
|
return image |
|
|
|
def create_interface(): |
|
artisan = EquityArtisanPro() |
|
|
|
with gr.Blocks(theme=gr.themes.Soft( |
|
primary_hue="indigo", |
|
secondary_hue="purple", |
|
)) as app: |
|
gr.HTML(""" |
|
<div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #4F46E5 0%, #7C3AED 100%); border-radius: 16px; margin-bottom: 24px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);"> |
|
<h1 style="color: white; font-size: 2.5em; margin-bottom: 10px;">🎨 Equity Artisan 3.0</h1> |
|
<p style="color: #E5E7EB; font-size: 1.2em;">Créez des œuvres d'art uniques avec notre IA spécialisée</p> |
|
</div> |
|
""") |
|
|
|
with gr.Row(): |
|
|
|
with gr.Column(scale=1): |
|
with gr.Group(): |
|
gr.Markdown("### 📐 Format & Style") |
|
format_choice = gr.Dropdown( |
|
choices=list(PRO_DIMENSIONS.keys()), |
|
value="A4+", |
|
label="Format", |
|
info="Formats optimisés pour qualité professionnelle" |
|
) |
|
orientation = gr.Radio( |
|
choices=["Portrait", "Paysage"], |
|
value="Portrait", |
|
label="Orientation" |
|
) |
|
style = gr.Dropdown( |
|
choices=list(PRO_STYLES.keys()), |
|
value="Neo Vintage", |
|
label="Style Artistique", |
|
info="Styles inspirés des grands maîtres" |
|
) |
|
|
|
with gr.Group(): |
|
gr.Markdown("### 🎨 Vision Artistique") |
|
collection = gr.Dropdown( |
|
choices=list(ARTISTIC_COLLECTIONS.keys()), |
|
label="Collection", |
|
info="Thèmes artistiques spécialisés" |
|
) |
|
prompt = gr.Textbox( |
|
lines=3, |
|
label="Description", |
|
placeholder="Décrivez votre vision artistique...", |
|
info="Soyez précis et créatif" |
|
) |
|
|
|
with gr.Group(): |
|
gr.Markdown("### ✨ Paramètres Créatifs") |
|
quality = gr.Slider( |
|
minimum=70, |
|
maximum=100, |
|
value=85, |
|
label="Qualité Artistique", |
|
info="Influence la finesse des détails" |
|
) |
|
creativity = gr.Slider( |
|
minimum=7, |
|
maximum=15, |
|
value=10, |
|
label="Expression Créative", |
|
info="Balance entre fidélité et originalité" |
|
) |
|
|
|
generate_btn = gr.Button("✨ Créer", variant="primary", scale=1) |
|
|
|
|
|
with gr.Column(scale=2): |
|
image_output = gr.Image( |
|
label="Votre Création", |
|
type="pil" |
|
) |
|
status = gr.Textbox( |
|
label="Statut", |
|
interactive=False |
|
) |
|
|
|
|
|
generate_btn.click( |
|
artisan.generate_artwork, |
|
inputs=[ |
|
format_choice, |
|
orientation, |
|
style, |
|
collection, |
|
prompt, |
|
quality, |
|
creativity |
|
], |
|
outputs=[image_output, status] |
|
) |
|
|
|
return app |
|
|
|
if __name__ == "__main__": |
|
app = create_interface() |
|
app.launch() |