Spaces:
Paused
Paused
| <div class="ai-tool-container"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.13.11/katex.min.css"> | |
| <link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@100&display=swap" rel="stylesheet"> | |
| <div class="container"> | |
| <h3>Image to sketch</h3> | |
| <form id="remakeai-form"> | |
| <div class="form-group"> | |
| <label for="file" class="custom-file-upload"> | |
| <i class="fa fa-cloud-upload"></i> Upload Image | |
| </label> | |
| <input type="file" id="file" name="file" required> | |
| <span id="file-name"></span> | |
| </div> | |
| <button type="submit" class="btn-submit">Submit</button> | |
| </form> | |
| <div class="result"></div> | |
| <div class="progress-container"> | |
| <div class="progress-bar" id="progress-bar"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener("DOMContentLoaded", function() { | |
| const form = document.getElementById("remakeai-form"); | |
| const fileInput = document.getElementById('file'); | |
| const fileNameSpan = document.getElementById('file-name'); | |
| const progressBar = document.getElementById('progress-bar'); | |
| const progressContainer = document.querySelector('.progress-container'); | |
| const resultDiv = document.querySelector(".result"); | |
| let simulatedProgressInterval; | |
| let simulatedProgress = 0; | |
| fileInput.addEventListener('change', function() { | |
| fileNameSpan.textContent = this.files[0].name; | |
| }); | |
| form.addEventListener("submit", async function(event) { | |
| event.preventDefault(); | |
| const file = fileInput.files[0]; | |
| const compressedFile = await compressImage(file); | |
| const formData = new FormData(); | |
| formData.append('file', compressedFile, file.name); | |
| // Reset and show the progress bar | |
| progressBar.style.width = '0%'; | |
| progressContainer.style.display = 'block'; | |
| simulatedProgress = 0; | |
| // Clear previous result | |
| resultDiv.innerHTML = ''; | |
| const xhr = new XMLHttpRequest(); | |
| xhr.open("POST", "/upload/", true); | |
| xhr.responseType = 'json'; // Ensure the response is treated as JSON | |
| xhr.upload.onprogress = function(event) { | |
| if (event.lengthComputable) { | |
| const percentComplete = (event.loaded / event.total) * 100; | |
| updateProgressBar(percentComplete); | |
| } | |
| }; | |
| xhr.onloadstart = function() { | |
| // Start simulating progress during backend processing | |
| simulateBackendProcessingProgress(); | |
| }; | |
| xhr.onload = function() { | |
| clearInterval(simulatedProgressInterval); // Stop simulation | |
| if (xhr.status === 200) { | |
| const response = xhr.response; | |
| if (response.error) { | |
| resultDiv.innerHTML = `<p class="error-message">${response.error}</p>`; | |
| } else { | |
| const originalURL = URL.createObjectURL(file); | |
| const sketchImageBase64 = response.sketch_image_base64; | |
| resultDiv.innerHTML = ` | |
| <h2>Result</h2> | |
| <div class="result-images"> | |
| <img src="${originalURL}" alt="Original Image" class="result-image"> | |
| <span class="arrow">↓</span> | |
| <img src="${sketchImageBase64}" alt="Sketch Image" class="result-image"> | |
| </div> | |
| `; | |
| // Create and append the download button | |
| const downloadButton = document.createElement('a'); | |
| downloadButton.href = sketchImageBase64; | |
| downloadButton.download = 'result.jpg'; | |
| downloadButton.textContent = 'Download Result'; | |
| downloadButton.className = 'btn-download'; | |
| resultDiv.appendChild(downloadButton); | |
| updateProgressBar(100); | |
| } | |
| } else { | |
| resultDiv.innerHTML = `<p class="error-message">Error: ${xhr.statusText}</p>`; | |
| updateProgressBar(0); | |
| } | |
| setTimeout(() => { | |
| progressContainer.style.display = 'none'; | |
| }, 1000); | |
| }; | |
| xhr.onerror = function() { | |
| clearInterval(simulatedProgressInterval); // Stop simulation | |
| resultDiv.innerHTML = `<p class="error-message">Error: Network Error</p>`; | |
| updateProgressBar(0); | |
| setTimeout(() => { | |
| progressContainer.style.display = 'none'; | |
| }, 1000); | |
| }; | |
| xhr.send(formData); | |
| }); | |
| async function compressImage(file) { | |
| return new Promise((resolve, reject) => { | |
| const reader = new FileReader(); | |
| reader.onload = function(event) { | |
| const img = new Image(); | |
| img.src = event.target.result; | |
| img.onload = function() { | |
| const canvas = document.createElement('canvas'); | |
| const ctx = canvas.getContext('2d'); | |
| // Calculate the new dimensions to resize the image while maintaining aspect ratio | |
| const maxWidth = 1000; | |
| const maxHeight = 1000; | |
| let width = img.width; | |
| let height = img.height; | |
| if (width > height) { | |
| if (width > maxWidth) { | |
| height *= maxWidth / width; | |
| width = maxWidth; | |
| } | |
| } else { | |
| if (height > maxHeight) { | |
| width *= maxHeight / height; | |
| height = maxHeight; | |
| } | |
| } | |
| // Set the canvas dimensions | |
| canvas.width = width; | |
| canvas.height = height; | |
| // Draw the image on the canvas with the new dimensions | |
| ctx.drawImage(img, 0, 0, width, height); | |
| // Convert canvas content to a blob | |
| canvas.toBlob((blob) => { | |
| resolve(blob); | |
| }, 'image/jpeg', 0.7); // Adjust quality as needed (0.7 is 70% quality) | |
| } | |
| } | |
| // Read the file as data URL | |
| reader.readAsDataURL(file); | |
| }); | |
| } | |
| function updateProgressBar(percentComplete) { | |
| progressBar.style.width = percentComplete + '%'; | |
| updateProgressBarColor(percentComplete); | |
| } | |
| function updateProgressBarColor(percentComplete) { | |
| const startColor = "#ff0000"; // Red | |
| const endColor = "#0056b3"; // Blue | |
| const currentColor = interpolateColor(startColor, endColor, percentComplete / 100); | |
| progressBar.style.backgroundColor = currentColor; | |
| } | |
| function interpolateColor(color1, color2, factor) { | |
| const result = color1.slice(1).match(/.{2}/g).map((hex, i) => { | |
| return Math.round(parseInt(hex, 16) * (1 - factor) + parseInt(color2.slice(1).match(/.{2}/g)[i], 16) * factor); | |
| }); | |
| return `#${result.map(val => val.toString(16).padStart(2, '0')).join('')}`; | |
| } | |
| function simulateBackendProcessingProgress() { | |
| simulatedProgressInterval = setInterval(() => { | |
| simulatedProgress += 1; // Increment progress by 1% | |
| if (simulatedProgress < 90) { // Cap the simulated progress at 90% | |
| updateProgressBar(simulatedProgress); | |
| } else { | |
| clearInterval(simulatedProgressInterval); // Stop simulation at 90% | |
| } | |
| }, 200); // Update every 200ms | |
| } | |
| }); | |
| </script> | |
| <style> | |
| .ai-tool-container body{ | |
| font-family: 'Barlow Condensed', sans-serif; | |
| background: linear-gradient(135deg, #f5f7fa, #c3cfe2); | |
| margin: 0; | |
| padding: 0; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| height: 100vh; | |
| direction: ltr; | |
| } | |
| .ai-tool-container { | |
| background: #fff; | |
| border-radius: 10px; | |
| box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1); | |
| padding: 20px; | |
| max-width: 500px; | |
| width: 100%; | |
| text-align: center; | |
| direction: ltr; | |
| } | |
| .ai-tool-container h3 { | |
| font-size: 24px; | |
| margin-bottom: 20px; | |
| color: #333; | |
| } | |
| .ai-tool-container .form-group { | |
| margin-bottom: 15px; | |
| text-align: left; | |
| } | |
| .ai-tool-container | |
| input[type="file"] { | |
| display: none; | |
| } | |
| .ai-tool-container .custom-file-upload { | |
| display: inline-block; | |
| padding: 10px 20px; | |
| cursor: pointer; | |
| background-color: #007bff; | |
| color: #fff; | |
| border-radius: 5px; | |
| transition: background 0.3s; | |
| } | |
| .ai-tool-container .custom-file-upload:hover { | |
| background-color: #0056b3; | |
| } | |
| .ai-tool-container #file-name { | |
| display: block; | |
| margin-top: 10px; | |
| font-size: 14px; | |
| color: #555; | |
| } | |
| .ai-tool-container .radio-group { | |
| display: flex; | |
| justify-content: space-around; | |
| align-items: center; | |
| } | |
| .ai-tool-container .btn-submit { | |
| background: #007bff; | |
| color: #fff; | |
| padding: 10px 20px; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| transition: background 0.3s; | |
| } | |
| .ai-tool-container .btn-submit:hover { | |
| background: #0056b3; | |
| } | |
| .ai-tool-container .result { | |
| margin-top: 20px; | |
| } | |
| .ai-tool-container .result h2 { | |
| font-size: 20px; | |
| color: #333; | |
| } | |
| .ai-tool-container .result-image { | |
| max-width: 100%; | |
| border-radius: 10px; | |
| box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1); | |
| transition: transform 0.3s; | |
| } | |
| .ai-tool-container .result-image:hover { | |
| transform: scale(1.05); | |
| } | |
| .ai-tool-container .error-message { | |
| color: red; | |
| font-size: 16px; | |
| } | |
| .ai-tool-container .progress-container { | |
| width: 100%; | |
| background-color: #f3f3f3; | |
| border-radius: 5px; | |
| overflow: hidden; | |
| margin-top: 20px; | |
| display: none; | |
| } | |
| .ai-tool-container .progress-bar { | |
| height: 10px; | |
| width: 0%; | |
| transition: width 0.4s ease, background-color 0.4s ease; | |
| } | |
| .ai-tool-container .result-images { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .ai-tool-container .result-images { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .ai-tool-container .result-image { | |
| max-width: 100%; | |
| max-height: 300px; | |
| border-radius: 10px; | |
| box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1); | |
| transition: transform 0.3s; | |
| margin: 10px 0; | |
| } | |
| .ai-tool-container .result-image:hover { | |
| transform: scale(1.05); | |
| } | |
| .ai-tool-container .arrow { | |
| font-size: 24px; | |
| color: #333; | |
| margin: 10px 0; | |
| } | |
| .ai-tool-container .btn-download { | |
| display: inline-block; | |
| margin-top: 20px; | |
| padding: 10px 20px; | |
| background-color: #708090; | |
| color: #fff; | |
| border-radius: 5px; | |
| text-decoration: none; | |
| transition: background 0.3s; | |
| } | |
| .ai-tool-container .btn-download:hover { | |
| background-color: #218838; | |
| } | |
| </style> | |
| </div> | |