Team Ai
Apppublic

shailex/stable-diffusion-api

sourceHugging Faceupdated 2y agoView on Hugging Face
1likes
index.html340 linesDownload Raw Back to root
1<!DOCTYPE html>2<html lang="en">3 4<head>5    <meta charset="UTF-8">6    <meta name="viewport" content="width=device-width, initial-scale=1.0">7    <title>Stable Diffusion Image Generator</title>8    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">9    <style>10        body {11            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;12            background-color: #f8f9fa;13            padding-bottom: 40px;14        }15 16        .header {17            background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);18            color: white;19            padding: 2rem 0;20            margin-bottom: 2rem;21            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);22        }23 24        .form-container {25            background-color: white;26            border-radius: 10px;27            padding: 30px;28            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);29            margin-bottom: 2rem;30        }31 32        .image-gallery {33            display: grid;34            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));35            gap: 20px;36            margin-top: 30px;37        }38 39        .image-card {40            background-color: white;41            border-radius: 10px;42            overflow: hidden;43            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);44            transition: transform 0.3s ease;45        }46 47        .image-card:hover {48            transform: translateY(-5px);49        }50 51        .image-container {52            position: relative;53            padding-top: 100%;54            /* 1:1 Aspect Ratio */55            overflow: hidden;56        }57 58        .generated-image {59            position: absolute;60            top: 0;61            left: 0;62            width: 100%;63            height: 100%;64            object-fit: contain;65            background-color: #f8f9fa;66        }67 68        .image-actions {69            padding: 15px;70            display: flex;71            justify-content: space-between;72            align-items: center;73            background-color: #f8f9fa;74        }75 76        .loading-spinner {77            display: none;78            text-align: center;79            margin: 20px 0;80        }81 82        .slider-container {83            margin-bottom: 20px;84        }85 86        .slider-value {87            font-weight: bold;88            margin-left: 10px;89        }90 91        footer {92            margin-top: 3rem;93            padding: 20px 0;94            background-color: #f1f1f1;95            text-align: center;96        }97 98        #status {99            display: none;100            margin-top: 20px;101            padding: 10px;102            border-radius: 5px;103        }104 105        .status-success {106            background-color: #d4edda;107            color: #155724;108        }109 110        .status-error {111            background-color: #f8d7da;112            color: #721c24;113        }114        115        .api-url-container {116            margin-bottom: 20px;117            padding: 10px;118            background-color: #e9ecef;119            border-radius: 5px;120        }121    </style>122</head>123 124<body>125    <div class="header text-center">126        <div class="container">127            <h1>Stable Diffusion Image Generator</h1>128            <p class="lead">Create stunning AI-generated images from text descriptions</p>129        </div>130    </div>131 132    <div class="container">133        <div class="form-container">134            <!-- Added API URL configuration -->135            <div class="api-url-container">136                <div class="mb-3">137                    <label for="api-url" class="form-label">API URL:</label>138                    <div class="input-group">139                        <input type="text" class="form-control" id="api-url" value="http://localhost:7860/proxy-generate">140                        <button class="btn btn-outline-secondary" type="button" id="test-connection">Test Connection</button>141                    </div>142                    <div class="form-text">If running locally, use localhost. If using HuggingFace, use their API URL.</div>143                </div>144                <div id="connection-status"></div>145            </div>146 147            <form id="generation-form">148                <div class="mb-4">149                    <label for="prompt" class="form-label">Enter your prompt:</label>150                    <textarea class="form-control" id="prompt" rows="3"151                        placeholder="Describe the image you want to generate..." required></textarea>152                </div>153 154                <div class="row">155                    <div class="col-md-4 mb-3">156                        <label for="num-images" class="form-label">Number of Images:</label>157                        <div class="slider-container d-flex align-items-center">158                            <input type="range" class="form-range" min="1" max="4" step="1" value="2" id="num-images">159                            <span class="slider-value" id="num-images-value">2</span>160                        </div>161                    </div>162                    <div class="col-md-4 mb-3">163                        <label for="steps" class="form-label">Inference Steps:</label>164                        <div class="slider-container d-flex align-items-center">165                            <input type="range" class="form-range" min="20" max="100" step="10" value="50" id="steps">166                            <span class="slider-value" id="steps-value">50</span>167                        </div>168                    </div>169                    <div class="col-md-4 mb-3">170                        <label for="guidance" class="form-label">Guidance Scale:</label>171                        <div class="slider-container d-flex align-items-center">172                            <input type="range" class="form-range" min="1" max="20" step="0.5" value="7.5"173                                id="guidance">174                            <span class="slider-value" id="guidance-value">7.5</span>175                        </div>176                    </div>177                </div>178 179                <div class="d-grid">180                    <button type="submit" class="btn btn-primary btn-lg">Generate Images</button>181                </div>182            </form>183 184            <div id="status"></div>185 186            <div class="loading-spinner" id="loading">187                <div class="spinner-border text-primary" role="status">188                    <span class="visually-hidden">Loading...</span>189                </div>190                <p>Generating your images... This may take a minute.</p>191            </div>192        </div>193 194        <div class="image-gallery" id="image-gallery">195            <!-- Images will be displayed here -->196        </div>197    </div>198 199    <footer>200        <div class="container">201            <p>Powered by Stable Diffusion | Created by Shailesh Tagadghar</p>202        </div>203    </footer>204 205    <script>206        // Updated to use configurable API URL207        let API_URL = 'http://localhost:7860/proxy-generate';208        209        // Test connection button210        document.getElementById('test-connection').addEventListener('click', function() {211            const url = document.getElementById('api-url').value;212            const connectionStatus = document.getElementById('connection-status');213            214            connectionStatus.innerHTML = '<div class="alert alert-info">Testing connection...</div>';215            216            // Test the root endpoint of the API217            fetch(url.replace('/proxy-generate', '/'))218                .then(response => {219                    if (response.ok) {220                        return response.json();221                    } else {222                        throw new Error('Server returned an error');223                    }224                })225                .then(data => {226                    connectionStatus.innerHTML = `<div class="alert alert-success">Connection successful! Server running on ${data.device}</div>`;227                    API_URL = document.getElementById('api-url').value;228                })229                .catch(error => {230                    connectionStatus.innerHTML = '<div class="alert alert-danger">Connection failed. Please check the URL and make sure the server is running.</div>';231                    console.error('Connection error:', error);232                });233        });234 235        // Update slider values236        document.getElementById('num-images').addEventListener('input', function () {237            document.getElementById('num-images-value').textContent = this.value;238        });239 240        document.getElementById('steps').addEventListener('input', function () {241            document.getElementById('steps-value').textContent = this.value;242        });243 244        document.getElementById('guidance').addEventListener('input', function () {245            document.getElementById('guidance-value').textContent = this.value;246        });247 248        // Form submission249        document.getElementById('generation-form').addEventListener('submit', function (e) {250            e.preventDefault();251 252            // Get values253            const prompt = document.getElementById('prompt').value;254            const numImages = document.getElementById('num-images').value;255            const steps = document.getElementById('steps').value;256            const guidance = document.getElementById('guidance').value;257            258            // Use the current API URL259            API_URL = document.getElementById('api-url').value;260 261            // Show loading spinner262            document.getElementById('loading').style.display = 'block';263            document.getElementById('status').style.display = 'none';264 265            // Send request266            fetch(API_URL, {267                method: 'POST',268                headers: {269                    'Content-Type': 'application/json',270                },271                body: JSON.stringify({272                    prompt: prompt,273                    num_images: parseInt(numImages),274                    steps: parseInt(steps),275                    guidance: parseFloat(guidance)276                })277            })278            .then(response => {279                if (!response.ok) {280                    throw new Error('Server returned an error: ' + response.status);281                }282                return response.json();283            })284            .then(data => {285                // Hide loading spinner286                document.getElementById('loading').style.display = 'none';287 288                if (data.error) {289                    // Show error message290                    const statusEl = document.getElementById('status');291                    statusEl.className = 'status-error';292                    statusEl.textContent = data.error;293                    statusEl.style.display = 'block';294                } else {295                    // Display images296                    const gallery = document.getElementById('image-gallery');297                    gallery.innerHTML = '';298 299                    data.images.forEach((image, index) => {300                        const card = document.createElement('div');301                        card.className = 'image-card';302 303                        card.innerHTML = `304                            <div class="image-container">305                                <img src="data:image/png;base64,${image.data}" class="generated-image" alt="Generated image ${index + 1}">306                            </div>307                            <div class="image-actions">308                                <span>Image ${index + 1}</span>309                                <a href="data:image/png;base64,${image.data}" class="btn btn-sm btn-outline-primary" download="generated_image_${index + 1}.png">Download</a>310                            </div>311                        `;312 313                        gallery.appendChild(card);314                    });315 316                    // Show success message317                    const statusEl = document.getElementById('status');318                    statusEl.className = 'status-success';319                    statusEl.textContent = 'Images generated successfully!';320                    statusEl.style.display = 'block';321                }322            })323            .catch(error => {324                // Hide loading spinner325                document.getElementById('loading').style.display = 'none';326 327                // Show error message328                const statusEl = document.getElementById('status');329                statusEl.className = 'status-error';330                statusEl.textContent = 'An error occurred: ' + error.message;331                statusEl.style.display = 'block';332                console.error('Error:', error);333            });334        });335    </script>336 337    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>338</body>339 340</html>