feat(exif): name the capture device and place (0x9a00/0x0110/0x889d) for the Gallery frame
The framing tool matches Make/Model against its known-device list and prints the place name; a CameraX capture only carried the raw model codename (2203121C) and no 0x9a00/0x889d, which is what a stock camera photo always has. State the market name plus the geotag locality, and leave a source that already carries 0x9a00 untouched so a library photo of another device is never relabelled.
This commit is contained in:
+26
-1
@@ -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'));
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user