Download index.html from Mahmoudmody777/Flux1.1Pro-Fast-BFL-API-Control-Interface: direct link, hf CLI and curl.
- Browser
- Download file 17.8 kB
-
https://huggingface.co/spaces/Mahmoudmody777/Flux1.1Pro-Fast-BFL-API-Control-Interface/resolve/main/index.html
- Command line
-
hf download hf://spaces/Mahmoudmody777/Flux1.1Pro-Fast-BFL-API-Control-Interface/index.html
-
curl -L -o index.html https://huggingface.co/spaces/Mahmoudmody777/Flux1.1Pro-Fast-BFL-API-Control-Interface/resolve/main/index.html
17.8 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Image Generator bfl api by mahmoudshokri</title> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| margin: 0; | |
| padding: 0; | |
| background-color: #f9f9f9; | |
| display: flex; | |
| flex-direction: column; | |
| height: 100vh; | |
| overflow: hidden; | |
| } | |
| .header { | |
| background-color: #007bff; | |
| color: white; | |
| padding: 15px; | |
| text-align: center; | |
| font-size: 24px; | |
| position: sticky; | |
| top: 0; | |
| z-index: 2; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .header img { | |
| max-height: 50px; | |
| margin-right: 10px; | |
| cursor: pointer; | |
| } | |
| .header img:hover + .tooltip { | |
| display: block; | |
| } | |
| .tooltip { | |
| display: none; | |
| position: absolute; | |
| color: white; | |
| background-color: rgba(0, 0, 0, 0.7); | |
| padding: 5px; | |
| border-radius: 5px; | |
| font-size: 14px; | |
| margin-left: -30px; | |
| margin-top: -30px; | |
| } | |
| .container { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| flex: 1; | |
| overflow-y: auto; | |
| } | |
| .api-info { | |
| margin: 19px; | |
| text-align: center; | |
| font-size: 16px; | |
| color: #333; | |
| } | |
| .api-info a { | |
| color: #007bff; | |
| text-decoration: none; | |
| } | |
| .api-info a:hover { | |
| text-decoration: underline; | |
| } | |
| .controls { | |
| width: 80%; | |
| margin: 20px auto; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: stretch; | |
| } | |
| .controls label { | |
| margin-bottom: 5px; | |
| font-size: 14px; | |
| color: #333; | |
| } | |
| .controls input[type="password"], | |
| .controls input[type="text"], | |
| .controls textarea { | |
| width: 100%; | |
| padding: 10px; | |
| margin-bottom: 10px; | |
| border: 1px solid #ccc; | |
| border-radius: 5px; | |
| font-size: 14px; | |
| box-sizing: border-box; | |
| transition: border-color 0.3s; | |
| } | |
| .controls input[type="password"]:focus, | |
| .controls input[type="text"]:focus, | |
| .controls textarea:focus { | |
| border-color: #007bff; | |
| } | |
| .controls button { | |
| padding: 10px; | |
| background-color: #007bff; | |
| color: white; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| font-size: 16px; | |
| transition: background-color 0.3s; | |
| } | |
| .controls button:hover { | |
| background-color: #0056b3; | |
| } | |
| .sliders { | |
| display: flex; | |
| flex-direction: column; | |
| margin: 10px 0; | |
| } | |
| .slider-container { | |
| display: flex; | |
| align-items: center; | |
| margin-bottom: 15px; | |
| flex-wrap: nowrap; | |
| } | |
| .slider-container label { | |
| margin-right: 10px; | |
| font-size: 14px; | |
| color: #333; | |
| width: 100px; | |
| } | |
| .slider-value { | |
| width: 40px; /* تصغير عرض خانة القياس */ | |
| text-align: center; | |
| font-size: 14px; | |
| margin-left: 10px; | |
| } | |
| .output { | |
| width: 80%; | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); | |
| gap: 20px; | |
| margin: 20px auto; | |
| } | |
| .output img { | |
| width: 100%; | |
| height: auto; | |
| border-radius: 10px; | |
| cursor: pointer; | |
| max-height: 620px; | |
| object-fit: contain; | |
| transition: transform 0.3s; | |
| } | |
| .output img:hover { | |
| transform: scale(1.05); | |
| } | |
| .image-container { | |
| position: relative; | |
| } | |
| .delete-button, .download-button { | |
| position: absolute; | |
| top: 10px; | |
| background-color: red; | |
| color: white; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| padding: 5px 10px; | |
| } | |
| .delete-button { | |
| left: 25px; /* وضع زر الحذف على اليسار */ | |
| background: border-box; | |
| width: 55px; | |
| } | |
| .download-button { | |
| left: 75px; /* وضع زر التحميل على اليمين */ | |
| width: 52px; | |
| background: border-box; | |
| } | |
| .image-container:hover .delete-button, | |
| .image-container:hover .download-button { | |
| display: block; | |
| } | |
| #status { | |
| text-align: center; | |
| color: #333; | |
| margin-top: 10px; | |
| font-size: 14px; | |
| } | |
| .modal { | |
| display: none; | |
| position: fixed; | |
| z-index: 1000; | |
| left: 0; | |
| top: 0; | |
| width: 100%; | |
| height: 100%; | |
| overflow: auto; | |
| background-color: rgba(0, 0, 0, 0.8); | |
| justify-content: center; | |
| align-items: center; | |
| padding: 20px; | |
| } | |
| .modal-content { | |
| background-color: white; | |
| padding: 50px; | |
| border-radius: 10px; | |
| max-width: 800px; | |
| width: 100%; | |
| display: flex; | |
| flex-direction: row; | |
| align-items: center; | |
| } | |
| .modal img { | |
| max-width: 50%; | |
| height: auto; | |
| border-radius: 10px; | |
| margin-right: 20px; | |
| object-fit: contain; | |
| } | |
| .prompt-info { | |
| margin-top: 0px; | |
| font-size: 14px; | |
| max-width: 300px; | |
| } | |
| .copy-prompt { | |
| background-color: #007bff; | |
| color: white; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| padding: 5px 10px; | |
| margin-top: 10px; | |
| } | |
| .copy-prompt:hover { | |
| background-color: #0056b3; | |
| } | |
| @media (max-width: 600px) { | |
| .slider-container label { | |
| width: auto; | |
| } | |
| .slider-container { | |
| flex-direction: column; | |
| align-items: stretch; | |
| } | |
| .slider-value { | |
| margin-left: 0; | |
| margin-top: 5px; | |
| } | |
| .modal img { | |
| max-width: 100%; | |
| } | |
| } | |
| input[type="range"] { | |
| width: 100%; /* تكبير شريط التمرير */ | |
| } | |
| .toggle-button { | |
| background-color: #007bff; | |
| color: white; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| padding: 5px 10px; | |
| margin-left: 10px; | |
| font-size: 14px; | |
| } | |
| .toggle-button:hover { | |
| background-color: #0056b3; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="header"> | |
| <img src="palestine.png" alt="Logo" id="logo"> | |
| <span class="tooltip">Free Palestine</span> | |
| Pray for Palestine | |
| </div> | |
| <div class="api-info"> | |
| <p>Get the API key and 50 free credits to generate images and purchase from here<a href="https://api.bfl.ml/auth/login#" target="_blank">BFL API Portal</a>.</p> | |
| </div> | |
| <div class="container"> | |
| <div class="controls"> | |
| <label for="api-key">API Key:</label> | |
| <div style="display: flex; align-items: center;"> | |
| <input type="password" id="api-key" placeholder="Enter your API Key"> | |
| <button class="toggle-button" id="toggle-api-key">Show</button> | |
| </div> | |
| <label for="prompt">Image Description:</label> | |
| <textarea id="prompt" placeholder="Describe the image you want to generate" rows="4"></textarea> | |
| <div class="sliders"> | |
| <div class="slider-container"> | |
| <label for="width">Width:</label> | |
| <input type="range" id="width" min="512" max="1440" step="64" value="1024"> | |
| <input class="slider-value" type="text" id="width-value" value="1024" readonly> | |
| </div> | |
| <div class="slider-container"> | |
| <label for="height">Height:</label> | |
| <input type="range" id="height" min="512" max="1440" step="64" value="768"> | |
| <input class="slider-value" type="text" id="height-value" value="768" readonly> | |
| </div> | |
| <div class="slider-container"> | |
| <label for="steps">Steps:</label> | |
| <input type="range" id="steps" min="1" max="100" step="1" value="8"> | |
| <input class="slider-value" type="text" id="steps-value" value="8" readonly> | |
| </div> | |
| </div> | |
| <button id="generate-btn">Generate Image</button> | |
| <p id="status"></p> | |
| </div> | |
| <div class="output" id="output-container"></div> | |
| </div> | |
| <div class="modal" id="modal"> | |
| <div class="modal-content"> | |
| <img id="modal-image" alt="Enlarged Image"> | |
| <div> | |
| <div class="prompt-info" id="prompt-info"></div> | |
| <div class="settings-info" id="settings-info"></div> | |
| <button id="copy-prompt" class="copy-prompt">Copy Prompt</button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| const generateBtn = document.getElementById('generate-btn'); | |
| const promptInput = document.getElementById('prompt'); | |
| const apiKeyInput = document.getElementById('api-key'); | |
| const widthSlider = document.getElementById('width'); | |
| const heightSlider = document.getElementById('height'); | |
| const stepsSlider = document.getElementById('steps'); | |
| const widthValue = document.getElementById('width-value'); | |
| const heightValue = document.getElementById('height-value'); | |
| const stepsValue = document.getElementById('steps-value'); | |
| const statusElement = document.getElementById('status'); | |
| const outputContainer = document.getElementById('output-container'); | |
| const modal = document.getElementById('modal'); | |
| const modalImage = document.getElementById('modal-image'); | |
| const promptInfo = document.getElementById('prompt-info'); | |
| const settingsInfo = document.getElementById('settings-info'); | |
| const copyPromptBtn = document.getElementById('copy-prompt'); | |
| const toggleApiKeyBtn = document.getElementById('toggle-api-key'); | |
| let isApiKeyVisible = false; | |
| window.onload = () => { | |
| const savedPrompt = localStorage.getItem('lastPrompt'); | |
| const savedApiKey = localStorage.getItem('apiKey'); | |
| if (savedPrompt) { | |
| promptInput.value = savedPrompt; | |
| } | |
| if (savedApiKey) { | |
| apiKeyInput.value = savedApiKey; | |
| } | |
| loadImagesFromStorage(); | |
| }; | |
| function loadImagesFromStorage() { | |
| const savedImages = JSON.parse(localStorage.getItem('images')) || []; | |
| savedImages.forEach(imgObj => addImageToOutput(imgObj.url, imgObj.prompt, imgObj.width, imgObj.height, imgObj.steps)); | |
| } | |
| widthSlider.addEventListener('input', () => { | |
| widthValue.value = widthSlider.value; | |
| localStorage.setItem('lastWidth', widthSlider.value); | |
| }); | |
| heightSlider.addEventListener('input', () => { | |
| heightValue.value = heightSlider.value; | |
| localStorage.setItem('lastHeight', heightSlider.value); | |
| }); | |
| stepsSlider.addEventListener('input', () => { | |
| stepsValue.value = stepsSlider.value; | |
| localStorage.setItem('lastSteps', stepsSlider.value); | |
| }); | |
| generateBtn.addEventListener('click', async () => { | |
| const prompt = promptInput.value; | |
| const apiKey = apiKeyInput.value; | |
| const width = widthSlider.value; | |
| const height = heightSlider.value; | |
| const steps = stepsSlider.value; | |
| if (!prompt || !apiKey) { | |
| alert('Please enter both a prompt and API key!'); | |
| return; | |
| } | |
| localStorage.setItem('lastPrompt', prompt); | |
| localStorage.setItem('apiKey', apiKey); | |
| statusElement.textContent = 'Generating image...'; | |
| try { | |
| const requestId = await sendImageGenerationRequest(prompt, width, height, steps, apiKey); | |
| const imageUrl = await pollResult(requestId, apiKey); | |
| addImageToOutput(imageUrl, prompt, width, height, steps); | |
| statusElement.textContent = 'Image generated successfully!'; | |
| } catch (error) { | |
| statusElement.textContent = `Error: ${error.message}`; | |
| } | |
| }); | |
| toggleApiKeyBtn.addEventListener('click', () => { | |
| isApiKeyVisible = !isApiKeyVisible; | |
| apiKeyInput.type = isApiKeyVisible ? 'text' : 'password'; | |
| toggleApiKeyBtn.textContent = isApiKeyVisible ? 'Hide' : 'Show'; | |
| }); | |
| function addImageToOutput(imageUrl, prompt, width, height, steps) { | |
| const container = document.createElement('div'); | |
| container.className = 'image-container'; | |
| const img = document.createElement('img'); | |
| img.src = imageUrl; | |
| img.alt = "Generated Image"; | |
| img.onclick = () => openModal(imageUrl, prompt, width, height, steps); | |
| // زر الحذف مع أيقونة | |
| const deleteButton = document.createElement('button'); | |
| deleteButton.className = 'delete-button'; | |
| const deleteIcon = document.createElement('img'); | |
| deleteIcon.src = 'delete.png'; // استبدل بالمسار الصحيح للأيقونة | |
| deleteButton.appendChild(deleteIcon); | |
| deleteButton.onclick = (e) => { | |
| e.stopPropagation(); | |
| container.remove(); | |
| removeImageFromStorage(imageUrl); | |
| }; | |
| // زر التحميل مع أيقونة | |
| const downloadButton = document.createElement('button'); | |
| downloadButton.className = 'download-button'; | |
| const downloadIcon = document.createElement('img'); | |
| downloadIcon.src = 'download.png'; // استبدل بالمسار الصحيح للأيقونة | |
| downloadButton.appendChild(downloadIcon); | |
| downloadButton.onclick = (e) => { | |
| e.stopPropagation(); | |
| downloadImage(imageUrl); | |
| }; | |
| container.appendChild(img); | |
| container.appendChild(deleteButton); | |
| container.appendChild(downloadButton); | |
| outputContainer.prepend(container); | |
| let savedImages = JSON.parse(localStorage.getItem('images')) || []; | |
| if (!savedImages.some(imgObj => imgObj.url === imageUrl)) { | |
| savedImages.push({ url: imageUrl, prompt: prompt, width: width, height: height, steps: steps }); | |
| localStorage.setItem('images', JSON.stringify(savedImages)); | |
| } | |
| } | |
| function removeImageFromStorage(imageUrl) { | |
| let savedImages = JSON.parse(localStorage.getItem('images')) || []; | |
| savedImages = savedImages.filter(imgObj => imgObj.url !== imageUrl); | |
| localStorage.setItem('images', JSON.stringify(savedImages)); | |
| } | |
| function openModal(imageUrl, prompt, width, height, steps) { | |
| modal.style.display = 'flex'; | |
| modalImage.src = imageUrl; | |
| promptInfo.innerText = `Prompt: ${prompt}`; | |
| settingsInfo.innerText = `Width: ${width}, Height: ${height}, Steps: ${steps}`; | |
| } | |
| function downloadImage(imageUrl) { | |
| const a = document.createElement('a'); | |
| a.href = imageUrl; | |
| a.download = 'generated-image.png'; // Specify the default filename | |
| document.body.appendChild(a); | |
| a.click(); | |
| document.body.removeChild(a); | |
| } | |
| copyPromptBtn.onclick = () => { | |
| const promptText = promptInfo.innerText.replace('Prompt: ', ''); | |
| navigator.clipboard.writeText(promptText); | |
| }; | |
| modal.onclick = (event) => { | |
| if (event.target === modal) { | |
| modal.style.display = 'none'; | |
| } | |
| }; | |
| async function sendImageGenerationRequest(prompt, width, height, steps, apiKey) { | |
| const response = await fetch('https://api.bfl.ml/v1/image', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'x-key': apiKey, | |
| }, | |
| body: JSON.stringify({ | |
| prompt: prompt, | |
| width: parseInt(width), | |
| height: parseInt(height), | |
| steps: parseInt(steps), | |
| }), | |
| }); | |
| const data = await response.json(); | |
| return data.id; | |
| } | |
| async function pollResult(requestId, apiKey) { | |
| while (true) { | |
| const result = await getResult(requestId, apiKey); | |
| const status = result.status; | |
| if (status === 'Ready') { | |
| return result.result.sample; | |
| } else if (['Error', 'Content Moderated', 'Request Moderated', 'Task not found'].includes(status)) { | |
| throw new Error(`Image generation failed. Status: ${status}`); | |
| } | |
| await new Promise(resolve => setTimeout(resolve, 1000)); | |
| } | |
| } | |
| async function getResult(requestId, apiKey) { | |
| const response = await fetch(`https://api.bfl.ml/v1/get_result?id=${requestId}`, { | |
| method: 'GET', | |
| headers: { | |
| 'x-key': apiKey, | |
| }, | |
| }); | |
| const data = await response.json(); | |
| return data; | |
| } | |
| </script> | |
| </body> | |
| </html> |