import gradio as gr import requests from PIL import Image from io import BytesIO import urllib.parse import base64 import json import time # ==================== WORKING FREE APIs ==================== def craiyon_generate(prompt, width=1024, height=1024, seed=0): """ Craiyon (formerly DALL-E mini) - Unlimited, no signup required Community-maintained API endpoint """ try: # Craiyon API endpoint (unofficial but working) url = "https://backend.craiyon.com/generate" payload = { "prompt": prompt, "model": "photo" # Options: art, photo, drawing, none } headers = { "Content-Type": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" } response = requests.post(url, json=payload, headers=headers, timeout=60) if response.status_code == 200: data = response.json() if "images" in data and len(data["images"]) > 0: # Craiyon returns base64 images img_data = base64.b64decode(data["images"][0]) return Image.open(BytesIO(img_data)), "Craiyon (Unlimited)" else: return None, "Craiyon: No images in response" else: return None, f"Craiyon: HTTP {response.status_code}" except Exception as e: return None, f"Craiyon Failed: {str(e)}" def pollinations_generate(prompt, width=1024, height=1024, seed=0): """ Pollinations.ai - Free, no signup, but occasionally down """ try: encoded_prompt = urllib.parse.quote(prompt) url = f"https://image.pollinations.ai/prompt/{encoded_prompt}?width={width}&height={height}&nologo=true&seed={seed if seed > 0 else int(time.time())}" response = requests.get(url, timeout=30) if response.status_code == 200: return Image.open(BytesIO(response.content)), "Pollinations.ai" else: return None, f"Pollinations: HTTP {response.status_code}" except Exception as e: return None, f"Pollinations Failed: {str(e)}" def deepai_generate(prompt, width=1024, height=1024, seed=0): """ DeepAI - No signup, stable, but lower quality """ try: url = "https://api.deepai.org/api/text2img" # DeepAI allows a demo key for limited free use headers = { 'api-key': 'tryit-demo-key', } data = { 'text': prompt, } response = requests.post(url, headers=headers, data=data, timeout=40) if response.status_code == 200: result = response.json() if 'output_url' in result: img_response = requests.get(result['output_url'], timeout=20) if img_response.status_code == 200: return Image.open(BytesIO(img_response.content)), "DeepAI" return None, f"DeepAI: HTTP {response.status_code}" except Exception as e: return None, f"DeepAI Failed: {str(e)}" # ==================== MAIN GENERATION LOGIC ==================== def generate_with_fallback(prompt, width=1024, height=1024, seed=0, primary="Craiyon (Unlimited)"): """ Try multiple free services in order """ if not prompt: return None, "âš ī¸ Please enter a prompt!" services = { "Craiyon (Unlimited)": craiyon_generate, "Pollinations.ai": pollinations_generate, "DeepAI (Stable)": deepai_generate, } errors = [] # Try primary first if primary in services: try: print(f"🔄 Trying {primary}...") img, status = services[primary](prompt, width, height, seed) if img: return img, f"✅ Success! ({status})" else: errors.append(f"{primary}: {status}") except Exception as e: errors.append(f"{primary}: {str(e)}") # Try others as fallback for name, func in services.items(): if name == primary: continue try: print(f"🔄 Trying fallback: {name}...") img, status = func(prompt, width, height, seed) if img: return img, f"✅ Success! ({status} - Fallback)" else: errors.append(f"{name}: {status}") except Exception as e: errors.append(f"{name}: {str(e)}") # All failed error_msg = "❌ All services failed:\\n" + "\\n".join(errors) return None, error_msg # ==================== GRADIO UI ==================== with gr.Blocks(title="Free Image Generator") as demo: gr.Markdown(""" # 🎨 Free Image Generator (Working Edition) **No API Keys â€ĸ Multiple Providers â€ĸ Craiyon + Pollinations + DeepAI** Made with â¤ī¸ by Srijan Gajurel """) with gr.Row(): with gr.Column(scale=1): prompt = gr.Textbox( label="📝 Prompt", lines=3, placeholder="Describe your image...", value="A beautiful sunset over mountains, cinematic lighting" ) with gr.Row(): width = gr.Slider(512, 1024, 1024, step=64, label="Width") height = gr.Slider(512, 1024, 1024, step=64, label="Height") seed = gr.Number(0, label="🎲 Seed (0 for random)", precision=0) primary_service = gr.Radio( choices=["Craiyon (Unlimited)", "Pollinations.ai", "DeepAI (Stable)"], value="Craiyon (Unlimited)", label="🚀 Primary Service" ) with gr.Accordion("â„šī¸ Service Info", open=False): gr.Markdown(""" **Craiyon (Recommended)** - ✅ Unlimited generations - ✅ No signup required - âš ī¸ 1024x1024 only (other sizes ignored) - âš ī¸ Lower quality than premium models **Pollinations.ai** - ✅ High quality - ✅ Custom sizes supported - âš ī¸ Occasionally down for maintenance **DeepAI** - ✅ Stable and reliable - âš ī¸ Lower quality - âš ī¸ Slower generation """) btn = gr.Button("🎨 Generate Image", variant="primary") status = gr.Textbox(label="Status", value="Ready") with gr.Column(scale=1): output_img = gr.Image(label="Generated Image", type="pil", height=600) examples = gr.Examples( examples=[ ["A futuristic cyberpunk city at night, neon lights", 1024, 1024, 0, "Craiyon (Unlimited)"], ["Portrait of a cat wearing a crown, oil painting", 1024, 1024, 42, "Pollinations.ai"], ["Space nebula with vibrant colors and stars", 1024, 1024, 0, "DeepAI (Stable)"], ], inputs=[prompt, width, height, seed, primary_service] ) btn.click( fn=generate_with_fallback, inputs=[prompt, width, height, seed, primary_service], outputs=[output_img, status] ) if __name__ == "__main__": print("🚀 Starting Free Image Generator...") print("đŸ› ī¸ Services: Craiyon (Primary), Pollinations (Backup), DeepAI (Backup)") demo.launch()