Download static/index.html from cloudapp/imagen: direct link, hf CLI and curl.
- Browser
- Download file 16.5 kB
-
https://huggingface.co/spaces/cloudapp/imagen/resolve/main/static/index.html
- Command line
-
hf download hf://spaces/cloudapp/imagen/static/index.html
-
curl -L -o index.html https://huggingface.co/spaces/cloudapp/imagen/resolve/main/static/index.html
16.5 kB
| <html lang="zh-CN"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Imagen Generator</title> | |
| <style> | |
| :root { | |
| --bg-color: #0b0f19; | |
| --card-color: #1a1f2e; | |
| --text-color: #e2e8f0; | |
| --accent-color: #3b82f6; | |
| --input-bg: #2d3748; | |
| --danger-color: #ef4444; | |
| --success-color: #10b981; | |
| } | |
| body { | |
| font-family: 'Segoe UI', system-ui, sans-serif; | |
| background-color: var(--bg-color); | |
| color: var(--text-color); | |
| margin: 0; | |
| padding: 20px; | |
| display: flex; | |
| justify-content: center; | |
| } | |
| .container { | |
| width: 100%; | |
| max-width: 1000px; | |
| display: grid; | |
| grid-template-columns: 350px 1fr; | |
| gap: 20px; | |
| } | |
| .card { | |
| background-color: var(--card-color); | |
| padding: 20px; | |
| border-radius: 12px; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.3); | |
| } | |
| h1 { margin-top: 0; font-size: 1.5rem; color: var(--accent-color); } | |
| .form-group { margin-bottom: 15px; } | |
| label { display: block; margin-bottom: 5px; font-size: 0.9rem; color: #a0aec0; } | |
| input, select, textarea { | |
| width: 100%; | |
| padding: 10px; | |
| background-color: var(--input-bg); | |
| border: 1px solid #4a5568; | |
| border-radius: 6px; | |
| color: white; | |
| box-sizing: border-box; | |
| font-size: 0.95rem; | |
| } | |
| input:focus, select:focus, textarea:focus { | |
| outline: none; | |
| border-color: var(--accent-color); | |
| } | |
| .file-upload-wrapper { | |
| position: relative; | |
| border: 2px dashed #4a5568; | |
| border-radius: 6px; | |
| padding: 20px; | |
| text-align: center; | |
| cursor: pointer; | |
| transition: border-color 0.3s; | |
| } | |
| .file-upload-wrapper:hover { | |
| border-color: var(--accent-color); | |
| } | |
| #init_image_input { | |
| position: absolute; | |
| top: 0; left: 0; width: 100%; height: 100%; | |
| opacity: 0; | |
| cursor: pointer; | |
| } | |
| .upload-placeholder { color: #a0aec0; pointer-events: none; } | |
| .preview-container { | |
| display: none; | |
| margin-top: 10px; | |
| position: relative; | |
| flex-wrap: wrap; | |
| gap: 12px; | |
| } | |
| /* 缩略图包裹层 */ | |
| .thumb-wrapper { | |
| position: relative; | |
| width: 80px; | |
| height: 80px; | |
| } | |
| .thumb-img { | |
| width: 100%; | |
| height: 100%; | |
| object-fit: cover; | |
| border-radius: 6px; | |
| border: 1px solid #4a5568; | |
| } | |
| /* 单独删除按钮样式 */ | |
| .single-remove-btn { | |
| position: absolute; | |
| top: -8px; | |
| right: -8px; | |
| background: var(--danger-color); | |
| color: white; | |
| border: none; | |
| border-radius: 50%; | |
| width: 20px; | |
| height: 20px; | |
| cursor: pointer; | |
| font-size: 14px; | |
| font-weight: bold; | |
| line-height: 20px; | |
| text-align: center; | |
| padding: 0; | |
| z-index: 11; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.3); | |
| } | |
| /* 顶部一键清除按钮(可选保留) */ | |
| .clear-preview-btn { | |
| background: #4a5568; | |
| color: white; | |
| border: none; | |
| border-radius: 4px; | |
| padding: 2px 8px; | |
| cursor: pointer; | |
| font-size: 0.75rem; | |
| margin-bottom: 8px; | |
| width: auto; | |
| } | |
| button { | |
| width: 100%; | |
| padding: 12px; | |
| background-color: var(--accent-color); | |
| color: white; | |
| border: none; | |
| border-radius: 6px; | |
| font-size: 1rem; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| font-weight: bold; | |
| opacity: 1; | |
| } | |
| button:hover:not(:disabled) { | |
| background-color: #2563eb; | |
| transform: translateY(-1px); | |
| } | |
| button:disabled { | |
| background-color: #4a5568; | |
| cursor: not-allowed; | |
| opacity: 0.6; | |
| } | |
| .result-area { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| min-height: 400px; | |
| border: 2px dashed #4a5568; | |
| border-radius: 12px; | |
| position: relative; | |
| margin-top: 20px; | |
| } | |
| #result-img { | |
| max-width: 100%; | |
| max-height: 600px; | |
| border-radius: 8px; | |
| display: none; | |
| box-shadow: 0 4px 15px rgba(0,0,0,0.5); | |
| } | |
| .loader { | |
| border: 4px solid #f3f3f3; | |
| border-top: 4px solid var(--accent-color); | |
| border-radius: 50%; | |
| width: 40px; | |
| height: 40px; | |
| animation: spin 1s linear infinite; | |
| display: none; | |
| } | |
| .download-btn { | |
| margin-top: 15px; | |
| background-color: var(--success-color); | |
| width: auto; | |
| padding: 8px 20px; | |
| display: none; | |
| text-decoration: none; | |
| color: white; | |
| border-radius: 6px; | |
| } | |
| @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } | |
| .disclaimer-box { | |
| margin-bottom: 15px; | |
| padding: 12px; | |
| background-color: rgba(239, 68, 68, 0.1); | |
| border: 1px solid rgba(239, 68, 68, 0.3); | |
| border-radius: 6px; | |
| font-size: 0.85rem; | |
| color: #cbd5e1; | |
| line-height: 1.5; | |
| } | |
| .disclaimer-box strong { color: var(--danger-color); display: block; margin-bottom: 5px; } | |
| .checkbox-wrapper { | |
| display: flex; | |
| align-items: center; | |
| margin-bottom: 15px; | |
| padding: 5px 0; | |
| cursor: pointer; | |
| } | |
| .checkbox-wrapper input[type="checkbox"] { | |
| width: 18px; | |
| height: 18px; | |
| margin-right: 10px; | |
| cursor: pointer; | |
| accent-color: var(--accent-color); | |
| } | |
| .checkbox-wrapper label { | |
| display: inline; | |
| margin: 0; | |
| font-size: 0.95rem; | |
| color: #e2e8f0; | |
| cursor: pointer; | |
| } | |
| @media (max-width: 768px) { | |
| .container { grid-template-columns: 1fr; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="card"> | |
| <h1>Imagen Generator</h1> | |
| <div class="form-group"> | |
| <label>API Key</label> | |
| <input type="password" id="api_key" placeholder="sk-..."> | |
| </div> | |
| <div class="form-group"> | |
| <label>模型名称</label> | |
| <select id="model"> | |
| <option value="gpt-image-2">gpt-image-2(0.08)</option> | |
| <option value="gemini-3-pro-image-preview">gemini-3-pro-image-preview(0.35)</option> | |
| <option value="gemini-3.1-flash-image-preview">gemini-3.1-flash-image-preview(0.2)</option> | |
| </select> | |
| </div> | |
| <div class="form-group"> | |
| <label>画面比例</label> | |
| <select id="ratio"> | |
| <option value="16:9 (1080p/4K)">16:9 (1080p/4K 宽屏)</option> | |
| <option value="1:1 (正方形)">1:1 (正方形)</option> | |
| <option value="9:16 (手机壁纸)">9:16 (手机壁纸)</option> | |
| <option value="4:3 (标准照片)">4:3 (标准照片)</option> | |
| <option value="3:4 (竖向照片)">3:4 (竖向照片)</option> | |
| <option value="21:9 (电影感)">21:9 (电影感)</option> | |
| <option value="2:3 (艺术照)">2:3 (艺术照)</option> | |
| </select> | |
| </div> | |
| <div class="form-group"> | |
| <label>清晰度等级</label> | |
| <select id="scale"> | |
| <option value="1k">1k (标准)</option> | |
| <option value="2k">2k (高清)</option> | |
| <option value="4k">4k (超清 Pro)</option> | |
| </select> | |
| </div> | |
| <div class="form-group"> | |
| <label>输出格式</label> | |
| <select id="format"> | |
| <option value="png">PNG</option> | |
| <option value="jpg">JPG</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="form-group"> | |
| <label>提示词 (Prompt)</label> | |
| <textarea id="prompt" rows="4" placeholder="描述你想要的画面..."></textarea> | |
| </div> | |
| <div class="form-group"> | |
| <label>参考图 (支持多选,Chat模型可理解多图)</label> | |
| <div class="file-upload-wrapper" id="upload-box"> | |
| <span class="upload-placeholder" id="upload-text">点击或拖拽上传图片 (支持多选)</span> | |
| <input type="file" id="init_image_input" accept="image/jpeg, image/png" multiple> | |
| </div> | |
| <div class="preview-container" id="preview-container"> | |
| <div style="width: 100%; display: flex; justify-content: space-between; align-items: center;"> | |
| <span style="font-size: 0.8rem; color: #a0aec0;">已选择的图片:</span> | |
| <button class="clear-preview-btn" onclick="clearImagePreview()">全部清空</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="disclaimer-box"> | |
| <strong>⚠️ 免责声明 (Disclaimer)</strong> | |
| 本工具仅供个人学习与技术研究使用。严禁生成色情、暴力、政治敏感等违法内容。用户生成的任何内容纯属个人行为,法律后果由用户自行承担。 | |
| </div> | |
| <div class="checkbox-wrapper"> | |
| <input type="checkbox" id="agree_chk" onchange="toggleSubmitButton()"> | |
| <label for="agree_chk">我已知晓并承诺合规使用</label> | |
| </div> | |
| <button onclick="generateImage()" id="gen-btn" disabled>🚫 请先勾选免责声明</button> | |
| <div class="result-area" id="result-area"> | |
| <div class="loader" id="loader"></div> | |
| <img id="result-img" alt="Generated Image" /> | |
| <a id="download-link" class="download-btn" href="#" download="image.png">下载图片</a> | |
| <p id="status-text" style="color: #a0aec0; margin-top: 10px;">等待生成...</p> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| let initImagesList = []; | |
| const fileInput = document.getElementById('init_image_input'); | |
| const previewContainer = document.getElementById('preview-container'); | |
| const uploadBox = document.getElementById('upload-box'); | |
| fileInput.addEventListener('change', async function(e) { | |
| const files = Array.from(e.target.files); | |
| if (!files.length) return; | |
| previewContainer.style.display = 'flex'; | |
| uploadBox.style.display = 'none'; | |
| for (const file of files) { | |
| if (file.size > 10 * 1024 * 1024) continue; | |
| const base64Data = await new Promise((resolve) => { | |
| const reader = new FileReader(); | |
| reader.onload = (ev) => resolve(ev.target.result); | |
| reader.readAsDataURL(file); | |
| }); | |
| if (base64Data) { | |
| initImagesList.push(base64Data); | |
| renderThumbnail(base64Data); | |
| } | |
| } | |
| e.target.value = ''; // 重置以允许重新选择同一张图 | |
| }); | |
| // 渲染单个缩略图及其删除按钮 | |
| function renderThumbnail(data) { | |
| const wrapper = document.createElement('div'); | |
| wrapper.className = 'thumb-wrapper'; | |
| const img = document.createElement('img'); | |
| img.className = 'thumb-img'; | |
| img.src = data; | |
| const removeBtn = document.createElement('button'); | |
| removeBtn.className = 'single-remove-btn'; | |
| removeBtn.innerHTML = '×'; | |
| removeBtn.onclick = function() { | |
| // 从数据列表中删除 | |
| const index = initImagesList.indexOf(data); | |
| if (index > -1) initImagesList.splice(index, 1); | |
| // 从界面删除 | |
| wrapper.remove(); | |
| // 如果删光了,恢复上传状态 | |
| if (initImagesList.length === 0) { | |
| clearImagePreview(); | |
| } | |
| }; | |
| wrapper.appendChild(img); | |
| wrapper.appendChild(removeBtn); | |
| previewContainer.appendChild(wrapper); | |
| } | |
| function clearImagePreview() { | |
| fileInput.value = ''; | |
| initImagesList = []; | |
| // 删除除了标题栏(第一个子节点)外的所有缩略图 | |
| const header = previewContainer.firstElementChild; | |
| previewContainer.innerHTML = ''; | |
| previewContainer.appendChild(header); | |
| previewContainer.style.display = 'none'; | |
| uploadBox.style.display = 'block'; | |
| } | |
| function toggleSubmitButton() { | |
| const checkbox = document.getElementById('agree_chk'); | |
| const btn = document.getElementById('gen-btn'); | |
| if (checkbox.checked) { | |
| btn.disabled = false; | |
| btn.innerText = "🚀 开始生成"; | |
| } else { | |
| btn.disabled = true; | |
| btn.innerText = "🚫 请先勾选免责声明"; | |
| } | |
| } | |
| async function generateImage() { | |
| const apiKey = document.getElementById('api_key').value; | |
| const prompt = document.getElementById('prompt').value; | |
| const checkbox = document.getElementById('agree_chk'); | |
| if (!checkbox.checked) { alert("请先勾选免责声明!"); return; } | |
| if (!apiKey) { alert("请输入 API Key"); return; } | |
| if (!prompt) { alert("请输入提示词"); return; } | |
| const btn = document.getElementById('gen-btn'); | |
| const loader = document.getElementById('loader'); | |
| const img = document.getElementById('result-img'); | |
| const downloadBtn = document.getElementById('download-link'); | |
| const statusText = document.getElementById('status-text'); | |
| btn.disabled = true; | |
| btn.innerText = "生成中..."; | |
| loader.style.display = 'block'; | |
| img.style.display = 'none'; | |
| downloadBtn.style.display = 'none'; | |
| statusText.innerText = "正在请求 API..."; | |
| const payload = { | |
| api_key: apiKey, | |
| model: document.getElementById('model').value, | |
| prompt: prompt, | |
| ratio: document.getElementById('ratio').value, | |
| scale: document.getElementById('scale').value, | |
| format: document.getElementById('format').value, | |
| init_images: initImagesList | |
| }; | |
| try { | |
| const response = await fetch('/api/generate', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(payload) | |
| }); | |
| const data = await response.json(); | |
| if (data.status === 'success') { | |
| img.src = `data:image/${payload.format === 'jpg' ? 'jpeg' : 'png'};base64,${data.image_base64}`; | |
| img.style.display = 'block'; | |
| downloadBtn.href = img.src; | |
| downloadBtn.download = `generated_image.${payload.format}`; | |
| downloadBtn.style.display = 'inline-block'; | |
| downloadBtn.innerText = "下载图片"; | |
| statusText.innerText = ""; | |
| } else { | |
| statusText.innerText = "生成失败: " + data.message; | |
| alert("错误: " + data.message); | |
| } | |
| } catch (error) { | |
| console.error(error); | |
| statusText.innerText = "网络请求失败"; | |
| } finally { | |
| if (document.getElementById('agree_chk').checked) { | |
| btn.disabled = false; | |
| btn.innerText = "🚀 开始生成"; | |
| } | |
| loader.style.display = 'none'; | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |