Optimize RAW inspection and add timings v0.8.1
This commit is contained in:
1 parent
4e3c442b26
commit
d17bc6a132
6 files changed
+200
-122
No files matched your search
+50
-4
@@ -378,7 +378,10 @@ async function readPhotoMetadata(photo, file) {
|
||||
try { message = (await response.json()).detail || message; } catch {}
|
||||
throw new Error(message);
|
||||
}
|
||||
const data = await response.json();
|
||||
applyMetadataResult(photo, await response.json());
|
||||
}
|
||||
|
||||
function applyMetadataResult(photo, data) {
|
||||
photo.metadataLoaded = true;
|
||||
photo.metadataPresent = Boolean(data.hasMetadata);
|
||||
photo.fileValues = data.hasMetadata ? data.values : null;
|
||||
@@ -391,6 +394,31 @@ async function readPhotoMetadata(photo, file) {
|
||||
}
|
||||
}
|
||||
|
||||
function base64PreviewUrl(base64, mediaType) {
|
||||
const binary = atob(base64);
|
||||
const bytes = new Uint8Array(binary.length);
|
||||
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
||||
return URL.createObjectURL(new Blob([bytes], { type: mediaType || 'image/jpeg' }));
|
||||
}
|
||||
|
||||
async function inspectServerPreviewPhoto(photo, file) {
|
||||
const payload = new FormData();
|
||||
payload.append('file', file, photo.name);
|
||||
const response = await fetch('/api/inspect', { method: 'POST', body: payload });
|
||||
if (!response.ok) {
|
||||
let message = `Photo inspection failed (${response.status}).`;
|
||||
try { message = (await response.json()).detail || message; } catch {}
|
||||
throw new Error(message);
|
||||
}
|
||||
const data = await response.json();
|
||||
const oldUrl = state.thumbUrls.get(photo.name);
|
||||
if (oldUrl) URL.revokeObjectURL(oldUrl);
|
||||
const previewUrl = base64PreviewUrl(data.previewBase64, data.previewMediaType);
|
||||
state.thumbUrls.set(photo.name, previewUrl);
|
||||
applyMetadataResult(photo, data);
|
||||
return previewUrl;
|
||||
}
|
||||
|
||||
async function selectPhoto(index, force = false) {
|
||||
if (index < 0 || index >= state.photos.length || (state.processing && !force)) return;
|
||||
captureCurrentValues();
|
||||
@@ -414,9 +442,17 @@ async function selectPhoto(index, force = false) {
|
||||
if (requiresServerPreview(photo)) {
|
||||
setSaveStatus('loading', `Rendering ${photo.format} preview…`, photo.name);
|
||||
}
|
||||
const previewUrl = await getPreviewUrl(photo, file);
|
||||
const serverInspectionNeeded = requiresServerPreview(photo)
|
||||
&& (!state.thumbUrls.has(photo.name) || !photo.metadataLoaded);
|
||||
const previewUrl = serverInspectionNeeded
|
||||
? await inspectServerPreviewPhoto(photo, file)
|
||||
: await getPreviewUrl(photo, file);
|
||||
if (selectionToken !== state.selectionToken || state.currentIndex !== index) return;
|
||||
elements.preview.src = previewUrl;
|
||||
if (serverInspectionNeeded) {
|
||||
if (!formHasUserInput() && photo.values) restoreValues(photo.values);
|
||||
updatePhotoStatus(photo);
|
||||
}
|
||||
renderFileList();
|
||||
} catch (error) {
|
||||
if (selectionToken === state.selectionToken && state.currentIndex === index) {
|
||||
@@ -574,6 +610,8 @@ async function savePhoto(moveNext) {
|
||||
payload.append('location_name', values.locationName);
|
||||
}
|
||||
|
||||
const saveStarted = performance.now();
|
||||
setSaveStatus('saving', 'Uploading and rewriting metadata…', `${photo.name} · large RAW files can take a while`);
|
||||
const response = await fetch('/api/process', { method: 'POST', body: payload });
|
||||
if (!response.ok) {
|
||||
let message = `Save failed (${response.status}).`;
|
||||
@@ -582,6 +620,9 @@ async function savePhoto(moveNext) {
|
||||
}
|
||||
|
||||
const updatedBlob = await response.blob();
|
||||
const serverAndTransferSeconds = (performance.now() - saveStarted) / 1000;
|
||||
setSaveStatus('saving', 'Writing updated file locally…', `${photo.name} · ${serverAndTransferSeconds.toFixed(1)}s processing and transfer`);
|
||||
const localWriteStarted = performance.now();
|
||||
const writable = await photo.handle.createWritable({ keepExistingData: false });
|
||||
try {
|
||||
await writable.write(updatedBlob);
|
||||
@@ -590,6 +631,7 @@ async function savePhoto(moveNext) {
|
||||
await writable.abort().catch(() => {});
|
||||
throw error;
|
||||
}
|
||||
const localWriteSeconds = (performance.now() - localWriteStarted) / 1000;
|
||||
|
||||
const updatedFile = await photo.handle.getFile();
|
||||
photo.size = updatedFile.size;
|
||||
@@ -602,8 +644,12 @@ async function savePhoto(moveNext) {
|
||||
photo.metadataLoaded = true;
|
||||
photo.metadataPresent = true;
|
||||
saveFolderState();
|
||||
setSaveStatus('saved', 'Saved in place', formatMetadataSummary(savedValues));
|
||||
showToast(`Saved ${photo.name}`);
|
||||
setSaveStatus(
|
||||
'saved',
|
||||
'Saved in place',
|
||||
`${formatMetadataSummary(savedValues)} · ${serverAndTransferSeconds.toFixed(1)}s server/transfer · ${localWriteSeconds.toFixed(1)}s local write`,
|
||||
);
|
||||
showToast(`Saved ${photo.name} in ${(serverAndTransferSeconds + localWriteSeconds).toFixed(1)}s`);
|
||||
updateProgress();
|
||||
|
||||
const oldThumb = state.thumbUrls.get(photo.name);
|
||||
|
||||
Reference in new issue
Block a user