binaychandra's picture
try resolving path issues
1f21b17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Image SVD Processor</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 1000px;
margin: 0 auto;
padding: 15px;
background-color: #f5f5f5;
}
.container {
background-color: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1 {
text-align: center;
background-color: #3498db;
color: #fff;
padding: 20px;
margin: 0 0 20px 0;
border-radius: 8px;
}
.controls {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin: 10px 0;
padding: 10px;
background-color: #f8f9fa;
border-radius: 8px;
gap: 10px;
}
.image-selection {
display: flex;
gap: 8px;
flex-wrap: wrap;
align-items: center;
}
.predefined-images, .upload-section {
display: flex;
flex-direction: column;
gap: 5px;
}
.slider-container {
flex: 0 0 40%;
margin-left: auto;
text-align: right;
}
#r-value {
width: 80%;
}
.image-container {
display: flex;
justify-content: space-between;
margin-top: 15px;
flex-wrap: wrap;
gap: 15px;
}
.image-box {
flex: 1;
min-width: 250px;
text-align: center;
margin-bottom: 15px;
padding: 10px;
background: #fff;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
position: relative;
}
.image-box img {
max-width: 100%;
max-height: 300px;
border: 1px solid #ddd;
border-radius: 4px;
padding: 8px;
background: #fff;
}
.loading-overlay {
display: none;
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(255,255,255,0.8);
justify-content: center;
align-items: center;
}
.spinner {
width: 50px; height: 50px;
border: 5px solid #f3f3f3;
border-top: 5px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {transform: rotate(0deg);}
100% {transform: rotate(360deg);}
}
.info {
margin-top: 10px;
color: #666;
padding: 5px;
background: #f8f9fa;
border-radius: 4px;
}
input[type="file"] {
padding: 5px;
border: none;
background: transparent;
}
input[type="file"]::-webkit-file-upload-button {
background: #3498db;
color: white;
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[type="range"] {
height: 8px;
-webkit-appearance: none;
margin: 10px 0;
background: #ddd;
border-radius: 4px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 20px;
height: 20px;
background: #3498db;
border-radius: 50%;
cursor: pointer;
}
.storage-info {
font-size: 0.9em;
color: #666;
margin-top: 5px;
text-align: left;
padding: 8px;
background: #f8f9fa;
border-radius: 4px;
}
.storage-details {
display: flex;
flex-direction: column;
gap: 5px;
}
.storage-row {
display: flex;
justify-content: space-between;
}
.highlight {
color: #3498db;
font-weight: bold;
}
.or-divider {
display: flex;
align-items: center;
color: #666;
font-size: 0.9em;
padding: 5px;
}
</style>
</head>
<body>
<div class="container">
<h1>Image SVD Processor</h1>
<div class="controls">
<div class="image-selection">
<div class="predefined-images">
<label for="predefinedImage" style="margin-top: -5px;padding-bottom: 5px;">Select a predefined image:</label>
<select id="predefinedImage" style="height: 30px;">
<option value="">-- Select an image --</option>
{% for image in predefined_images %}
<option value="{{ image.path }}">{{ image.name }}</option>
{% endfor %}
</select>
</div>
<div class="or-divider">
<span>OR</span>
</div>
<div class="upload-section">
<label for="imageInput">Upload your own image:</label>
<input type="file" id="imageInput" accept="image/*">
</div>
</div>
<div class="slider-container" style="margin-top: 10px;">
<label for="r-value">R Value: <span id="r-value-display">5</span></label>
<input type="range" id="r-value" min="1" max="100" value="5">
</div>
</div>
<div class="image-container">
<div class="image-box">
<h3>Original Image</h3>
<img id="originalImage" src="" alt="Original image will appear here">
<div class="info" id="originalInfo"></div>
<div class="storage-info">
<div class="storage-details" id="originalStorage">
<div class="storage-row">
<span>Storage (bytes):</span>
<span class="highlight">-</span>
</div>
<div class="storage-row">
<span>Dimensions:</span>
<span>height × width × channels</span>
</div>
</div>
</div>
</div>
<div class="image-box">
<h3>Processed Image</h3>
<img id="processedImage" src="" alt="Processed image will appear here">
<div class="info" id="processedInfo"></div>
<div class="storage-info">
<div class="storage-details" id="processedStorage">
<div class="storage-row">
<span>Storage (bytes):</span>
<span class="highlight">-</span>
</div>
<div class="storage-row">
<span>SVD Components:</span>
<span>U×r + r + V×r</span>
</div>
<div class="storage-row">
<span>Compression Ratio:</span>
<span class="highlight">-</span>
</div>
</div>
</div>
<div class="loading-overlay" id="loading">
<div class="spinner"></div>
</div>
</div>
</div>
</div>
<script>
let originalImage = document.getElementById('originalImage');
let processedImage = document.getElementById('processedImage');
let rValue = document.getElementById('r-value');
let rValueDisplay = document.getElementById('r-value-display');
let loading = document.getElementById('loading');
let imageInput = document.getElementById('imageInput');
let predefinedSelect = document.getElementById('predefinedImage');
let maxR = 100;
let currentImage = null;
// Function to load first predefined image
function loadFirstPredefinedImage() {
if (predefinedSelect.options.length > 1) { // if we have any predefined images
predefinedSelect.selectedIndex = 1; // select first image (index 0 is the placeholder)
const selectedImageUrl = predefinedSelect.value;
if (selectedImageUrl) {
originalImage.src = selectedImageUrl;
processImageFromUrl(selectedImageUrl);
}
}
}
// Load first image when page loads
window.addEventListener('load', loadFirstPredefinedImage);
document.getElementById('predefinedImage').addEventListener('change', function(e) {
if (e.target.value) {
imageInput.value = '';
originalImage.src = e.target.value;
processImageFromUrl(e.target.value);
}
});
imageInput.addEventListener('change', function(e) {
if (e.target.files && e.target.files[0]) {
document.getElementById('predefinedImage').value = '';
let reader = new FileReader();
reader.onload = function(e) {
originalImage.src = e.target.result;
currentImage = imageInput.files[0];
processImage();
}
reader.readAsDataURL(e.target.files[0]);
}
});
async function processImageFromUrl(imageUrl) {
loading.style.display = 'flex';
const formData = new FormData();
formData.append('image_url', imageUrl);
formData.append('r_value', rValue.value);
try {
const response = await fetch('/process', {method: 'POST', body: formData});
// Check if response is ok (status 200-299)
if (!response.ok) {
const text = await response.text();
console.error('Server response error:', response.status, text);
throw new Error(`Server error: ${response.status}. Check console for details.`);
}
// Try parsing the response as JSON
let data;
try {
data = await response.json();
} catch (parseError) {
console.error('JSON parse error:', parseError);
const text = await response.text();
console.error('Raw response:', text);
throw new Error('Failed to parse server response as JSON');
}
// Check for error in JSON response
if (data.error) {
console.error('API error:', data.error);
if (data.traceback) console.error('Traceback:', data.traceback);
throw new Error(data.error);
}
// Process successful response
processedImage.src = 'data:image/png;base64,' + data.processed_image;
maxR = data.max_r;
rValue.max = maxR;
// Update storage information
document.getElementById('originalStorage').innerHTML = `
<div class="storage-row">
<span>Storage (bytes):</span>
<span class="highlight">${data.storage.original.toLocaleString()}</span>
</div>
<div class="storage-row">
<span>Dimensions:</span>
<span>${data.dimensions.join(' × ')}</span>
</div>`;
document.getElementById('processedStorage').innerHTML = `
<div class="storage-row">
<span>Storage (bytes):</span>
<span class="highlight">${data.storage.compressed.toLocaleString()}</span>
</div>
<div class="storage-row">
<span>SVD Components:</span>
<span>${data.dimensions[0]}×${rValue.value} + ${rValue.value} + ${data.dimensions[1]}×${rValue.value}</span>
</div>
<div class="storage-row">
<span>Compression Ratio:</span>
<span class="highlight">${data.storage.compression_ratio.toFixed(2)}:1</span>
</div>`;
document.getElementById('originalInfo').textContent =
`Dimensions: ${data.dimensions.join(' × ')}`;
document.getElementById('processedInfo').textContent =
`Using ${rValue.value} of ${maxR} singular values`;
} catch (error) {
console.error('Error details:', error);
alert('Error processing image: ' + error.message);
} finally {
loading.style.display = 'none';
}
}
rValue.addEventListener('input', function() {
rValueDisplay.textContent = this.value;
const predefinedImage = document.getElementById('predefinedImage');
if (predefinedImage.value) {
processImageFromUrl(predefinedImage.value);
} else if (currentImage) {
processImage();
}
});
async function processImage() {
if (!currentImage) {return;}
loading.style.display = 'flex';
const formData = new FormData();
formData.append('image', currentImage);
formData.append('r_value', rValue.value);
try {
const response = await fetch('/process', {method: 'POST', body: formData});
const data = await response.json();
if (data.error) {
alert('Error: ' + data.error);
return;
}
processedImage.src = 'data:image/png;base64,' + data.processed_image;
maxR = data.max_r;
rValue.max = maxR;
document.getElementById('originalStorage').innerHTML = `
<div class="storage-row">
<span>Storage (bytes):</span>
<span class="highlight">${data.storage.original.toLocaleString()}</span>
</div>
<div class="storage-row">
<span>Dimensions:</span>
<span>${data.dimensions.join(' × ')}</span>
</div>`;
document.getElementById('processedStorage').innerHTML = `
<div class="storage-row">
<span>Storage (bytes):</span>
<span class="highlight">${data.storage.compressed.toLocaleString()}</span>
</div>
<div class="storage-row">
<span>SVD Components:</span>
<span>${data.dimensions[0]}×${rValue.value} + ${rValue.value} + ${data.dimensions[1]}×${rValue.value}</span>
</div>
<div class="storage-row">
<span>Compression Ratio:</span>
<span class="highlight">${data.storage.compression_ratio.toFixed(2)}:1</span>
</div>`;
document.getElementById('originalInfo').textContent =
`Dimensions: ${data.dimensions.join(' × ')}`;
document.getElementById('processedInfo').textContent =
`Using ${rValue.value} of ${maxR} singular values`;
} catch (error) {
alert('Error processing image: ' + error.message);
} finally {
loading.style.display = 'none';
}
}
</script>
</body>
</html>