Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>AI Image Generator</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #6e8efb, #a777e3); | |
| } | |
| .image-placeholder { | |
| background: linear-gradient(45deg, #f3f4f6 25%, #e5e7eb 25%, #e5e7eb 50%, #f3f4f6 50%, #f3f4f6 75%, #e5e7eb 75%, #e5e7eb 100%); | |
| background-size: 20px 20px; | |
| } | |
| .prompt-input:focus { | |
| box-shadow: 0 0 0 3px rgba(167, 119, 227, 0.3); | |
| } | |
| .loading-spinner { | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| .fade-in { | |
| animation: fadeIn 0.5s ease-in-out; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; } | |
| to { opacity: 1; } | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen gradient-bg text-gray-100"> | |
| <div class="container mx-auto px-4 py-12"> | |
| <header class="text-center mb-12"> | |
| <h1 class="text-4xl md:text-5xl font-bold mb-4">AI Image Generator</h1> | |
| <p class="text-xl opacity-90">Transform your imagination into stunning visuals</p> | |
| </header> | |
| <main class="max-w-4xl mx-auto"> | |
| <div class="bg-white bg-opacity-10 backdrop-blur-lg rounded-xl shadow-2xl p-6 mb-8"> | |
| <div class="flex flex-col md:flex-row gap-6"> | |
| <div class="flex-1"> | |
| <div class="mb-6"> | |
| <label for="prompt" class="block text-lg font-medium mb-2">Describe your image</label> | |
| <div class="relative"> | |
| <textarea | |
| id="prompt" | |
| rows="4" | |
| class="w-full px-4 py-3 rounded-lg bg-white bg-opacity-20 border border-white border-opacity-30 prompt-input text-white placeholder-white placeholder-opacity-70 focus:outline-none focus:border-opacity-50 transition-all" | |
| placeholder="A futuristic cityscape at sunset with flying cars..." | |
| ></textarea> | |
| <div class="absolute right-3 bottom-3 flex gap-2"> | |
| <button id="clear-btn" class="p-2 rounded-full bg-white bg-opacity-20 hover:bg-opacity-30 transition-all"> | |
| <i class="fas fa-eraser"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mb-6"> | |
| <label class="block text-lg font-medium mb-2">Style</label> | |
| <div class="grid grid-cols-2 sm:grid-cols-4 gap-3"> | |
| <button class="style-btn px-4 py-2 rounded-lg bg-white bg-opacity-10 hover:bg-opacity-20 border border-white border-opacity-20 transition-all active:bg-opacity-30" data-style="realistic"> | |
| <i class="fas fa-camera mr-2"></i> Realistic | |
| </button> | |
| <button class="style-btn px-4 py-2 rounded-lg bg-white bg-opacity-10 hover:bg-opacity-20 border border-white border-opacity-20 transition-all active:bg-opacity-30" data-style="cartoon"> | |
| <i class="fas fa-paint-brush mr-2"></i> Cartoon | |
| </button> | |
| <button class="style-btn px-4 py-2 rounded-lg bg-white bg-opacity-10 hover:bg-opacity-20 border border-white border-opacity-20 transition-all active:bg-opacity-30" data-style="fantasy"> | |
| <i class="fas fa-dragon mr-2"></i> Fantasy | |
| </button> | |
| <button class="style-btn px-4 py-2 rounded-lg bg-white bg-opacity-10 hover:bg-opacity-20 border border-white border-opacity-20 transition-all active:bg-opacity-30" data-style="minimal"> | |
| <i class="fas fa-shapes mr-2"></i> Minimal | |
| </button> | |
| </div> | |
| </div> | |
| <div class="flex flex-wrap gap-4"> | |
| <button id="generate-btn" class="flex-1 px-6 py-3 bg-purple-600 hover:bg-purple-700 rounded-lg font-semibold flex items-center justify-center gap-2 transition-all transform hover:scale-105 active:scale-95"> | |
| <i class="fas fa-magic"></i> Generate Image | |
| </button> | |
| <button id="random-btn" class="px-6 py-3 bg-white bg-opacity-10 hover:bg-opacity-20 rounded-lg font-semibold flex items-center justify-center gap-2 transition-all"> | |
| <i class="fas fa-random"></i> Random | |
| </button> | |
| </div> | |
| </div> | |
| <div class="flex-1"> | |
| <div class="aspect-square w-full rounded-xl overflow-hidden relative image-placeholder"> | |
| <div id="image-container" class="w-full h-full flex items-center justify-center"> | |
| <div class="text-center p-6"> | |
| <i class="fas fa-image text-5xl mb-4 opacity-30"></i> | |
| <p class="opacity-70">Your generated image will appear here</p> | |
| </div> | |
| </div> | |
| <div id="loading-indicator" class="absolute inset-0 bg-black bg-opacity-70 flex items-center justify-center hidden"> | |
| <div class="text-center"> | |
| <i class="fas fa-spinner loading-spinner text-4xl mb-4"></i> | |
| <p>Creating your masterpiece...</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="download-container" class="mt-4 hidden"> | |
| <button id="download-btn" class="w-full px-4 py-2 bg-green-600 hover:bg-green-700 rounded-lg font-medium flex items-center justify-center gap-2"> | |
| <i class="fas fa-download"></i> Download Image | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white bg-opacity-10 backdrop-blur-lg rounded-xl shadow-2xl p-6"> | |
| <h2 class="text-xl font-semibold mb-4">Recent Creations</h2> | |
| <div id="gallery" class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4"> | |
| <!-- Gallery items will be added here --> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <footer class="text-center py-6 text-white text-opacity-70"> | |
| <p>© 2023 AI Image Generator | Powered by DALL-E Mini</p> | |
| </footer> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| const promptInput = document.getElementById('prompt'); | |
| const generateBtn = document.getElementById('generate-btn'); | |
| const randomBtn = document.getElementById('random-btn'); | |
| const clearBtn = document.getElementById('clear-btn'); | |
| const imageContainer = document.getElementById('image-container'); | |
| const loadingIndicator = document.getElementById('loading-indicator'); | |
| const downloadContainer = document.getElementById('download-container'); | |
| const downloadBtn = document.getElementById('download-btn'); | |
| const gallery = document.getElementById('gallery'); | |
| const styleButtons = document.querySelectorAll('.style-btn'); | |
| let currentStyle = 'realistic'; | |
| let generatedImages = []; | |
| // Sample prompts for random button | |
| const samplePrompts = [ | |
| "A cyberpunk city with neon lights and rain", | |
| "A majestic dragon flying over a medieval castle", | |
| "An astronaut exploring an alien jungle", | |
| "A futuristic underwater city with glass domes", | |
| "A steampunk airship flying through clouds", | |
| "A magical forest with glowing plants and fairies", | |
| "A robot playing chess with an old man in a park", | |
| "A sunset over a desert with ancient ruins" | |
| ]; | |
| // Set active style button | |
| function setActiveStyle(style) { | |
| styleButtons.forEach(btn => { | |
| if (btn.dataset.style === style) { | |
| btn.classList.add('bg-opacity-30', 'border-opacity-50'); | |
| } else { | |
| btn.classList.remove('bg-opacity-30', 'border-opacity-50'); | |
| } | |
| }); | |
| currentStyle = style; | |
| } | |
| // Generate a random prompt | |
| function generateRandomPrompt() { | |
| const randomIndex = Math.floor(Math.random() * samplePrompts.length); | |
| promptInput.value = samplePrompts[randomIndex]; | |
| } | |
| // Generate image using DALL-E Mini API | |
| async function generateImage(prompt, style) { | |
| if (!prompt.trim()) { | |
| alert('Please enter a prompt'); | |
| return; | |
| } | |
| // Show loading indicator | |
| loadingIndicator.classList.remove('hidden'); | |
| try { | |
| // Call DALL-E Mini API | |
| const response = await fetch('https://bf.dallemini.ai/generate', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| prompt: `${prompt} in ${style} style`, | |
| // You can add more parameters here if needed | |
| }), | |
| }); | |
| if (!response.ok) { | |
| throw new Error('Failed to generate image'); | |
| } | |
| const data = await response.json(); | |
| // DALL-E Mini returns an array of images (base64 encoded) | |
| if (data.images && data.images.length > 0) { | |
| const imageUrl = `data:image/jpeg;base64,${data.images[0]}`; | |
| // Create image element | |
| const img = document.createElement('img'); | |
| img.src = imageUrl; | |
| img.alt = prompt; | |
| img.className = 'w-full h-full object-cover fade-in'; | |
| // Clear previous image | |
| imageContainer.innerHTML = ''; | |
| imageContainer.appendChild(img); | |
| // Add to gallery | |
| addToGallery(prompt, imageUrl, style); | |
| } else { | |
| throw new Error('No images returned'); | |
| } | |
| } catch (error) { | |
| console.error('Error generating image:', error); | |
| alert('Failed to generate image. Please try again later.'); | |
| } finally { | |
| // Hide loading indicator | |
| loadingIndicator.classList.add('hidden'); | |
| // Show download button | |
| downloadContainer.classList.remove('hidden'); | |
| } | |
| } | |
| // Add generated image to gallery | |
| function addToGallery(prompt, imageUrl, style) { | |
| const galleryItem = document.createElement('div'); | |
| galleryItem.className = 'relative group overflow-hidden rounded-lg aspect-square'; | |
| const img = document.createElement('img'); | |
| img.src = imageUrl; | |
| img.alt = prompt; | |
| img.className = 'w-full h-full object-cover'; | |
| const overlay = document.createElement('div'); | |
| overlay.className = 'absolute inset-0 bg-black bg-opacity-60 opacity-0 group-hover:opacity-100 transition-opacity p-3 flex flex-col justify-end'; | |
| const promptText = document.createElement('p'); | |
| promptText.className = 'text-sm truncate'; | |
| promptText.textContent = prompt; | |
| const styleText = document.createElement('p'); | |
| styleText.className = 'text-xs opacity-70 capitalize'; | |
| styleText.textContent = style; | |
| overlay.appendChild(promptText); | |
| overlay.appendChild(styleText); | |
| galleryItem.appendChild(img); | |
| galleryItem.appendChild(overlay); | |
| // Add click event to reuse the image | |
| galleryItem.addEventListener('click', () => { | |
| promptInput.value = prompt; | |
| setActiveStyle(style); | |
| // Create image element | |
| const img = document.createElement('img'); | |
| img.src = imageUrl; | |
| img.alt = prompt; | |
| img.className = 'w-full h-full object-cover fade-in'; | |
| // Clear previous image | |
| imageContainer.innerHTML = ''; | |
| imageContainer.appendChild(img); | |
| // Show download button | |
| downloadContainer.classList.remove('hidden'); | |
| }); | |
| gallery.prepend(galleryItem); | |
| generatedImages.unshift({prompt, imageUrl, style}); | |
| // Limit gallery to 8 items | |
| if (gallery.children.length > 8) { | |
| gallery.removeChild(gallery.lastChild); | |
| generatedImages.pop(); | |
| } | |
| } | |
| // Download image | |
| function downloadImage() { | |
| const img = imageContainer.querySelector('img'); | |
| if (!img) { | |
| alert('No image to download'); | |
| return; | |
| } | |
| const link = document.createElement('a'); | |
| link.href = img.src; | |
| link.download = `ai-image-${Date.now()}.jpg`; | |
| document.body.appendChild(link); | |
| link.click(); | |
| document.body.removeChild(link); | |
| } | |
| // Event listeners | |
| generateBtn.addEventListener('click', () => { | |
| generateImage(promptInput.value, currentStyle); | |
| }); | |
| randomBtn.addEventListener('click', () => { | |
| generateRandomPrompt(); | |
| }); | |
| clearBtn.addEventListener('click', () => { | |
| promptInput.value = ''; | |
| promptInput.focus(); | |
| }); | |
| downloadBtn.addEventListener('click', downloadImage); | |
| // Style buttons | |
| styleButtons.forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| setActiveStyle(btn.dataset.style); | |
| }); | |
| }); | |
| // Initialize with random prompt and realistic style | |
| generateRandomPrompt(); | |
| setActiveStyle('realistic'); | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=JulioHerculano/deepsite" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |