herbertrt's picture
Now it seems like the CR2 is opening but the image preview is broken.
68df552 verified
// Global state for the application
const appState = {
currentImage: null,
adjustments: {
exposure: 0,
contrast: 0,
highlights: 0,
shadows: 0,
temperature: 0,
tint: 0,
vibrance: 0,
saturation: 0,
sharpening: 25,
noiseReduction: 0
},
history: [],
historyIndex: -1
};
// Initialize the application
function init() {
// Set up event listeners for all sliders
document.querySelectorAll('input[type="range"]').forEach(slider => {
slider.addEventListener('input', function() {
const adjustmentName = this.previousElementSibling.textContent.trim().toLowerCase();
appState.adjustments[adjustmentName] = parseFloat(this.value);
applyAdjustments();
});
});
// Set up drag and drop for image upload
const imagePreview = document.getElementById('image-preview');
imagePreview.addEventListener('dragover', (e) => {
e.preventDefault();
imagePreview.classList.add('border-2', 'border-blue-500');
});
imagePreview.addEventListener('dragleave', () => {
imagePreview.classList.remove('border-2', 'border-blue-500');
});
imagePreview.addEventListener('drop', (e) => {
e.preventDefault();
imagePreview.classList.remove('border-2', 'border-blue-500');
const file = e.dataTransfer.files[0];
if (file && file.type.match('image.*')) {
loadImage(file);
}
});
// Click to upload
imagePreview.addEventListener('click', () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.onchange = (e) => {
const file = e.target.files[0];
if (file) loadImage(file);
};
input.click();
});
}
// Load image from file
function loadImage(file) {
// Check if it's a RAW file
const rawExtensions = [
'.cr2', '.nef', '.arw', '.dng', '.raf', '.rw2', '.cr3', '.orf', '.pef', '.srf', '.sr2',
'.3fr', '.ari', '.bay', '.cap', '.dcs', '.dcr', '.drf', '.eip', '.erf', '.fff', '.iiq',
'.k25', '.kdc', '.mdc', '.mef', '.mos', '.mrw', '.nrw', '.obm', '.ptx', '.pxn', '.r3d',
'.raw', '.rwl', '.rwz', '.srw', '.x3f'
];
const isRaw = rawExtensions.some(ext => file.name.toLowerCase().endsWith(ext));
if (isRaw) {
processRawImage(file);
} else {
// Regular image processing
const reader = new FileReader();
reader.onload = (e) => {
appState.currentImage = e.target.result;
document.getElementById('image-preview').src = appState.currentImage;
resetAdjustments();
};
reader.readAsDataURL(file);
}
}
// Process RAW image (simulated since browsers can't process RAW files directly)
function processRawImage(file) {
const loader = document.getElementById('raw-loader');
const progressBar = document.getElementById('raw-progress');
const imagePreview = document.getElementById('image-preview');
// Create a temporary image to show the file is being processed
const tempImg = new Image();
tempImg.src = 'data:image/svg+xml;base64,' + btoa(
`<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="800" viewBox="0 0 1200 800">
<rect width="100%" height="100%" fill="#374151"/>
<text x="50%" y="50%" fill="white" font-family="Arial" font-size="24" text-anchor="middle" dominant-baseline="middle">
Processing RAW File...
</text>
</svg>`
);
imagePreview.src = tempImg.src;
// Show loading UI
loader.classList.remove('hidden');
progressBar.style.width = '0%';
// Simulate RAW processing with progress
let progress = 0;
const interval = setInterval(() => {
progress += 5;
progressBar.style.width = `${progress}%`;
if (progress >= 100) {
clearInterval(interval);
// Create object URL for the RAW file (in reality, you'd process it properly)
const objectUrl = URL.createObjectURL(file);
// Create a canvas to render a preview since browsers can't display RAW files directly
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1200;
canvas.height = 800;
// Fill with a placeholder color (simulating RAW processing)
ctx.fillStyle = '#374151';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Add text indicating this is a RAW file
ctx.fillStyle = '#ffffff';
ctx.font = '24px Arial';
ctx.textAlign = 'center';
ctx.fillText('RAW File Processed', canvas.width/2, canvas.height/2 - 20);
ctx.font = '16px Arial';
ctx.fillText(file.name, canvas.width/2, canvas.height/2 + 20);
// Convert canvas to data URL and set as image source
const processedUrl = canvas.toDataURL('image/jpeg');
imagePreview.src = processedUrl;
appState.currentImage = processedUrl;
resetAdjustments();
// Hide loader
loader.classList.add('hidden');
}
}, 100);
// Fallback in case something goes wrong
setTimeout(() => {
if (!loader.classList.contains('hidden')) {
clearInterval(interval);
loader.classList.add('hidden');
alert('Unable to process RAW file. Please try a different file format.');
}
}, 5000);
}
// Reset all adjustments to default
function resetAdjustments() {
Object.keys(appState.adjustments).forEach(key => {
appState.adjustments[key] = key === 'sharpening' ? 25 : 0;
});
// Reset sliders
document.querySelectorAll('input[type="range"]').forEach(slider => {
const adjustmentName = slider.previousElementSibling.textContent.trim().toLowerCase();
slider.value = appState.adjustments[adjustmentName];
});
}
// Apply all adjustments to the image
function applyAdjustments() {
// In a real app, this would use WebGL or Canvas to apply the adjustments
// For this demo, we'll just update the image with CSS filters
const image = document.getElementById('image-preview');
const adj = appState.adjustments;
let filter = '';
filter += `brightness(${1 + adj.exposure * 0.2}) `;
filter += `contrast(${1 + adj.contrast * 0.01}) `;
filter += `saturate(${1 + adj.saturation * 0.01}) `;
// Temperature and tint would be more complex in a real app
// This is a simplified approximation
if (adj.temperature > 0) {
filter += `sepia(${adj.temperature * 0.3}%) `;
}
image.style.filter = filter.trim();
}
// Initialize the app when the DOM is loaded
document.addEventListener('DOMContentLoaded', init);