diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3bda00713..01ef0cb47 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
+### Added
+
+- Cataloguing: identify Apple variant of HDR images
+
## [v1.10.9] - 2024-04-14
### Fixed
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt
index 0ef28ec13..57a035142 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt
@@ -20,6 +20,7 @@ import com.drew.metadata.exif.ExifDirectoryBase
import com.drew.metadata.exif.ExifIFD0Directory
import com.drew.metadata.exif.ExifSubIFDDirectory
import com.drew.metadata.exif.GpsDirectory
+import com.drew.metadata.exif.makernotes.AppleMakernoteDirectory
import com.drew.metadata.file.FileTypeDirectory
import com.drew.metadata.gif.GifAnimationDirectory
import com.drew.metadata.iptc.IptcDirectory
@@ -69,6 +70,7 @@ import deckers.thibault.aves.metadata.metadataextractor.Helper.getSafeRational
import deckers.thibault.aves.metadata.metadataextractor.Helper.getSafeString
import deckers.thibault.aves.metadata.metadataextractor.Helper.isPngTextDir
import deckers.thibault.aves.metadata.metadataextractor.PngActlDirectory
+import deckers.thibault.aves.metadata.metadataextractor.mpf.MpEntry
import deckers.thibault.aves.metadata.metadataextractor.mpf.MpEntryDirectory
import deckers.thibault.aves.metadata.xmp.GoogleXMP
import deckers.thibault.aves.metadata.xmp.XMP
@@ -639,6 +641,10 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
// JPEG Multi-Picture Format
if (metadata.getDirectoriesOfType(MpEntryDirectory::class.java).count { !it.entry.isThumbnail } > 1) {
flags = flags or MASK_IS_MULTIPAGE
+
+ if (hasAppleHdrGainMap(uri, sizeBytes, metadata)) {
+ flags = flags or MASK_IS_HDR
+ }
}
// XMP
@@ -765,6 +771,29 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
metadataMap[KEY_FLAGS] = flags
}
+ private fun hasAppleHdrGainMap(uri: Uri, sizeBytes: Long?, primaryMetadata: com.drew.metadata.Metadata): Boolean {
+ if (!primaryMetadata.containsDirectoryOfType(AppleMakernoteDirectory::class.java)) return false
+
+ val mpEntries = MultiPage.getJpegMpfEntries(context, uri, sizeBytes) ?: return false
+ mpEntries.filter { it.type == MpEntry.TYPE_UNDEFINED }.forEach { mpEntry ->
+ var dataOffset = mpEntry.dataOffset
+ if (dataOffset > 0) {
+ val baseOffset = MultiPage.getJpegMpfBaseOffset(context, uri, sizeBytes)
+ if (baseOffset != null) {
+ dataOffset += baseOffset
+ }
+ }
+ StorageUtils.openInputStream(context, uri)?.let { input ->
+ input.skip(dataOffset)
+ val pageMetadata = Helper.safeRead(input)
+ if (pageMetadata.getDirectoriesOfType(XmpDirectory::class.java).any { it.xmpMeta.hasHdrGainMap() }) {
+ return true
+ }
+ }
+ }
+ return false
+ }
+
private fun getMultimediaCatalogMetadataByMediaMetadataRetriever(
mimeType: String,
uri: Uri,
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/xmp/XMP.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/xmp/XMP.kt
index 47a26ca7d..b7d49f9f9 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/xmp/XMP.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/xmp/XMP.kt
@@ -40,6 +40,7 @@ object XMP {
private const val XMP_NS_URI = "http://ns.adobe.com/xap/1.0/"
// other namespaces
+ private const val APPLE_HDRGM_NS_URI = "http://ns.apple.com/HDRGainMap/1.0/"
private const val HDRGM_NS_URI = "http://ns.adobe.com/hdr-gain-map/1.0/"
private const val PMTM_NS_URI = "http://www.hdrsoft.com/photomatix_settings01"
@@ -59,6 +60,7 @@ object XMP {
// HDR gain map
private val HDRGM_VERSION_PROP_NAME = XMPPropName(HDRGM_NS_URI, "Version")
+ private val APPLE_HDRGM_VERSION_PROP_NAME = XMPPropName(APPLE_HDRGM_NS_URI, "HDRGainMapVersion")
// panorama
@@ -137,6 +139,9 @@ object XMP {
// `Ultra HDR`
if (GoogleXMP.isUltraHdPhoto(this)) return true
+ // Apple HDR gain map
+ if (doesPropExist(APPLE_HDRGM_VERSION_PROP_NAME)) return true
+
return false
} catch (e: XMPException) {
if (e.errorCode != XMPError.BADSCHEMA) {