import gradio as gr import numpy as np import random import torch from diffusers import DiffusionPipeline # Load the model dtype = torch.bfloat16 if torch.cuda.is_available() else torch.float32 device = "cuda" if torch.cuda.is_available() else "cpu" pipe = DiffusionPipeline.from_pretrained("black-forest-labs/FLUX.1-schnell", torch_dtype=dtype).to(device) # Constants MAX_SEED = np.iinfo(np.int32).max MAX_IMAGE_SIZE = 2048 # Style list for prompt customization style_list = [ {"name": "D&D Art", "prompt": "dungeons & dragons style artwork {prompt}. d&d style, key visual, vibrant, studio anime, highly detailed", "negative_prompt": "photo, deformed, black and white, realism, disfigured, low contrast"}, {"name": "Dark Fantasy", "prompt": "dark and moody dungeons & dragons artwork of {prompt}. gothic ruins, shadowy figures, haunting atmospheres, grim villains, muted colors, intricate textures, sinister undertones", "negative_prompt": "bright, cheerful, cartoonish, lighthearted, futuristic, deformed"}, {"name": "Epic Battle", "prompt": "dynamic dungeons & dragons artwork of {prompt}. epic battle scene, legendary heroes, fierce monsters, intense action, dramatic lighting, high-detail environment, magical effects, vibrant colors", "negative_prompt": "peaceful, mundane, low energy, modern, sci-fi, simplistic, cartoonish, low contrast"}, {"name": "(No style)", "prompt": "{prompt}", "negative_prompt": ""}, ] styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in style_list} STYLE_NAMES = list(styles.keys()) DEFAULT_STYLE_NAME = "D&D Art" # Function to apply selected style def apply_style(style_name: str, positive: str, negative: str = ""): p, n = styles.get(style_name, styles[DEFAULT_STYLE_NAME]) return p.replace("{prompt}", positive), n + (negative or "") # Inference function def infer( prompt, style, seed=42, randomize_seed=False, width=1024, height=1024, num_inference_steps=4, batch_size=1, positive_override=None, negative_override=None, progress=gr.Progress(track_tqdm=True), ): if randomize_seed: seed = random.randint(0, MAX_SEED) images = [] for _ in range(batch_size): # Apply custom styles if specified if positive_override and negative_override: styled_prompt = positive_override.replace("{prompt}", prompt) negative_prompt = negative_override else: styled_prompt, negative_prompt = apply_style(style, prompt) generator = torch.manual_seed(seed) image = pipe( prompt=styled_prompt, width=width, height=height, num_inference_steps=num_inference_steps, generator=generator, guidance_scale=0.0, negative_prompt=negative_prompt, ).images[0] images.append(image) return images, seed # Example prompts examples = [ ["A heroic adventurer wielding a flaming sword standing on a cliff", "D&D Art"], ["A mystical library with ancient scrolls and glowing runes", "Dark Fantasy"], ["A ferocious dragon breathing fire in a dark cavern", "Epic Battle"], ] # Predefined previews for styles style_previews = { "D&D Art": "https://example.com/dnd_preview.png", "Dark Fantasy": "https://example.com/dark_fantasy_preview.png", "Epic Battle": "https://example.com/epic_battle_preview.png", "(No style)": "https://example.com/no_style_preview.png", } # Custom CSS for a Dungeons & Dragons theme css = """ body { background-color: #1b1b1b; font-family: 'Cinzel', serif; color: #f5f5f5; background-image: url('https://www.transparenttextures.com/patterns/dark-matter.png'); } #col-container { margin: 0 auto; max-width: 550px; padding: 15px; border: 4px solid #8b4513; background: linear-gradient(145deg, #2e2b2a, #3a3433); border-radius: 15px; box-shadow: 0 0 20px rgba(0, 0, 0, 0.8); } """ # Interface with gr.Blocks(css=css) as demo: with gr.Column(elem_id="col-container"): # Title and Description gr.Markdown( """ # 🛡️ ChatDnD.net 🛡️ # ⚔️ Dungeons & Dragons Image Generator ⚔️ **Unleash Your Imagination!** Create heroes, maps, quests, and epic scenes to bring your campaigns to life. Tailored for adventurers seeking inspiration or Dungeon Masters constructing their next grand story.
[Visit Our Website](https://chatdnd.net) | [Support Us](https://buymeacoffee.com/watchoutformike) """ ) # Style previews with gr.Row(): for name, url in style_previews.items(): gr.Image(value=url, label=name) # Prompt input and style selector with gr.Row(): prompt = gr.Textbox( label="🎲 Describe Your Vision:", lines=3, placeholder="Describe your hero, monster, or legendary landscape..." ) style = gr.Dropdown( label="🎨 Select a Style", choices=STYLE_NAMES, value=DEFAULT_STYLE_NAME, ) # Custom style builder with gr.Accordion("🛠️ Custom Style Builder", open=False): positive_override = gr.Textbox( label="Custom Positive Prompt", placeholder="Enter custom positive prompt. Use '{prompt}' as a placeholder for the main description." ) negative_override = gr.Textbox( label="Custom Negative Prompt", placeholder="Enter custom negative prompt for exclusion criteria." ) # Run button and result display with gr.Row(): run_button = gr.Button("Generate Image") results = gr.Gallery(label="🖼️ Generated Images") # Advanced settings with gr.Accordion("⚙️ Advanced Settings", open=False): seed = gr.Slider( label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0, ) randomize_seed = gr.Checkbox(label="Randomize Seed", value=True) with gr.Row(): width = gr.Slider( label="Width", minimum=256, maximum=MAX_IMAGE_SIZE, step=32, value=1024, ) height = gr.Slider( label="Height", minimum=256, maximum=MAX_IMAGE_SIZE, step=32, value=1024, ) num_inference_steps = gr.Slider( label="Inference Steps", minimum=1, maximum=50, step=1, value=4, ) batch_size = gr.Slider( label="Batch Size", minimum=1, maximum=10, step=1, value=1, ) # Examples with styles gr.Examples( examples=examples, inputs=[prompt, style], outputs=[results], fn=infer, cache_examples="lazy", ) # Interactivity run_button.click( fn=infer, inputs=[prompt, style, seed, randomize_seed, width, height, num_inference_steps, batch_size, positive_override, negative_override], outputs=[results, seed], ) # Launch the demo demo.launch()