From e25a1eefb9c30565853a71c297f95c2006f7031a Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sat, 27 Feb 2021 19:08:24 +0900 Subject: [PATCH] fixed opening panorama with non-gpano xmp namespace --- .../aves/channel/calls/MetadataHandler.kt | 34 +++++++++---------- .../deckers/thibault/aves/metadata/XMP.kt | 28 +++++++++++++++ lib/widgets/viewer/overlay/panorama.dart | 20 ++++++----- 3 files changed, 55 insertions(+), 27 deletions(-) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataHandler.kt index 2d8656cbb..1dbcdc345 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataHandler.kt @@ -47,7 +47,9 @@ import deckers.thibault.aves.metadata.MetadataExtractorHelper.getSafeRational import deckers.thibault.aves.metadata.MetadataExtractorHelper.getSafeString import deckers.thibault.aves.metadata.MetadataExtractorHelper.isGeoTiff import deckers.thibault.aves.metadata.XMP.getSafeDateMillis +import deckers.thibault.aves.metadata.XMP.getSafeInt import deckers.thibault.aves.metadata.XMP.getSafeLocalizedText +import deckers.thibault.aves.metadata.XMP.getSafeString import deckers.thibault.aves.metadata.XMP.isPanorama import deckers.thibault.aves.model.FieldMap import deckers.thibault.aves.model.provider.FileImageProvider @@ -627,25 +629,21 @@ class MetadataHandler(private val context: Context) : MethodCallHandler { try { Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input -> val metadata = ImageMetadataReader.readMetadata(input) - val xmpDirs = metadata.getDirectoriesOfType(XmpDirectory::class.java) - try { - fun getIntProp(propName: String): Int? = xmpDirs.map { it.xmpMeta.getPropertyInteger(XMP.GPANO_SCHEMA_NS, propName) }.firstOrNull { it != null } - fun getStringProp(propName: String): String? = xmpDirs.map { it.xmpMeta.getPropertyString(XMP.GPANO_SCHEMA_NS, propName) }.firstOrNull { it != null } - val fields: FieldMap = hashMapOf( - "croppedAreaLeft" to getIntProp(XMP.GPANO_CROPPED_AREA_LEFT_PROP_NAME), - "croppedAreaTop" to getIntProp(XMP.GPANO_CROPPED_AREA_TOP_PROP_NAME), - "croppedAreaWidth" to getIntProp(XMP.GPANO_CROPPED_AREA_WIDTH_PROP_NAME), - "croppedAreaHeight" to getIntProp(XMP.GPANO_CROPPED_AREA_HEIGHT_PROP_NAME), - "fullPanoWidth" to getIntProp(XMP.GPANO_FULL_PANO_WIDTH_PROP_NAME), - "fullPanoHeight" to getIntProp(XMP.GPANO_FULL_PANO_HEIGHT_PROP_NAME), - "projectionType" to (getStringProp(XMP.GPANO_PROJECTION_TYPE_PROP_NAME) ?: XMP.GPANO_PROJECTION_TYPE_DEFAULT), - ) - result.success(fields) - return - } catch (e: XMPException) { - result.error("getPanoramaInfo-args", "failed to read XMP for uri=$uri", e.message) - return + val fields = hashMapOf( + "projectionType" to XMP.GPANO_PROJECTION_TYPE_DEFAULT, + ) + for (dir in metadata.getDirectoriesOfType(XmpDirectory::class.java)) { + val xmpMeta = dir.xmpMeta + xmpMeta.getSafeInt(XMP.GPANO_SCHEMA_NS, XMP.GPANO_CROPPED_AREA_LEFT_PROP_NAME) { fields["croppedAreaLeft"] = it } + xmpMeta.getSafeInt(XMP.GPANO_SCHEMA_NS, XMP.GPANO_CROPPED_AREA_TOP_PROP_NAME) { fields["croppedAreaTop"] = it } + xmpMeta.getSafeInt(XMP.GPANO_SCHEMA_NS, XMP.GPANO_CROPPED_AREA_WIDTH_PROP_NAME) { fields["croppedAreaWidth"] = it } + xmpMeta.getSafeInt(XMP.GPANO_SCHEMA_NS, XMP.GPANO_CROPPED_AREA_HEIGHT_PROP_NAME) { fields["croppedAreaHeight"] = it } + xmpMeta.getSafeInt(XMP.GPANO_SCHEMA_NS, XMP.GPANO_FULL_PANO_WIDTH_PROP_NAME) { fields["fullPanoWidth"] = it } + xmpMeta.getSafeInt(XMP.GPANO_SCHEMA_NS, XMP.GPANO_FULL_PANO_HEIGHT_PROP_NAME) { fields["fullPanoHeight"] = it } + xmpMeta.getSafeString(XMP.GPANO_SCHEMA_NS, XMP.GPANO_PROJECTION_TYPE_PROP_NAME) { fields["projectionType"] = it } } + result.success(fields) + return } } catch (e: Exception) { Log.w(LOG_TAG, "failed to read XMP", e) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt index 0ca46696b..6d411f1e5 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt @@ -97,6 +97,34 @@ object XMP { return false } + fun XMPMeta.getSafeInt(schema: String, propName: String, save: (value: Int) -> Unit) { + try { + if (doesPropertyExist(schema, propName)) { + val item = getPropertyInteger(schema, propName) + // double check retrieved items as the property sometimes is reported to exist but it is actually null + if (item != null) { + save(item) + } + } + } catch (e: XMPException) { + Log.w(LOG_TAG, "failed to get int for XMP schema=$schema, propName=$propName", e) + } + } + + fun XMPMeta.getSafeString(schema: String, propName: String, save: (value: String) -> Unit) { + try { + if (doesPropertyExist(schema, propName)) { + val item = getPropertyString(schema, propName) + // double check retrieved items as the property sometimes is reported to exist but it is actually null + if (item != null) { + save(item) + } + } + } catch (e: XMPException) { + Log.w(LOG_TAG, "failed to get int for XMP schema=$schema, propName=$propName", e) + } + } + fun XMPMeta.getSafeLocalizedText(schema: String, propName: String, acceptBlank: Boolean = true, save: (value: String) -> Unit) { try { if (doesPropertyExist(schema, propName)) { diff --git a/lib/widgets/viewer/overlay/panorama.dart b/lib/widgets/viewer/overlay/panorama.dart index 0d142edeb..fe6a2dbb0 100644 --- a/lib/widgets/viewer/overlay/panorama.dart +++ b/lib/widgets/viewer/overlay/panorama.dart @@ -25,16 +25,18 @@ class PanoramaOverlay extends StatelessWidget { text: 'Open Panorama', onPressed: () async { final info = await MetadataService.getPanoramaInfo(entry); - unawaited(Navigator.push( - context, - MaterialPageRoute( - settings: RouteSettings(name: PanoramaPage.routeName), - builder: (context) => PanoramaPage( - entry: entry, - info: info, + if (info != null) { + unawaited(Navigator.push( + context, + MaterialPageRoute( + settings: RouteSettings(name: PanoramaPage.routeName), + builder: (context) => PanoramaPage( + entry: entry, + info: info, + ), ), - ), - )); + )); + } }, ) ],