#976 identify Apple variant of HDR images

This commit is contained in:
Thibault Deckers 2024-04-16 22:09:57 +02:00
parent e9d2e3c42e
commit ce27d47342
3 changed files with 38 additions and 0 deletions

View file

@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
## <a id="unreleased"></a>[Unreleased] ## <a id="unreleased"></a>[Unreleased]
### Added
- Cataloguing: identify Apple variant of HDR images
## <a id="v1.10.9"></a>[v1.10.9] - 2024-04-14 ## <a id="v1.10.9"></a>[v1.10.9] - 2024-04-14
### Fixed ### Fixed

View file

@ -20,6 +20,7 @@ import com.drew.metadata.exif.ExifDirectoryBase
import com.drew.metadata.exif.ExifIFD0Directory import com.drew.metadata.exif.ExifIFD0Directory
import com.drew.metadata.exif.ExifSubIFDDirectory import com.drew.metadata.exif.ExifSubIFDDirectory
import com.drew.metadata.exif.GpsDirectory import com.drew.metadata.exif.GpsDirectory
import com.drew.metadata.exif.makernotes.AppleMakernoteDirectory
import com.drew.metadata.file.FileTypeDirectory import com.drew.metadata.file.FileTypeDirectory
import com.drew.metadata.gif.GifAnimationDirectory import com.drew.metadata.gif.GifAnimationDirectory
import com.drew.metadata.iptc.IptcDirectory 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.getSafeString
import deckers.thibault.aves.metadata.metadataextractor.Helper.isPngTextDir import deckers.thibault.aves.metadata.metadataextractor.Helper.isPngTextDir
import deckers.thibault.aves.metadata.metadataextractor.PngActlDirectory 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.metadataextractor.mpf.MpEntryDirectory
import deckers.thibault.aves.metadata.xmp.GoogleXMP import deckers.thibault.aves.metadata.xmp.GoogleXMP
import deckers.thibault.aves.metadata.xmp.XMP import deckers.thibault.aves.metadata.xmp.XMP
@ -639,6 +641,10 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
// JPEG Multi-Picture Format // JPEG Multi-Picture Format
if (metadata.getDirectoriesOfType(MpEntryDirectory::class.java).count { !it.entry.isThumbnail } > 1) { if (metadata.getDirectoriesOfType(MpEntryDirectory::class.java).count { !it.entry.isThumbnail } > 1) {
flags = flags or MASK_IS_MULTIPAGE flags = flags or MASK_IS_MULTIPAGE
if (hasAppleHdrGainMap(uri, sizeBytes, metadata)) {
flags = flags or MASK_IS_HDR
}
} }
// XMP // XMP
@ -765,6 +771,29 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
metadataMap[KEY_FLAGS] = flags 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( private fun getMultimediaCatalogMetadataByMediaMetadataRetriever(
mimeType: String, mimeType: String,
uri: Uri, uri: Uri,

View file

@ -40,6 +40,7 @@ object XMP {
private const val XMP_NS_URI = "http://ns.adobe.com/xap/1.0/" private const val XMP_NS_URI = "http://ns.adobe.com/xap/1.0/"
// other namespaces // 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 HDRGM_NS_URI = "http://ns.adobe.com/hdr-gain-map/1.0/"
private const val PMTM_NS_URI = "http://www.hdrsoft.com/photomatix_settings01" private const val PMTM_NS_URI = "http://www.hdrsoft.com/photomatix_settings01"
@ -59,6 +60,7 @@ object XMP {
// HDR gain map // HDR gain map
private val HDRGM_VERSION_PROP_NAME = XMPPropName(HDRGM_NS_URI, "Version") 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 // panorama
@ -137,6 +139,9 @@ object XMP {
// `Ultra HDR` // `Ultra HDR`
if (GoogleXMP.isUltraHdPhoto(this)) return true if (GoogleXMP.isUltraHdPhoto(this)) return true
// Apple HDR gain map
if (doesPropExist(APPLE_HDRGM_VERSION_PROP_NAME)) return true
return false return false
} catch (e: XMPException) { } catch (e: XMPException) {
if (e.errorCode != XMPError.BADSCHEMA) { if (e.errorCode != XMPError.BADSCHEMA) {