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 53a4f3d7c..d0fcdd67c 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 @@ -19,7 +19,10 @@ import com.drew.lang.KeyValuePair import com.drew.lang.Rational import com.drew.metadata.Tag import com.drew.metadata.avi.AviDirectory -import com.drew.metadata.exif.* +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.file.FileTypeDirectory import com.drew.metadata.gif.GifAnimationDirectory import com.drew.metadata.iptc.IptcDirectory @@ -160,25 +163,16 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler { // tags val tags = dir.tags - if (mimeType == MimeTypes.TIFF && (dir is ExifIFD0Directory || dir is ExifThumbnailDirectory)) { - fun tagMapper(it: Tag): Pair { - val name = if (it.hasTagName()) { - it.tagName - } else { - TiffTags.getTagName(it.tagType) ?: it.tagName - } - return Pair(name, it.description) - } - - if (dir is ExifIFD0Directory && dir.isGeoTiff()) { + if (dir is ExifDirectoryBase) { + if (dir.isGeoTiff()) { // split GeoTIFF tags in their own directory - val byGeoTiff = tags.groupBy { TiffTags.isGeoTiffTag(it.tagType) } + val byGeoTiff = tags.groupBy { ExifTags.isGeoTiffTag(it.tagType) } metadataMap["GeoTIFF"] = HashMap().apply { - byGeoTiff[true]?.map { tagMapper(it) }?.let { putAll(it) } + byGeoTiff[true]?.map { exifTagMapper(it) }?.let { putAll(it) } } - byGeoTiff[false]?.map { tagMapper(it) }?.let { dirMap.putAll(it) } + byGeoTiff[false]?.map { exifTagMapper(it) }?.let { dirMap.putAll(it) } } else { - dirMap.putAll(tags.map { tagMapper(it) }) + dirMap.putAll(tags.map { exifTagMapper(it) }) } } else if (dir.isPngTextDir()) { metadataMap.remove(thisDirName) @@ -210,7 +204,12 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler { val profileDirName = "${dir.name}/${profileDir.name}" val profileDirMap = metadataMap[profileDirName] ?: HashMap() metadataMap[profileDirName] = profileDirMap - profileDirMap.putAll(profileDir.tags.map { Pair(it.tagName, it.description) }) + val profileTags = profileDir.tags + if (profileDir is ExifDirectoryBase) { + profileDirMap.putAll(profileTags.map { exifTagMapper(it) }) + } else { + profileDirMap.putAll(profileTags.map { Pair(it.tagName, it.description) }) + } } null } else { @@ -974,6 +973,15 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler { omitXmpMetaElement = false // e.g. ... } + private fun exifTagMapper(it: Tag): Pair { + val name = if (it.hasTagName()) { + it.tagName + } else { + ExifTags.getTagName(it.tagType) ?: it.tagName + } + return Pair(name, it.description) + } + // catalog metadata private const val KEY_MIME_TYPE = "mimeType" private const val KEY_DATE_MILLIS = "dateMillis" diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/TiffTags.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/ExifTags.kt similarity index 94% rename from android/app/src/main/kotlin/deckers/thibault/aves/metadata/TiffTags.kt rename to android/app/src/main/kotlin/deckers/thibault/aves/metadata/ExifTags.kt index 2f8a9c23c..4dbe77450 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/TiffTags.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/ExifTags.kt @@ -1,6 +1,7 @@ package deckers.thibault.aves.metadata -object TiffTags { +// Exif tags missing from `metadata-extractor` +object ExifTags { // XPosition // Tag = 286 (011E.H) private const val TAG_X_POSITION = 0x011e @@ -32,6 +33,12 @@ object TiffTags { // SAMPLEFORMAT_COMPLEXIEEEFP 6 // complex ieee floating private const val TAG_SAMPLE_FORMAT = 0x0153 + + // Rating tag used by Windows, value in percent + // Tag = 18249 (4749.H) + // Type = SHORT + private const val TAG_RATING_PERCENT = 0x4749 + /* SGI tags 32995-32999 @@ -125,6 +132,7 @@ object TiffTags { TAG_COLOR_MAP to "Color Map", TAG_EXTRA_SAMPLES to "Extra Samples", TAG_SAMPLE_FORMAT to "Sample Format", + TAG_RATING_PERCENT to "Rating Percent", // SGI TAG_MATTEING to "Matteing", // GeoTIFF diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/MetadataExtractorHelper.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/MetadataExtractorHelper.kt index 1b518da6d..84d5959f2 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/MetadataExtractorHelper.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/MetadataExtractorHelper.kt @@ -5,6 +5,7 @@ import com.drew.lang.ByteArrayReader import com.drew.lang.Rational import com.drew.lang.SequentialByteArrayReader import com.drew.metadata.Directory +import com.drew.metadata.exif.ExifDirectoryBase import com.drew.metadata.exif.ExifIFD0Directory import com.drew.metadata.exif.ExifReader import com.drew.metadata.iptc.IptcReader @@ -68,14 +69,14 @@ object MetadataExtractorHelper { - If the ModelTransformationTag is included in an IFD, then a ModelPixelScaleTag SHALL NOT be included - If the ModelPixelScaleTag is included in an IFD, then a ModelTiepointTag SHALL also be included. */ - fun ExifIFD0Directory.isGeoTiff(): Boolean { - if (!this.containsTag(TiffTags.TAG_GEO_KEY_DIRECTORY)) return false + fun ExifDirectoryBase.isGeoTiff(): Boolean { + if (!this.containsTag(ExifTags.TAG_GEO_KEY_DIRECTORY)) return false - val modelTiepoint = this.containsTag(TiffTags.TAG_MODEL_TIEPOINT) - val modelTransformation = this.containsTag(TiffTags.TAG_MODEL_TRANSFORMATION) + val modelTiepoint = this.containsTag(ExifTags.TAG_MODEL_TIEPOINT) + val modelTransformation = this.containsTag(ExifTags.TAG_MODEL_TRANSFORMATION) if (!modelTiepoint && !modelTransformation) return false - val modelPixelScale = this.containsTag(TiffTags.TAG_MODEL_PIXEL_SCALE) + val modelPixelScale = this.containsTag(ExifTags.TAG_MODEL_PIXEL_SCALE) if ((modelTransformation && modelPixelScale) || (modelPixelScale && !modelTiepoint)) return false return true