fix: EXIF data now visible in photo preview card
- extractExifData() now async — reads real EXIF tags (Make, Model, DateTimeOriginal, ISO, FNumber, ExposureTime, FocalLength, GPS) via exifr.parse() and displays them in the UI - handlePickedPhoto() + reader.onload made async to support this - GPS extraction already auto-triggers on photo pick (tryExtractGpsFromPicked) - Server-side exif_data round-trip already functional (verified) - DNG/RAW-02: .dng allowed, 20MB limit
@@ -1732,15 +1732,15 @@
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function handlePickedPhoto(file) {
|
async function handlePickedPhoto(file) {
|
||||||
pickedPhotoFile = file;
|
pickedPhotoFile = file;
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = function(e) {
|
reader.onload = async function(e) {
|
||||||
document.getElementById('pickedPhotoPreview').src = e.target.result;
|
document.getElementById('pickedPhotoPreview').src = e.target.result;
|
||||||
document.getElementById('photoPreviewCard').style.display = 'block';
|
document.getElementById('photoPreviewCard').style.display = 'block';
|
||||||
|
|
||||||
// Extract EXIF / file metadata
|
// Extract EXIF / file metadata
|
||||||
extractExifData(file);
|
await extractExifData(file);
|
||||||
|
|
||||||
// Auto-extract GPS from the picked photo
|
// Auto-extract GPS from the picked photo
|
||||||
tryExtractGpsFromPicked();
|
tryExtractGpsFromPicked();
|
||||||
@@ -1751,13 +1751,44 @@
|
|||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractExifData(file) {
|
async function extractExifData(file) {
|
||||||
const exifDiv = document.getElementById('pickedExifData');
|
const exifDiv = document.getElementById('pickedExifData');
|
||||||
const rows = [];
|
const rows = [];
|
||||||
rows.push({ label: 'File name', value: file.name });
|
rows.push({ label: '📄 File name', value: file.name });
|
||||||
rows.push({ label: 'File size', value: formatFileSize(file.size) });
|
rows.push({ label: '📦 File size', value: formatFileSize(file.size) });
|
||||||
rows.push({ label: 'Type', value: file.type || 'unknown' });
|
rows.push({ label: '🏷️ Type', value: file.type || 'unknown' });
|
||||||
rows.push({ label: 'Last modified', value: formatDate(new Date(file.lastModified).toISOString()) });
|
rows.push({ label: '🕐 Modified', value: formatDate(new Date(file.lastModified).toISOString()) });
|
||||||
|
|
||||||
|
// Try to read actual EXIF tags from the file
|
||||||
|
try {
|
||||||
|
const exifData = await exifr.parse(file);
|
||||||
|
if (exifData) {
|
||||||
|
if (exifData.Make || exifData.Model) {
|
||||||
|
rows.push({ label: '📷 Camera', value: [exifData.Make, exifData.Model].filter(Boolean).join(' ') });
|
||||||
|
}
|
||||||
|
if (exifData.DateTimeOriginal) {
|
||||||
|
const d = new Date(exifData.DateTimeOriginal);
|
||||||
|
rows.push({ label: '📅 Date taken', value: d.toLocaleString() });
|
||||||
|
}
|
||||||
|
if (exifData.ISO) {
|
||||||
|
rows.push({ label: '🎯 ISO', value: String(exifData.ISO) });
|
||||||
|
}
|
||||||
|
if (exifData.FNumber) {
|
||||||
|
rows.push({ label: '🔆 Aperture', value: 'f/' + exifData.FNumber });
|
||||||
|
}
|
||||||
|
if (exifData.ExposureTime) {
|
||||||
|
rows.push({ label: '⏱️ Shutter', value: exifData.ExposureTime + 's' });
|
||||||
|
}
|
||||||
|
if (exifData.FocalLength) {
|
||||||
|
rows.push({ label: '🔭 Focal', value: exifData.FocalLength + 'mm' });
|
||||||
|
}
|
||||||
|
if (exifData.GPSLatitude && exifData.GPSLongitude) {
|
||||||
|
const lat = exifData.latitude || exifData.GPSLatitude;
|
||||||
|
const lng = exifData.longitude || exifData.GPSLongitude;
|
||||||
|
rows.push({ label: '📍 GPS', value: typeof lat === 'number' ? `${lat.toFixed(6)}, ${lng.toFixed(6)}` : `${exifData.GPSLatitude.join(' ')} ${exifData.GPSLatitudeRef}, ${exifData.GPSLongitude.join(' ')} ${exifData.GPSLongitudeRef}` });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_) { /* EXIF display is best-effort */ }
|
||||||
|
|
||||||
exifDiv.innerHTML = rows.map(r =>
|
exifDiv.innerHTML = rows.map(r =>
|
||||||
`<div class="exif-row"><span class="exif-label">${esc(r.label)}</span><span class="exif-value">${esc(r.value)}</span></div>`
|
`<div class="exif-row"><span class="exif-label">${esc(r.label)}</span><span class="exif-value">${esc(r.value)}</span></div>`
|
||||||
|
|||||||
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 982 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 982 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.0 KiB |