diff --git a/desktop/CHANGELOG.md b/desktop/CHANGELOG.md index 091ace6c38..34699edc79 100644 --- a/desktop/CHANGELOG.md +++ b/desktop/CHANGELOG.md @@ -2,6 +2,7 @@ ## v1.7.8 (Unreleased) +- Parse description from image metadata. - . ## v1.7.7 diff --git a/web/apps/photos/src/services/upload/upload-service.ts b/web/apps/photos/src/services/upload/upload-service.ts index 66ebe28406..38ce924081 100644 --- a/web/apps/photos/src/services/upload/upload-service.ts +++ b/web/apps/photos/src/services/upload/upload-service.ts @@ -1073,7 +1073,8 @@ const extractImageOrVideoMetadata = async ( if (h) publicMagicMetadata.h = ensureInteger(h); } - const caption = parsedMetadataJSON?.description; + const caption = + parsedMetadataJSON?.description ?? parsedMetadata.description; if (caption) { publicMagicMetadata.caption = caption; } diff --git a/web/packages/media/file-metadata.ts b/web/packages/media/file-metadata.ts index 75bc8bf6c0..b431a24f76 100644 --- a/web/packages/media/file-metadata.ts +++ b/web/packages/media/file-metadata.ts @@ -604,6 +604,10 @@ export interface ParsedMetadata { creationDate?: ParsedMetadataDate; /** The GPS coordinates where the photo was taken. */ location?: Location; + /** + * A caption / description attached by the user to the photo. + */ + description?: string; } /** diff --git a/web/packages/new/photos/services/exif.ts b/web/packages/new/photos/services/exif.ts index 782434323e..5c76398327 100644 --- a/web/packages/new/photos/services/exif.ts +++ b/web/packages/new/photos/services/exif.ts @@ -40,10 +40,12 @@ export const parseExif = (tags: RawExifTags) => { const location = parseLocation(tags); const creationDate = parseCreationDate(tags); const dimensions = parseDimensions(tags); + const description = parseDescription(tags); const metadata: ParsedMetadata = dimensions ?? {}; if (creationDate) metadata.creationDate = creationDate; if (location) metadata.location = location; + if (description) metadata.description = description; return metadata; }; @@ -536,3 +538,25 @@ export const tagNumericValue = ( const v = tag.value; return Array.isArray(v) ? (v[0] ?? 0) / (v[1] ?? 1) : v; }; + +/** + * Parse the description for an image from the metadata embedded in the file. + * + * This function will read the description from the following fields, in order: + * + * 1. XMP-dc:description + * 2. IPTC | Caption/Abstract (120) + * 3. EXIF IFD0 | 0x010e | ImageDescription + * + * For an overview of why this ordering was chosen, see + * https://github.com/ente-io/ente/discussions/3857#discussioncomment-11764990 + */ +const parseDescription = (tags: RawExifTags) => + // While the TypeScript tags for these three fields are varying (The XMP one + // doesn't have a static type, the IPTC one is marked as a number array, and + // the Exif one is a string array), for all three of these, the ExifReader + // description property (not related to the image "description" in the sense + // of this function) holds the singular string we're interested in. + tags.xmp?.description?.description ?? + tags.iptc?.["Caption/Abstract"]?.description ?? + tags.exif?.ImageDescription?.description;