|
|
class SketchConverter { |
|
|
constructor() { |
|
|
this.initializeElements(); |
|
|
this.attachEventListeners(); |
|
|
this.currentFile = null; |
|
|
this.currentSketchUrl = null; |
|
|
} |
|
|
|
|
|
initializeElements() { |
|
|
this.uploadArea = document.getElementById('upload-area'); |
|
|
this.processingArea = document.getElementById('processing-area'); |
|
|
this.resultArea = document.getElementById('result-area'); |
|
|
this.settingsArea = document.getElementById('settings-area'); |
|
|
this.fileInput = document.getElementById('file-input'); |
|
|
this.browseBtn = document.getElementById('browse-btn'); |
|
|
this.originalImage = document.getElementById('original-image'); |
|
|
this.sketchImage = document.getElementById('sketch-image'); |
|
|
this.downloadBtn = document.getElementById('download-btn'); |
|
|
this.newUploadBtn = document.getElementById('new-upload-btn'); |
|
|
this.blurSelect = document.getElementById('blur-select'); |
|
|
this.enhanceCheck = document.getElementById('enhance-check'); |
|
|
} |
|
|
|
|
|
attachEventListeners() { |
|
|
|
|
|
this.browseBtn.addEventListener('click', () => this.fileInput.click()); |
|
|
this.fileInput.addEventListener('change', (e) => this.handleFileSelect(e.target.files[0])); |
|
|
|
|
|
|
|
|
this.uploadArea.addEventListener('dragover', (e) => this.handleDragOver(e)); |
|
|
this.uploadArea.addEventListener('dragleave', (e) => this.handleDragLeave(e)); |
|
|
this.uploadArea.addEventListener('drop', (e) => this.handleDrop(e)); |
|
|
|
|
|
|
|
|
this.downloadBtn.addEventListener('click', () => this.downloadSketch()); |
|
|
this.newUploadBtn.addEventListener('click', () => this.resetInterface()); |
|
|
|
|
|
|
|
|
this.blurSelect.addEventListener('change', () => this.processCurrentFile()); |
|
|
this.enhanceCheck.addEventListener('change', () => this.processCurrentFile()); |
|
|
} |
|
|
|
|
|
handleDragOver(e) { |
|
|
e.preventDefault(); |
|
|
e.stopPropagation(); |
|
|
this.uploadArea.classList.add('border-primary'); |
|
|
} |
|
|
|
|
|
handleDragLeave(e) { |
|
|
e.preventDefault(); |
|
|
e.stopPropagation(); |
|
|
this.uploadArea.classList.remove('border-primary'); |
|
|
} |
|
|
|
|
|
handleDrop(e) { |
|
|
e.preventDefault(); |
|
|
e.stopPropagation(); |
|
|
this.uploadArea.classList.remove('border-primary'); |
|
|
|
|
|
const files = e.dataTransfer.files; |
|
|
if (files.length > 0) { |
|
|
this.handleFileSelect(files[0]); |
|
|
} |
|
|
} |
|
|
|
|
|
handleFileSelect(file) { |
|
|
if (!file) return; |
|
|
|
|
|
|
|
|
if (!file.type.startsWith('image/')) { |
|
|
this.showError('Please select a valid image file (JPG, PNG, etc.)'); |
|
|
return; |
|
|
} |
|
|
|
|
|
|
|
|
if (file.size > 10 * 1024 * 1024) { |
|
|
this.showError('File size must be less than 10MB'); |
|
|
return; |
|
|
} |
|
|
|
|
|
this.currentFile = file; |
|
|
this.showOriginalImage(file); |
|
|
this.processCurrentFile(); |
|
|
} |
|
|
|
|
|
showOriginalImage(file) { |
|
|
const reader = new FileReader(); |
|
|
reader.onload = (e) => { |
|
|
this.originalImage.src = e.target.result; |
|
|
}; |
|
|
reader.readAsDataURL(file); |
|
|
} |
|
|
|
|
|
async processCurrentFile() { |
|
|
if (!this.currentFile) return; |
|
|
|
|
|
this.showProcessing(); |
|
|
|
|
|
const formData = new FormData(); |
|
|
formData.append('image', this.currentFile); |
|
|
formData.append('blur', this.blurSelect.value); |
|
|
formData.append('enhance', this.enhanceCheck.checked); |
|
|
|
|
|
try { |
|
|
const response = await fetch('/convert', { |
|
|
method: 'POST', |
|
|
body: formData |
|
|
}); |
|
|
|
|
|
if (!response.ok) { |
|
|
const errorData = await response.json(); |
|
|
throw new Error(errorData.error || 'Failed to process image'); |
|
|
} |
|
|
|
|
|
const result = await response.json(); |
|
|
this.showResult(result.sketch_url); |
|
|
} catch (error) { |
|
|
console.error('Error processing image:', error); |
|
|
this.showError(error.message || 'Failed to process image. Please try again.'); |
|
|
} |
|
|
} |
|
|
|
|
|
showProcessing() { |
|
|
this.hideAllAreas(); |
|
|
this.processingArea.classList.remove('hidden'); |
|
|
this.settingsArea.classList.remove('hidden'); |
|
|
} |
|
|
|
|
|
showResult(sketchUrl) { |
|
|
this.currentSketchUrl = sketchUrl; |
|
|
this.sketchImage.src = sketchUrl; |
|
|
|
|
|
this.hideAllAreas(); |
|
|
this.resultArea.classList.remove('hidden'); |
|
|
this.settingsArea.classList.remove('hidden'); |
|
|
} |
|
|
|
|
|
hideAllAreas() { |
|
|
this.uploadArea.classList.add('hidden'); |
|
|
this.processingArea.classList.add('hidden'); |
|
|
this.resultArea.classList.add('hidden'); |
|
|
this.settingsArea.classList.add('hidden'); |
|
|
} |
|
|
|
|
|
resetInterface() { |
|
|
this.currentFile = null; |
|
|
this.currentSketchUrl = null; |
|
|
this.fileInput.value = ''; |
|
|
|
|
|
this.hideAllAreas(); |
|
|
this.uploadArea.classList.remove('hidden'); |
|
|
|
|
|
|
|
|
this.blurSelect.value = '21'; |
|
|
this.enhanceCheck.checked = false; |
|
|
} |
|
|
|
|
|
downloadSketch() { |
|
|
if (!this.currentSketchUrl) return; |
|
|
|
|
|
const link = document.createElement('a'); |
|
|
link.href = this.currentSketchUrl; |
|
|
link.download = 'sketch.jpg'; |
|
|
document.body.appendChild(link); |
|
|
link.click(); |
|
|
document.body.removeChild(link); |
|
|
} |
|
|
|
|
|
showError(message) { |
|
|
|
|
|
const toast = document.createElement('div'); |
|
|
toast.className = 'fixed top-4 right-4 bg-red-500 text-white px-6 py-3 rounded-lg z-50'; |
|
|
toast.textContent = message; |
|
|
|
|
|
document.body.appendChild(toast); |
|
|
|
|
|
setTimeout(() => { |
|
|
document.body.removeChild(toast); |
|
|
}, 5000); |
|
|
|
|
|
this.resetInterface(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
|
new SketchConverter(); |
|
|
}); |