catalog: fallback date from XMP photoshop:DateCreated, fallback HEIF date from MMR

This commit is contained in:
Thibault Deckers 2020-12-08 11:21:56 +09:00
parent ca670e4ee9
commit b297fd5fe0
2 changed files with 36 additions and 23 deletions

View file

@ -200,6 +200,20 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
return dirMap
}
// set `KEY_DATE_MILLIS` from these fields (by precedence):
// - ME / Exif / DATETIME_ORIGINAL
// - ME / Exif / DATETIME
// - EI / Exif / DATETIME_ORIGINAL
// - EI / Exif / DATETIME
// - ME / XMP / xmp:CreateDate
// - ME / XMP / photoshop:DateCreated
// - MMR / METADATA_KEY_DATE
// set `KEY_XMP_TITLE_DESCRIPTION` from these fields (by precedence):
// - ME / XMP / dc:title
// - ME / XMP / dc:description
// set `KEY_XMP_SUBJECTS` from these fields (by precedence):
// - ME / XMP / dc:subject
// - ME / IPTC / keywords
private fun getCatalogMetadata(call: MethodCall, result: MethodChannel.Result) {
val mimeType = call.argument<String>("mimeType")
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
@ -211,24 +225,14 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
}
val metadataMap = HashMap(getCatalogMetadataByMetadataExtractor(uri, mimeType, path, sizeBytes))
if (isVideo(mimeType)) {
metadataMap.putAll(getVideoCatalogMetadataByMediaMetadataRetriever(uri))
if (isMultimedia(mimeType)) {
metadataMap.putAll(getMultimediaCatalogMetadataByMediaMetadataRetriever(uri))
}
// report success even when empty
result.success(metadataMap)
}
// set `KEY_DATE_MILLIS` from these fields (by precedence):
// - Exif / DATETIME_ORIGINAL
// - Exif / DATETIME
// - XMP / xmp:CreateDate
// set `KEY_XMP_TITLE_DESCRIPTION` from these fields (by precedence):
// - XMP / dc:title
// - XMP / dc:description
// set `KEY_XMP_SUBJECTS` from these fields (by precedence):
// - XMP / dc:subject
// - IPTC / keywords
private fun getCatalogMetadataByMetadataExtractor(uri: Uri, mimeType: String, path: String?, sizeBytes: Long?): Map<String, Any> {
val metadataMap = HashMap<String, Any>()
@ -301,6 +305,9 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
}
if (!metadataMap.containsKey(KEY_DATE_MILLIS)) {
xmpMeta.getSafeDateMillis(XMP.XMP_SCHEMA_NS, XMP.CREATE_DATE_PROP_NAME) { metadataMap[KEY_DATE_MILLIS] = it }
if (!metadataMap.containsKey(KEY_DATE_MILLIS)) {
xmpMeta.getSafeDateMillis(XMP.PHOTOSHOP_SCHEMA_NS, XMP.PS_DATE_CREATED_PROP_NAME) { metadataMap[KEY_DATE_MILLIS] = it }
}
}
// identification of panorama (aka photo sphere)
@ -381,13 +388,16 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
return metadataMap
}
private fun getVideoCatalogMetadataByMediaMetadataRetriever(uri: Uri): Map<String, Any> {
private fun getMultimediaCatalogMetadataByMediaMetadataRetriever(uri: Uri): Map<String, Any> {
val metadataMap = HashMap<String, Any>()
val retriever = StorageUtils.openMetadataRetriever(context, uri) ?: return metadataMap
try {
retriever.getSafeInt(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION) { metadataMap[KEY_ROTATION_DEGREES] = it }
if (!metadataMap.containsKey(KEY_DATE_MILLIS)) {
retriever.getSafeDateMillis(MediaMetadataRetriever.METADATA_KEY_DATE) { metadataMap[KEY_DATE_MILLIS] = it }
}
if (!metadataMap.containsKey(KEY_LATITUDE)) {
val locationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION)
if (locationString != null) {
val matcher = Metadata.VIDEO_LOCATION_PATTERN.matcher(locationString)
@ -400,6 +410,7 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
}
}
}
}
} catch (e: Exception) {
Log.w(LOG_TAG, "failed to get catalog metadata by MediaMetadataRetriever for uri=$uri", e)
} finally {

View file

@ -10,12 +10,14 @@ object XMP {
private val LOG_TAG = LogUtils.createTag(XMP::class.java)
const val DC_SCHEMA_NS = "http://purl.org/dc/elements/1.1/"
const val PHOTOSHOP_SCHEMA_NS = "http://ns.adobe.com/photoshop/1.0/"
const val XMP_SCHEMA_NS = "http://ns.adobe.com/xap/1.0/"
const val IMG_SCHEMA_NS = "http://ns.adobe.com/xap/1.0/g/img/"
const val SUBJECT_PROP_NAME = "dc:subject"
const val TITLE_PROP_NAME = "dc:title"
const val DESCRIPTION_PROP_NAME = "dc:description"
const val PS_DATE_CREATED_PROP_NAME = "photoshop:DateCreated";
const val CREATE_DATE_PROP_NAME = "xmp:CreateDate"
const val THUMBNAIL_PROP_NAME = "xmp:Thumbnails"
const val THUMBNAIL_IMAGE_PROP_NAME = "xmpGImg:image"