import tkinter as tk from tkinter import ttk, scrolledtext, messagebox from PIL import Image, ImageTk import os from datetime import datetime import json import requests from io import BytesIO import base64 import time class DrawingTutorialApp: def __init__(self, root): self.root = root self.root.title("Générateur de Tutoriel de Dessin") # Configuration de l'API Hugging Face self.API_URL = "https://api-inference.huggingface.co/models/stabilityai/sdxl-turbo" # Remplacez par votre token # Configuration des styles self.setup_styles() # Variables self.current_step = 0 self.generated_images = [] self.steps_description = [] # Création de l'interface self.create_interface() def setup_styles(self): style = ttk.Style() style.configure('TButton', padding=5) style.configure('TFrame', padding=5) def create_interface(self): # Frame principal main_frame = ttk.Frame(self.root) main_frame.pack(expand=True, fill='both', padx=10, pady=10) # Zone de description desc_frame = ttk.LabelFrame(main_frame, text="Description du dessin") desc_frame.pack(fill='x', pady=5) self.description_text = scrolledtext.ScrolledText(desc_frame, height=4) self.description_text.pack(fill='x', padx=5, pady=5) # Boutons de contrôle control_frame = ttk.Frame(main_frame) control_frame.pack(fill='x', pady=5) ttk.Button(control_frame, text="Générer les étapes", command=self.generate_steps).pack(side='left', padx=5) ttk.Button(control_frame, text="Étape précédente", command=self.previous_step).pack(side='left', padx=5) ttk.Button(control_frame, text="Étape suivante", command=self.next_step).pack(side='left', padx=5) # Zone d'affichage self.display_frame = ttk.LabelFrame(main_frame, text="Aperçu de l'étape") self.display_frame.pack(fill='both', expand=True, pady=5) self.image_label = ttk.Label(self.display_frame) self.image_label.pack(padx=5, pady=5) # Zone de description des étapes self.step_description = ttk.Label(self.display_frame, text="Aucune étape générée", wraplength=400) self.step_description.pack(padx=5, pady=5) # Indicateur de progression self.progress_label = ttk.Label(main_frame, text="") self.progress_label.pack(pady=5) def query_image(self, prompt): """Génère une image via l'API Hugging Face""" try: response = requests.post( self.API_URL, headers=self.headers, json={ "inputs": prompt, "parameters": { "num_inference_steps": 1, "guidance_scale": 0.0, } } ) # Vérifier si la requête a réussi if response.status_code != 200: raise Exception(f"Erreur API: {response.status_code}") # Vérifier si le modèle est en cours de chargement if response.status_code == 200 and "error" in response.json(): if "currently loading" in response.json()["error"]: print("Modèle en cours de chargement, attente...") time.sleep(20) # Attendre et réessayer return self.query_image(prompt) # Traiter la réponse image_bytes = response.content image = Image.open(BytesIO(image_bytes)) return image except Exception as e: print(f"Erreur lors de la génération d'image: {e}") messagebox.showerror("Erreur", f"Erreur lors de la génération d'image: {e}") return None def generate_steps(self): description = self.description_text.get("1.0", "end-1c") if not description: messagebox.showwarning("Attention", "Veuillez entrer une description") return # Définition des étapes et prompts associés steps = [ { "name": "Esquisse de base et formes géométriques", "prompt": f"basic sketch with geometric shapes of {description}, lineart, sketch style, black and white" }, { "name": "Ajout des détails principaux", "prompt": f"detailed sketch of {description}, more defined lines, black and white drawing" }, { "name": "Affinement des lignes", "prompt": f"refined line drawing of {description}, clean lines, professional sketch" }, { "name": "Ajout des ombres de base", "prompt": f"shaded sketch of {description}, basic shadows and values, grayscale" }, { "name": "Colorisation de base", "prompt": f"basic colored version of {description}, flat colors, simple coloring" }, { "name": "Ajout des détails de couleur", "prompt": f"detailed colored drawing of {description}, with shading and color details" }, { "name": "Finalisation et mise en valeur", "prompt": f"final polished illustration of {description}, complete with details and professional finish" } ] # Réinitialisation des listes self.generated_images = [] self.steps_description = [] # Génération des images pour chaque étape for i, step in enumerate(steps): self.progress_label.configure( text=f"Génération de l'étape {i+1}/{len(steps)}: {step['name']}") self.root.update() image = self.query_image(step['prompt']) if image: self.generated_images.append(image) self.steps_description.append(f"{step['name']}\n{step['prompt']}") else: messagebox.showerror("Erreur", f"Échec de la génération pour l'étape {i+1}") continue if self.generated_images: self.progress_label.configure(text="Génération terminée!") self.current_step = 0 self.update_display() else: self.progress_label.configure(text="Échec de la génération") def update_display(self): if not self.generated_images: return image = self.generated_images[self.current_step] # Redimensionner l'image si nécessaire image = image.resize((400, 400), Image.Resampling.LANCZOS) photo = ImageTk.PhotoImage(image) self.image_label.configure(image=photo) self.image_label.image = photo step_text = f"Étape {self.current_step + 1}/{len(self.generated_images)}\n" step_text += self.steps_description[self.current_step] self.step_description.configure(text=step_text) def previous_step(self): if self.current_step > 0: self.current_step -= 1 self.update_display() def next_step(self): if self.current_step < len(self.generated_images) - 1: self.current_step += 1 self.update_display() def main(): root = tk.Tk() app = DrawingTutorialApp(root) root.mainloop() if __name__ == "__main__": main()