Reorder metadata: scary stuff first, clean up formatting
Lead with GPS location (reverse geocoded), date, camera/device. Combine aperture/exposure/ISO/focal length into one "Settings" line with rounded values. Technical details (dimensions, ICC, EXIF/XMP data sizes) at the bottom. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
63
server.js
63
server.js
@@ -424,7 +424,7 @@ app.get("/", (_req, res) => {
|
||||
td1.textContent = k;
|
||||
const td2 = document.createElement("td");
|
||||
td2.textContent = meta[k];
|
||||
if (meta[k].includes("⚠")) td2.className = "warn";
|
||||
if (k === "GPS Location") td2.className = "warn";
|
||||
tr.appendChild(td1);
|
||||
tr.appendChild(td2);
|
||||
removedBody.appendChild(tr);
|
||||
@@ -471,32 +471,15 @@ app.get("/", (_req, res) => {
|
||||
});
|
||||
|
||||
async function extractMetadata(buf) {
|
||||
const removed = {};
|
||||
const items = [];
|
||||
try {
|
||||
const meta = await sharp(buf, { failOnError: false }).metadata();
|
||||
if (meta.width && meta.height) removed["Dimensions"] = `${meta.width} × ${meta.height}`;
|
||||
if (meta.format) removed["Format"] = meta.format.toUpperCase();
|
||||
if (meta.space) removed["Color Space"] = meta.space;
|
||||
if (meta.density) removed["DPI"] = String(meta.density);
|
||||
if (meta.hasProfile) removed["ICC Profile"] = meta.icc ? `${(meta.icc.length / 1024).toFixed(1)} KB` : "Yes";
|
||||
if (meta.orientation && meta.orientation !== 1) removed["Orientation"] = String(meta.orientation);
|
||||
|
||||
if (meta.exif) {
|
||||
removed["EXIF Data"] = `${(meta.exif.length / 1024).toFixed(1)} KB`;
|
||||
try {
|
||||
const exif = exifReader(meta.exif);
|
||||
if (exif.Image?.Make) removed["Camera Make"] = String(exif.Image.Make);
|
||||
if (exif.Image?.Model) removed["Camera Model"] = String(exif.Image.Model);
|
||||
if (exif.Image?.Software) removed["Software"] = String(exif.Image.Software);
|
||||
if (exif.Photo?.DateTimeOriginal) {
|
||||
const d = exif.Photo.DateTimeOriginal;
|
||||
removed["Date Taken"] = d instanceof Date ? d.toISOString().slice(0, 19).replace("T", " ") : String(d);
|
||||
}
|
||||
if (exif.Photo?.LensModel) removed["Lens"] = String(exif.Photo.LensModel);
|
||||
if (exif.Photo?.ExposureTime) removed["Exposure"] = `1/${Math.round(1 / exif.Photo.ExposureTime)}s`;
|
||||
if (exif.Photo?.FNumber) removed["Aperture"] = `f/${exif.Photo.FNumber}`;
|
||||
if (exif.Photo?.ISOSpeedRatings) removed["ISO"] = String(exif.Photo.ISOSpeedRatings);
|
||||
if (exif.Photo?.FocalLength) removed["Focal Length"] = `${exif.Photo.FocalLength}mm`;
|
||||
|
||||
// Scary / identifiable stuff first
|
||||
if (exif.GPSInfo?.GPSLatitude && exif.GPSInfo?.GPSLongitude) {
|
||||
const lat = exif.GPSInfo.GPSLatitude;
|
||||
const lng = exif.GPSInfo.GPSLongitude;
|
||||
@@ -517,16 +500,44 @@ async function extractMetadata(buf) {
|
||||
if (geo.display_name) loc = geo.display_name;
|
||||
}
|
||||
} catch {}
|
||||
removed["GPS Location"] = loc + " — Removed!";
|
||||
items.push(["GPS Location", loc]);
|
||||
}
|
||||
if (exif.Photo?.ImageUniqueID) removed["Unique ID"] = "Removed";
|
||||
if (exif.Image?.HostComputer) removed["Device"] = String(exif.Image.HostComputer);
|
||||
|
||||
if (exif.Photo?.DateTimeOriginal) {
|
||||
const d = exif.Photo.DateTimeOriginal;
|
||||
items.push(["Date Taken", d instanceof Date ? d.toISOString().slice(0, 19).replace("T", " ") : String(d)]);
|
||||
}
|
||||
|
||||
if (exif.Image?.Make && exif.Image?.Model) {
|
||||
items.push(["Camera", `${exif.Image.Make} ${exif.Image.Model}`]);
|
||||
} else if (exif.Image?.Model) {
|
||||
items.push(["Camera", String(exif.Image.Model)]);
|
||||
}
|
||||
if (exif.Image?.HostComputer) items.push(["Device", String(exif.Image.HostComputer)]);
|
||||
if (exif.Photo?.LensModel) items.push(["Lens", String(exif.Photo.LensModel)]);
|
||||
if (exif.Photo?.ImageUniqueID) items.push(["Unique ID", String(exif.Photo.ImageUniqueID)]);
|
||||
|
||||
// Camera settings
|
||||
const settings = [];
|
||||
if (exif.Photo?.FNumber) settings.push(`f/${Math.round(exif.Photo.FNumber * 100) / 100}`);
|
||||
if (exif.Photo?.ExposureTime) settings.push(`1/${Math.round(1 / exif.Photo.ExposureTime)}s`);
|
||||
if (exif.Photo?.ISOSpeedRatings) settings.push(`ISO ${exif.Photo.ISOSpeedRatings}`);
|
||||
if (exif.Photo?.FocalLength) settings.push(`${Math.round(exif.Photo.FocalLength * 100) / 100}mm`);
|
||||
if (settings.length) items.push(["Settings", settings.join(" ")]);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
if (meta.iptc) removed["IPTC Data"] = `${(meta.iptc.length / 1024).toFixed(1)} KB`;
|
||||
if (meta.xmp) removed["XMP Data"] = `${(meta.xmp.length / 1024).toFixed(1)} KB`;
|
||||
// Technical details at the bottom
|
||||
if (meta.width && meta.height) items.push(["Dimensions", `${meta.width} × ${meta.height}`]);
|
||||
if (meta.hasProfile && meta.icc) items.push(["ICC Profile", `${(meta.icc.length / 1024).toFixed(1)} KB`]);
|
||||
if (meta.exif) items.push(["EXIF Data", `${(meta.exif.length / 1024).toFixed(1)} KB`]);
|
||||
if (meta.xmp) items.push(["XMP Data", `${(meta.xmp.length / 1024).toFixed(1)} KB`]);
|
||||
if (meta.iptc) items.push(["IPTC Data", `${(meta.iptc.length / 1024).toFixed(1)} KB`]);
|
||||
} catch {}
|
||||
|
||||
// Convert to ordered object
|
||||
const removed = {};
|
||||
for (const [k, v] of items) removed[k] = v;
|
||||
return removed;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user