library: open a phone's HEIC, and lock the shelves to accounts
A HEIC is the one camera file no engine on this platform will paint: Chromium answers createImageBitmap with InvalidStateError and its WebCodecs take no hvc1 still, and unlike a RAW there is no JPEG preview inside to lift. It is decoded in software instead, by libheif built to wasm, in a worker of its own — so a folder of them reads without the tab stopping for a second, and what leaves the worker is the same JPEG developRaw hands the studio. Nothing downstream knows the difference. Into the studio it goes on the same terms as every other frame: dropped, picked, or opened from the catalogue, no tier asked and the engine's own colour untouched. The frame's date, ISO and position come off the HEIC itself, which is passed along as the bytes the stamps read. The catalogue's tile does not pay the decode: a phone writes a small HEVC copy of its frame as an item of its own (thmb, 320x240 on an iPhone), reachable only by walking the container by hand, and it decodes in milliseconds where the frame takes a second — from the same 256KB the catalogue already reads for a header. The shelves themselves now want an account: a guest gets the note and the way in, and the scan never starts.
This commit is contained in:
@@ -17,6 +17,7 @@ import { loadEngine, MARK_FACES } from './engine/assets';
|
||||
import { renderPhoto, type RenderAssets } from './engine/exportEngine';
|
||||
import { download, fileToBytes, readCapturedAt, readGps, readIso, resizedJpeg, scaledJpeg } from './engine/imageOps';
|
||||
import { developRaw, isRawName } from './engine/rawDevelop';
|
||||
import { heicToJpeg, isHeicName } from './engine/heicDevelop';
|
||||
import { clearRaw, readRaw, storeRaw } from './engine/rawStore';
|
||||
import { getPhoto, loadEdit, readPhotoFile, saveEdit, setRotation as savePhotoRotation } from './engine/library';
|
||||
import { offerInstall } from './pwa/install';
|
||||
@@ -1130,6 +1131,25 @@ export function Workspace() {
|
||||
void forgetPhoto();
|
||||
return;
|
||||
}
|
||||
if (isHeicName(file.name)) {
|
||||
// A phone's HEIC: no engine on this platform paints one (see
|
||||
// heicWorker.ts), so it is decoded to the JPEG the studio works on —
|
||||
// by the same worker the catalogue's tiles come from. No tier: unlike
|
||||
// a RAW there is nothing here for the engine to develop, only a format
|
||||
// the browser will not read, and the decode is a plain reading of the
|
||||
// pixels the file already holds.
|
||||
//
|
||||
// The session keeps the decode, not the file, so a reload opens the
|
||||
// frame at once instead of paying the second again. The name stays the
|
||||
// file's own, and it is no RAW name, so the reload path above shows the
|
||||
// saved copy as the picture it is. The HEIC goes along as the bytes the
|
||||
// stamps read: the JPEG the worker made carries no EXIF of its own.
|
||||
await clearRaw();
|
||||
const jpeg = await heicToJpeg(bytes);
|
||||
await adoptPhoto(jpeg, file.name, new Blob([jpeg as BlobPart], { type: 'image/jpeg' }), false, bytes);
|
||||
void savePhoto(file.name, jpeg);
|
||||
return;
|
||||
}
|
||||
await clearRaw();
|
||||
await adoptPhoto(bytes, file.name, file);
|
||||
void savePhoto(file.name, bytes);
|
||||
|
||||
Reference in New Issue
Block a user