info: improved exif tag display

This commit is contained in:
Thibault Deckers 2021-12-31 12:35:23 +09:00
parent acdb7afa6d
commit e5fe3e980f
3 changed files with 40 additions and 23 deletions

View file

@ -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<String, String> {
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<String, String>().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. <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core Test.SNAPSHOT">...</x:xmpmeta>
}
private fun exifTagMapper(it: Tag): Pair<String, String> {
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"

View file

@ -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

View file

@ -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