diff --git a/src/utils/exifWrite.ts b/src/utils/exifWrite.ts index 10cfb82..0111320 100644 --- a/src/utils/exifWrite.ts +++ b/src/utils/exifWrite.ts @@ -22,6 +22,10 @@ export interface ExifStamp { // DateTimeOriginal and only fill it in when the source has none. dateTime?: Date | null; gps?: { latitude: number; longitude: number } | null; + // Place name shown on the Gallery frame (EXIF 0x889d). Stock photos carry it + // whenever the capture was geotagged; ours have to state it from the same + // info the watermark prints. + locationName?: string | null; width?: number | null; height?: number | null; dpi?: number | null; @@ -394,10 +398,31 @@ export function writeJpegExif(jpeg: Uint8Array, stamp: ExifStamp, sourceJpeg?: U // HyperOS Gallery refuses to open its watermark editor without 0x889e, and a // CameraX capture never carries it. Never overwrite a blob the source has. - if (stamp.device && !exif.has(0x889e) && /xiaomi|redmi|poco/i.test(stamp.device.manufacturer)) { + const xiaomi = !!stamp.device && /xiaomi|redmi|poco/i.test(stamp.device.manufacturer); + if (stamp.device && xiaomi && !exif.has(0x889e)) { exif.set(0x889e, asciiEntry(0x889e, watermarkBlob(stamp.device))); } + // Stock Xiaomi photos name the device in 0x9a00 and in Model (0x0110) as the + // MARKET name ("Xiaomi 14 Ultra"); the framing tool matches those against its + // known-device list and reports an unknown device otherwise. A CameraX capture + // only has the raw codename, so state the market name. A source that already + // carries 0x9a00 is a stock photo of some other device — leave it alone. + if (stamp.device && xiaomi && !ifd0.has(0x9a00)) { + const market = (stamp.device.marketName || stamp.device.model).trim(); + if (market) { + ifd0.set(0x9a00, asciiEntry(0x9a00, market)); + ifd0.set(0x0110, asciiEntry(0x0110, market)); + } + } + + // Place name the frame prints (0x889d) — stock writes it in both IFDs. + const place = stamp.locationName?.trim(); + if (place) { + if (!ifd0.has(0x889d)) ifd0.set(0x889d, asciiEntry(0x889d, place)); + if (!exif.has(0x889d)) exif.set(0x889d, asciiEntry(0x889d, place)); + } + if (stamp.gps) { const { latitude: lat, longitude: lon } = stamp.gps; gps.set(0x0001, asciiEntry(0x0001, lat >= 0 ? 'N' : 'S')); diff --git a/src/utils/exportEngine.ts b/src/utils/exportEngine.ts index 1e2091c..87e4a76 100644 --- a/src/utils/exportEngine.ts +++ b/src/utils/exportEngine.ts @@ -721,6 +721,7 @@ export async function processAndExportPhoto( width: resultImage.width(), height: resultImage.height(), dpi: options?.dpi ?? null, + locationName: useGeotag && gpsInfo ? gpsInfo.locality : null, device: getDeviceIdentity(), }, await readPhotoBytes(sourceUri)