#443 Info: improved NS prefix handling

This commit is contained in:
Thibault Deckers 2023-01-16 14:24:54 +01:00
parent a6b5398962
commit 86c6e7ce93
14 changed files with 132 additions and 98 deletions

View file

@ -12,7 +12,7 @@ import com.drew.metadata.xmp.XmpDirectory
import deckers.thibault.aves.channel.calls.Coresult.Companion.safe
import deckers.thibault.aves.channel.calls.Coresult.Companion.safeSuspend
import deckers.thibault.aves.metadata.*
import deckers.thibault.aves.metadata.XMP.doesPropExist
import deckers.thibault.aves.metadata.XMP.doesPropPathExist
import deckers.thibault.aves.metadata.XMP.getSafeStructField
import deckers.thibault.aves.metadata.metadataextractor.Helper
import deckers.thibault.aves.model.FieldMap
@ -104,7 +104,7 @@ class EmbeddedDataHandler(private val context: Context) : MethodCallHandler {
try {
container = xmpDirs.firstNotNullOfOrNull {
val xmpMeta = it.xmpMeta
if (xmpMeta.doesPropExist(XMP.GDEVICE_DIRECTORY_PROP_NAME)) {
if (xmpMeta.doesPropPathExist(listOf(XMP.GDEVICE_CONTAINER_PROP_NAME, XMP.GDEVICE_CONTAINER_DIRECTORY_PROP_NAME))) {
GoogleDeviceContainer().apply { findItems(xmpMeta) }
} else {
null

View file

@ -3,7 +3,7 @@ package deckers.thibault.aves.metadata
import android.content.Context
import android.net.Uri
import com.adobe.internal.xmp.XMPMeta
import deckers.thibault.aves.metadata.XMP.countPropArrayItems
import deckers.thibault.aves.metadata.XMP.countPropPathArrayItems
import deckers.thibault.aves.metadata.XMP.getSafeStructField
import deckers.thibault.aves.utils.indexOfBytes
import java.io.DataInputStream
@ -15,11 +15,12 @@ class GoogleDeviceContainer {
private val offsets: MutableList<Int> = ArrayList()
fun findItems(xmpMeta: XMPMeta) {
val count = xmpMeta.countPropArrayItems(XMP.GDEVICE_DIRECTORY_PROP_NAME)
val containerDirectoryPath = listOf(XMP.GDEVICE_CONTAINER_PROP_NAME, XMP.GDEVICE_CONTAINER_DIRECTORY_PROP_NAME)
val count = xmpMeta.countPropPathArrayItems(containerDirectoryPath)
for (i in 1 until count + 1) {
val mimeType = xmpMeta.getSafeStructField(listOf(XMP.GDEVICE_DIRECTORY_PROP_NAME, i, XMP.GDEVICE_CONTAINER_ITEM_MIME_PROP_NAME))?.value
val length = xmpMeta.getSafeStructField(listOf(XMP.GDEVICE_DIRECTORY_PROP_NAME, i, XMP.GDEVICE_CONTAINER_ITEM_LENGTH_PROP_NAME))?.value?.toLongOrNull()
val dataUri = xmpMeta.getSafeStructField(listOf(XMP.GDEVICE_DIRECTORY_PROP_NAME, i, XMP.GDEVICE_CONTAINER_ITEM_DATA_URI_PROP_NAME))?.value
val mimeType = xmpMeta.getSafeStructField(containerDirectoryPath + listOf(i, XMP.GDEVICE_CONTAINER_ITEM_MIME_PROP_NAME))?.value
val length = xmpMeta.getSafeStructField(containerDirectoryPath + listOf(i, XMP.GDEVICE_CONTAINER_ITEM_LENGTH_PROP_NAME))?.value?.toLongOrNull()
val dataUri = xmpMeta.getSafeStructField(containerDirectoryPath + listOf(i, XMP.GDEVICE_CONTAINER_ITEM_DATA_URI_PROP_NAME))?.value
if (mimeType != null && length != null && dataUri != null) {
items.add(
GoogleDeviceContainerItem(

View file

@ -49,6 +49,7 @@ object XMP {
private const val GCONTAINER_ITEM_NS_URI = "http://ns.google.com/photos/1.0/container/item/"
private const val GDEPTH_NS_URI = "http://ns.google.com/photos/1.0/depthmap/"
private const val GDEVICE_NS_URI = "http://ns.google.com/photos/dd/1.0/device/"
private const val GDEVICE_CONTAINER_NS_URI = "http://ns.google.com/photos/dd/1.0/container/"
private const val GDEVICE_ITEM_NS_URI = "http://ns.google.com/photos/dd/1.0/item/"
private const val GIMAGE_NS_URI = "http://ns.google.com/photos/1.0/image/"
private const val GPANO_NS_URI = "http://ns.google.com/photos/1.0/panorama/"
@ -79,7 +80,8 @@ object XMP {
// google portrait
val GDEVICE_DIRECTORY_PROP_NAME = XMPPropName(GDEVICE_NS_URI, "Container/Container:Directory")
val GDEVICE_CONTAINER_PROP_NAME = XMPPropName(GDEVICE_NS_URI, "Container")
val GDEVICE_CONTAINER_DIRECTORY_PROP_NAME = XMPPropName(GDEVICE_CONTAINER_NS_URI, "Directory")
val GDEVICE_CONTAINER_ITEM_DATA_URI_PROP_NAME = XMPPropName(GDEVICE_ITEM_NS_URI, "DataURI")
val GDEVICE_CONTAINER_ITEM_LENGTH_PROP_NAME = XMPPropName(GDEVICE_ITEM_NS_URI, "Length")
val GDEVICE_CONTAINER_ITEM_MIME_PROP_NAME = XMPPropName(GDEVICE_ITEM_NS_URI, "Mime")
@ -254,10 +256,18 @@ object XMP {
return doesPropertyExist(prop.nsUri, prop.toString())
}
fun XMPMeta.doesPropPathExist(props: List<XMPPropName>): Boolean {
return doesPropertyExist(props.first().nsUri, props.joinToString("/"))
}
fun XMPMeta.countPropArrayItems(prop: XMPPropName): Int {
return countArrayItems(prop.nsUri, prop.toString())
}
fun XMPMeta.countPropPathArrayItems(props: List<XMPPropName>): Int {
return countArrayItems(props.first().nsUri, props.joinToString("/"))
}
fun XMPMeta.getPropArrayItemValues(prop: XMPPropName): List<String> {
val schema = prop.nsUri
val propName = prop.toString()

View file

@ -463,7 +463,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry {
modified |= XMP.removeElements(
descriptions,
XMP.containerDirectory,
Namespaces.container,
Namespaces.gContainer,
);
modified |= [

View file

@ -7,7 +7,6 @@ class Namespaces {
static const avm = 'http://www.communicatingastronomy.org/avm/1.0/';
static const camera = 'http://pix4d.com/camera/1.0/';
static const cc = 'http://creativecommons.org/ns#';
static const container = 'http://ns.google.com/photos/1.0/container/';
static const creatorAtom = 'http://ns.adobe.com/creatorAtom/1.0/';
static const crd = 'http://ns.adobe.com/camera-raw-defaults/1.0/';
static const crlcp = 'http://ns.adobe.com/camera-raw-embedded-lens-profile/1.0/';
@ -26,9 +25,13 @@ class Namespaces {
static const exifEx = 'http://cipa.jp/exif/1.0/';
static const gAudio = 'http://ns.google.com/photos/1.0/audio/';
static const gCamera = 'http://ns.google.com/photos/1.0/camera/';
static const gContainer = 'http://ns.google.com/photos/1.0/container/';
static const gCreations = 'http://ns.google.com/photos/1.0/creations/';
static const gDepth = 'http://ns.google.com/photos/1.0/depthmap/';
static const gDevice = 'http://ns.google.com/photos/dd/1.0/device/';
static const gDeviceCamera = 'http://ns.google.com/photos/dd/1.0/camera/';
static const gDeviceContainer = 'http://ns.google.com/photos/dd/1.0/container/';
static const gDeviceItem = 'http://ns.google.com/photos/dd/1.0/item/';
static const gFocus = 'http://ns.google.com/photos/1.0/focus/';
static const gImage = 'http://ns.google.com/photos/1.0/image/';
static const gPano = 'http://ns.google.com/photos/1.0/panorama/';
@ -83,7 +86,6 @@ class Namespaces {
avm: 'Astronomy Visualization',
camera: 'Pix4D Camera',
cc: 'Creative Commons',
container: 'Container',
crd: 'Camera Raw Defaults',
creatorAtom: 'After Effects',
crs: 'Camera Raw Settings',
@ -97,6 +99,7 @@ class Namespaces {
exifEx: 'Exif Ex',
gAudio: 'Google Audio',
gCamera: 'Google Camera',
gContainer: 'Google Container',
gCreations: 'Google Creations',
gDepth: 'Google Depth',
gDevice: 'Google Device',
@ -138,7 +141,7 @@ class Namespaces {
};
static final defaultPrefixes = {
container: 'Container',
gContainer: 'Container',
dc: 'dc',
gCamera: 'GCamera',
microsoftPhoto: 'MicrosoftPhoto',

View file

@ -22,56 +22,62 @@ import 'package:tuple/tuple.dart';
@immutable
class XmpNamespace extends Equatable {
final Map<String, String> schemaRegistryPrefixes;
final String nsUri, nsPrefix;
final Map<String, String> rawProps;
@override
List<Object?> get props => [nsUri, nsPrefix];
const XmpNamespace(this.nsUri, this.nsPrefix, this.rawProps);
XmpNamespace({
required this.nsUri,
required this.schemaRegistryPrefixes,
required this.rawProps,
}) : nsPrefix = prefixForUri(schemaRegistryPrefixes, nsUri);
factory XmpNamespace.create(String nsUri, String nsPrefix, Map<String, String> rawProps) {
factory XmpNamespace.create(Map<String, String> schemaRegistryPrefixes, String nsPrefix, Map<String, String> rawProps) {
final nsUri = schemaRegistryPrefixes[nsPrefix] ?? '';
switch (nsUri) {
case Namespaces.container:
return XmpContainer(nsPrefix, rawProps);
case Namespaces.creatorAtom:
return XmpCreatorAtom(nsPrefix, rawProps);
return XmpCreatorAtom(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.crs:
return XmpCrsNamespace(nsPrefix, rawProps);
return XmpCrsNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.darktable:
return XmpDarktableNamespace(nsPrefix, rawProps);
return XmpDarktableNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.dwc:
return XmpDwcNamespace(nsPrefix, rawProps);
return XmpDwcNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.exif:
return XmpExifNamespace(nsPrefix, rawProps);
return XmpExifNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.gAudio:
return XmpGAudioNamespace(nsPrefix, rawProps);
return XmpGAudioNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.gContainer:
return XmpGContainer(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.gDepth:
return XmpGDepthNamespace(nsPrefix, rawProps);
return XmpGDepthNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.gDevice:
return XmpGDeviceNamespace(nsPrefix, rawProps);
return XmpGDeviceNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.gImage:
return XmpGImageNamespace(nsPrefix, rawProps);
return XmpGImageNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.iptc4xmpCore:
return XmpIptcCoreNamespace(nsPrefix, rawProps);
return XmpIptcCoreNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.iptc4xmpExt:
return XmpIptc4xmpExtNamespace(nsPrefix, rawProps);
return XmpIptc4xmpExtNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.mwgrs:
return XmpMgwRegionsNamespace(nsPrefix, rawProps);
return XmpMgwRegionsNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.mp:
return XmpMPNamespace(nsPrefix, rawProps);
return XmpMPNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.photoshop:
return XmpPhotoshopNamespace(nsPrefix, rawProps);
return XmpPhotoshopNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.plus:
return XmpPlusNamespace(nsPrefix, rawProps);
return XmpPlusNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.tiff:
return XmpTiffNamespace(nsPrefix, rawProps);
return XmpTiffNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.xmp:
return XmpBasicNamespace(nsPrefix, rawProps);
return XmpBasicNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
case Namespaces.xmpMM:
return XmpMMNamespace(nsPrefix, rawProps);
return XmpMMNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
default:
return XmpNamespace(nsUri, nsPrefix, rawProps);
return XmpNamespace(nsUri: nsUri, schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps);
}
}
@ -130,6 +136,8 @@ class XmpNamespace extends Equatable {
String formatValue(XmpProp prop) => prop.value;
Map<String, InfoValueSpanBuilder> linkifyValues(List<XmpProp> props) => {};
static String prefixForUri(Map<String, String> schemaRegistryPrefixes, String nsUri) => schemaRegistryPrefixes.entries.firstWhereOrNull((kv) => kv.value == nsUri)?.key ?? '';
}
class XmpProp implements Comparable<XmpProp> {

View file

@ -2,7 +2,7 @@ import 'package:aves/utils/xmp_utils.dart';
import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
class XmpCrsNamespace extends XmpNamespace {
XmpCrsNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.crs, nsPrefix, rawProps);
XmpCrsNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.crs);
@override
late final List<XmpCardData> cards = [

View file

@ -4,68 +4,69 @@ import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
// cf https://github.com/adobe/xmp-docs/blob/master/XMPNamespaces/exif.md
class XmpExifNamespace extends XmpNamespace {
const XmpExifNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.exif, nsPrefix, rawProps);
XmpExifNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.exif);
@override
String formatValue(XmpProp prop) {
final v = prop.value;
switch (prop.path) {
case 'exif:ColorSpace':
final field = prop.path.replaceAll(nsPrefix, '');
switch (field) {
case 'ColorSpace':
return Exif.getColorSpaceDescription(v);
case 'exif:Contrast':
case 'Contrast':
return Exif.getContrastDescription(v);
case 'exif:CustomRendered':
case 'CustomRendered':
return Exif.getCustomRenderedDescription(v);
case 'exif:ExifVersion':
case 'exif:FlashpixVersion':
case 'ExifVersion':
case 'FlashpixVersion':
return Exif.getExifVersionDescription(v);
case 'exif:ExposureMode':
case 'ExposureMode':
return Exif.getExposureModeDescription(v);
case 'exif:ExposureProgram':
case 'ExposureProgram':
return Exif.getExposureProgramDescription(v);
case 'exif:FileSource':
case 'FileSource':
return Exif.getFileSourceDescription(v);
case 'exif:Flash/exif:Mode':
case 'Flash/Mode':
return Exif.getFlashModeDescription(v);
case 'exif:Flash/exif:Return':
case 'Flash/Return':
return Exif.getFlashReturnDescription(v);
case 'exif:FocalPlaneResolutionUnit':
case 'FocalPlaneResolutionUnit':
return Exif.getResolutionUnitDescription(v);
case 'exif:GainControl':
case 'GainControl':
return Exif.getGainControlDescription(v);
case 'exif:LightSource':
case 'LightSource':
return Exif.getLightSourceDescription(v);
case 'exif:MeteringMode':
case 'MeteringMode':
return Exif.getMeteringModeDescription(v);
case 'exif:Saturation':
case 'Saturation':
return Exif.getSaturationDescription(v);
case 'exif:SceneCaptureType':
case 'SceneCaptureType':
return Exif.getSceneCaptureTypeDescription(v);
case 'exif:SceneType':
case 'SceneType':
return Exif.getSceneTypeDescription(v);
case 'exif:SensingMethod':
case 'SensingMethod':
return Exif.getSensingMethodDescription(v);
case 'exif:Sharpness':
case 'Sharpness':
return Exif.getSharpnessDescription(v);
case 'exif:SubjectDistanceRange':
case 'SubjectDistanceRange':
return Exif.getSubjectDistanceRangeDescription(v);
case 'exif:WhiteBalance':
case 'WhiteBalance':
return Exif.getWhiteBalanceDescription(v);
case 'exif:GPSAltitudeRef':
case 'GPSAltitudeRef':
return Exif.getGPSAltitudeRefDescription(v);
case 'exif:GPSDestBearingRef':
case 'exif:GPSImgDirectionRef':
case 'exif:GPSTrackRef':
case 'GPSDestBearingRef':
case 'GPSImgDirectionRef':
case 'GPSTrackRef':
return Exif.getGPSDirectionRefDescription(v);
case 'exif:GPSDestDistanceRef':
case 'GPSDestDistanceRef':
return Exif.getGPSDestDistanceRefDescription(v);
case 'exif:GPSDifferential':
case 'GPSDifferential':
return Exif.getGPSDifferentialDescription(v);
case 'exif:GPSMeasureMode':
case 'GPSMeasureMode':
return Exif.getGPSMeasureModeDescription(v);
case 'exif:GPSSpeedRef':
case 'GPSSpeedRef':
return Exif.getGPSSpeedRefDescription(v);
case 'exif:GPSStatus':
case 'GPSStatus':
return Exif.getGPSStatusDescription(v);
default:
return v;

View file

@ -7,7 +7,11 @@ import 'package:collection/collection.dart';
import 'package:tuple/tuple.dart';
abstract class XmpGoogleNamespace extends XmpNamespace {
const XmpGoogleNamespace(String nsUri, String nsPrefix, Map<String, String> rawProps) : super(nsUri, nsPrefix, rawProps);
XmpGoogleNamespace({
required super.nsUri,
required super.schemaRegistryPrefixes,
required super.rawProps,
});
List<Tuple2<String, String>> get dataProps;
@ -53,14 +57,14 @@ abstract class XmpGoogleNamespace extends XmpNamespace {
}
class XmpGAudioNamespace extends XmpGoogleNamespace {
const XmpGAudioNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.gAudio, nsPrefix, rawProps);
XmpGAudioNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.gAudio);
@override
List<Tuple2<String, String>> get dataProps => [Tuple2('${nsPrefix}Data', '${nsPrefix}Mime')];
}
class XmpGDepthNamespace extends XmpGoogleNamespace {
const XmpGDepthNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.gDepth, nsPrefix, rawProps);
XmpGDepthNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.gDepth);
@override
List<Tuple2<String, String>> get dataProps => [
@ -70,8 +74,16 @@ class XmpGDepthNamespace extends XmpGoogleNamespace {
}
class XmpGDeviceNamespace extends XmpNamespace {
XmpGDeviceNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.gDevice, nsPrefix, rawProps) {
final mimePattern = RegExp(nsPrefix + r'Container/Container:Directory\[(\d+)\]/Item:Mime');
late final String _cameraNsPrefix;
late final String _containerNsPrefix;
late final String _itemNsPrefix;
XmpGDeviceNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.gDevice) {
_cameraNsPrefix = XmpNamespace.prefixForUri(schemaRegistryPrefixes, Namespaces.gDeviceCamera);
_containerNsPrefix = XmpNamespace.prefixForUri(schemaRegistryPrefixes, Namespaces.gDeviceContainer);
_itemNsPrefix = XmpNamespace.prefixForUri(schemaRegistryPrefixes, Namespaces.gDeviceItem);
final mimePattern = RegExp(nsPrefix + r'Container/' + _containerNsPrefix + r'Directory\[(\d+)\]/' + _itemNsPrefix + r'Mime');
final originalProps = rawProps.entries.toList();
originalProps.forEach((kv) {
final path = kv.key;
@ -81,7 +93,7 @@ class XmpGDeviceNamespace extends XmpNamespace {
if (indexString != null) {
final index = int.tryParse(indexString);
if (index != null) {
final dataPath = '${nsPrefix}Container/Container:Directory[$index]/Item:Data';
final dataPath = '${nsPrefix}Container/${_containerNsPrefix}Directory[$index]/${_itemNsPrefix}Data';
rawProps[dataPath] = '[skipped]';
}
}
@ -94,16 +106,16 @@ class XmpGDeviceNamespace extends XmpNamespace {
XmpCardData(
RegExp(nsPrefix + r'Cameras\[(\d+)\]/(.*)'),
cards: [
XmpCardData(RegExp(r'Camera:DepthMap/(.*)')),
XmpCardData(RegExp(r'Camera:Image/(.*)')),
XmpCardData(RegExp(r'Camera:ImagingModel/(.*)')),
XmpCardData(RegExp(_cameraNsPrefix + r'DepthMap/(.*)')),
XmpCardData(RegExp(_cameraNsPrefix + r'Image/(.*)')),
XmpCardData(RegExp(_cameraNsPrefix + r'ImagingModel/(.*)')),
],
),
XmpCardData(
RegExp(nsPrefix + r'Container/Container:Directory\[(\d+)\]/(.*)'),
RegExp(nsPrefix + r'Container/' + _containerNsPrefix + r'Directory\[(\d+)\]/(.*)'),
spanBuilders: (index, struct) {
if (struct.containsKey('Item:Data') && struct.containsKey('Item:DataURI')) {
final dataUriProp = struct['Item:DataURI'];
if (struct.containsKey('${_itemNsPrefix}Data') && struct.containsKey('${_itemNsPrefix}DataURI')) {
final dataUriProp = struct['${_itemNsPrefix}DataURI'];
if (dataUriProp != null) {
return {
'Data': InfoRowGroup.linkSpanBuilder(
@ -121,17 +133,17 @@ class XmpGDeviceNamespace extends XmpNamespace {
}
class XmpGImageNamespace extends XmpGoogleNamespace {
const XmpGImageNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.gImage, nsPrefix, rawProps);
XmpGImageNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.gImage);
@override
List<Tuple2<String, String>> get dataProps => [Tuple2('${nsPrefix}Data', '${nsPrefix}Mime')];
}
class XmpContainer extends XmpNamespace {
XmpContainer(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.container, nsPrefix, rawProps);
class XmpGContainer extends XmpNamespace {
XmpGContainer({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.gContainer);
@override
late final List<XmpCardData> cards = [
XmpCardData(RegExp('${nsPrefix}Directory\\[(\\d+)\\]/${nsPrefix}Item/(.*)'), title: 'Directory Item'),
XmpCardData(RegExp(nsPrefix + r'Directory\[(\d+)\]/' + nsPrefix + r'Item/(.*)'), title: 'Directory Item'),
];
}

View file

@ -2,7 +2,7 @@ import 'package:aves/utils/xmp_utils.dart';
import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
class XmpCreatorAtom extends XmpNamespace {
XmpCreatorAtom(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.creatorAtom, nsPrefix, rawProps);
XmpCreatorAtom({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.creatorAtom);
@override
late final List<XmpCardData> cards = [
@ -11,7 +11,7 @@ class XmpCreatorAtom extends XmpNamespace {
}
class XmpDarktableNamespace extends XmpNamespace {
XmpDarktableNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.darktable, nsPrefix, rawProps);
XmpDarktableNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.darktable);
@override
late final List<XmpCardData> cards = [
@ -20,7 +20,7 @@ class XmpDarktableNamespace extends XmpNamespace {
}
class XmpDwcNamespace extends XmpNamespace {
XmpDwcNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.dwc, nsPrefix, rawProps);
XmpDwcNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.dwc);
@override
late final List<XmpCardData> cards = [
@ -37,7 +37,7 @@ class XmpDwcNamespace extends XmpNamespace {
}
class XmpIptcCoreNamespace extends XmpNamespace {
XmpIptcCoreNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.iptc4xmpCore, nsPrefix, rawProps);
XmpIptcCoreNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.iptc4xmpCore);
@override
late final List<XmpCardData> cards = [
@ -46,7 +46,7 @@ class XmpIptcCoreNamespace extends XmpNamespace {
}
class XmpIptc4xmpExtNamespace extends XmpNamespace {
XmpIptc4xmpExtNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.iptc4xmpExt, nsPrefix, rawProps);
XmpIptc4xmpExtNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.iptc4xmpExt);
@override
late final List<XmpCardData> cards = [
@ -55,7 +55,7 @@ class XmpIptc4xmpExtNamespace extends XmpNamespace {
}
class XmpMPNamespace extends XmpNamespace {
XmpMPNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.mp, nsPrefix, rawProps);
XmpMPNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.mp);
@override
late final List<XmpCardData> cards = [
@ -65,7 +65,7 @@ class XmpMPNamespace extends XmpNamespace {
// cf www.metadataworkinggroup.org/pdf/mwg_guidance.pdf (down, as of 2021/02/15)
class XmpMgwRegionsNamespace extends XmpNamespace {
XmpMgwRegionsNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.mwgrs, nsPrefix, rawProps);
XmpMgwRegionsNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.mwgrs);
@override
late final List<XmpCardData> cards = [
@ -75,7 +75,7 @@ class XmpMgwRegionsNamespace extends XmpNamespace {
}
class XmpPlusNamespace extends XmpNamespace {
XmpPlusNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.plus, nsPrefix, rawProps);
XmpPlusNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.plus);
@override
late final List<XmpCardData> cards = [
@ -86,7 +86,7 @@ class XmpPlusNamespace extends XmpNamespace {
}
class XmpMMNamespace extends XmpNamespace {
XmpMMNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.xmpMM, nsPrefix, rawProps);
XmpMMNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.xmpMM);
@override
late final List<XmpCardData> cards = [

View file

@ -3,7 +3,7 @@ import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
// cf https://github.com/adobe/xmp-docs/blob/master/XMPNamespaces/photoshop.md
class XmpPhotoshopNamespace extends XmpNamespace {
XmpPhotoshopNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.photoshop, nsPrefix, rawProps);
XmpPhotoshopNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.photoshop);
@override
late final List<XmpCardData> cards = [

View file

@ -4,7 +4,7 @@ import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
// cf https://github.com/adobe/xmp-docs/blob/master/XMPNamespaces/tiff.md
class XmpTiffNamespace extends XmpNamespace {
const XmpTiffNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.tiff, nsPrefix, rawProps);
XmpTiffNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.tiff);
@override
String formatValue(XmpProp prop) {

View file

@ -6,7 +6,7 @@ import 'package:aves/widgets/viewer/info/common.dart';
import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
class XmpBasicNamespace extends XmpNamespace {
XmpBasicNamespace(String nsPrefix, Map<String, String> rawProps) : super(Namespaces.xmp, nsPrefix, rawProps);
XmpBasicNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.xmp);
@override
late final List<XmpCardData> cards = [

View file

@ -56,9 +56,8 @@ class _XmpDirTileState extends State<XmpDirTile> {
return nsPrefix;
}).entries.map((kv) {
final nsPrefix = kv.key;
final nsUri = _schemaRegistryPrefixes[nsPrefix] ?? '';
final rawProps = Map.fromEntries(kv.value);
return XmpNamespace.create(nsUri, nsPrefix, rawProps);
return XmpNamespace.create(_schemaRegistryPrefixes, nsPrefix, rawProps);
}).toList()
..sort((a, b) => compareAsciiUpperCase(a.displayTitle, b.displayTitle));
return AvesExpansionTile(