public DirectoryList ReadJpegSegments(IEnumerable <JpegSegment> segments) { // Ensure collection materialised (avoiding multiple lazy enumeration) segments = segments.ToList(); var directories = segments .Where(IsXmpSegment) .Select(segment => Extract(segment.Bytes, JpegSegmentPreambleBytes.Length, segment.Bytes.Length - JpegSegmentPreambleBytes.Length)) .Cast <Directory>() .ToList(); var extensionGroups = segments.Where(IsExtendedXmpSegment).GroupBy(GetExtendedDataGuid); foreach (var extensionGroup in extensionGroups) { var buffer = new MemoryStream(); foreach (var segment in extensionGroup) { var N = JpegSegmentPreambleExtensionBytes.Length + 32 + 4 + 4; buffer.Write(segment.Bytes, N, segment.Bytes.Length - N); } buffer.Position = 0; var directory = new XmpDirectory(); var xmpMeta = XmpMetaFactory.Parse(buffer); directory.SetXmpMeta(xmpMeta); directories.Add(directory); } return(directories); }
public XmpReaderTest() { var jpegSegments = new [] { File.ReadAllBytes("Tests/Data/withXmpAndIptc.jpg.app1.1") }; var directories = new XmpReader().ReadJpegSegments(jpegSegments, JpegSegmentType.App1); _directory = directories.OfType<XmpDirectory>().ToList().Single(); Assert.False(_directory.HasError); }
public XmpDirectory Extract([NotNull] byte[] xmpBytes, int offset, int length) { if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset), "Must be zero or greater."); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), "Must be zero or greater."); } if (xmpBytes.Length < offset + length) { throw new ArgumentException("Extends beyond length of byte array.", nameof(length)); } // Trim any trailing null bytes // https://github.com/drewnoakes/metadata-extractor-dotnet/issues/154 while (xmpBytes[offset + length - 1] == 0) { length--; } var directory = new XmpDirectory(); try { var xmpMeta = XmpMetaFactory.ParseFromBuffer(xmpBytes, offset, length); directory.SetXmpMeta(xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } return(directory); }
/// <exception cref="XmpException"/> private static void ProcessXmpTags(XmpDirectory directory, IXmpMeta xmpMeta) { // store the XMPMeta object on the directory in case others wish to use it directory.SetXmpMeta(xmpMeta); // read all the tags and send them to the directory // I've added some popular tags, feel free to add more tags ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagLensInfo, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagLens, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagCameraSerialNumber, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagFirmware, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagMake, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagModel, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagExposureTime, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagExposureProgram, FormatType.Int); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagApertureValue, FormatType.Rational); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagFNumber, FormatType.Rational); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagFocalLength, FormatType.Rational); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagShutterSpeed, FormatType.Rational); ProcessXmpDateTag(xmpMeta, directory, XmpDirectory.TagDateTimeOriginal); ProcessXmpDateTag(xmpMeta, directory, XmpDirectory.TagDateTimeDigitized); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagRating, FormatType.Double); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagLabel, FormatType.String); // this requires further research // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:title", XmpDirectory.TAG_TITLE, FMT_STRING); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagSubject, FormatType.StringArray); // processXmpDateTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:date", XmpDirectory.TAG_DATE); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:type", XmpDirectory.TAG_TYPE, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:description", XmpDirectory.TAG_DESCRIPTION, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:relation", XmpDirectory.TAG_RELATION, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:coverage", XmpDirectory.TAG_COVERAGE, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:creator", XmpDirectory.TAG_CREATOR, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:publisher", XmpDirectory.TAG_PUBLISHER, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:contributor", XmpDirectory.TAG_CONTRIBUTOR, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:rights", XmpDirectory.TAG_RIGHTS, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:format", XmpDirectory.TAG_FORMAT, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:identifier", XmpDirectory.TAG_IDENTIFIER, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:language", XmpDirectory.TAG_LANGUAGE, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:audience", XmpDirectory.TAG_AUDIENCE, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:provenance", XmpDirectory.TAG_PROVENANCE, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:rightsHolder", XmpDirectory.TAG_RIGHTS_HOLDER, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:instructionalMethod", XmpDirectory.TAG_INSTRUCTIONAL_METHOD, // FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:accrualMethod", XmpDirectory.TAG_ACCRUAL_METHOD, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:accrualPeriodicity", XmpDirectory.TAG_ACCRUAL_PERIODICITY, // FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:accrualPolicy", XmpDirectory.TAG_ACCRUAL_POLICY, FMT_STRING); foreach (var prop in xmpMeta.Properties) { var path = prop.Path; var value = prop.Value; if (path != null && value != null) { directory.AddProperty(path, value); } } }
private static void ProcessXmpTags([NotNull] XmpDirectory directory, [NotNull] IXmpMeta xmpMeta) { // store the XMPMeta object on the directory in case others wish to use it directory.SetXmpMeta(xmpMeta); // extract selected XMP tags ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagLensInfo, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagLens, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagCameraSerialNumber, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagFirmware, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagMake, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagModel, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagExposureTime, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagExposureProgram, FormatType.Int); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagApertureValue, FormatType.Rational); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagFNumber, FormatType.Rational); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagFocalLength, FormatType.Rational); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagShutterSpeed, FormatType.Rational); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagDateTimeOriginal, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagDateTimeDigitized, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagBaseUrl, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagCreateDate, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagCreatorTool, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagIdentifier, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagMetadataDate, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagModifyDate, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagNickname, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagRating, FormatType.Double); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagLabel, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagSubject, FormatType.StringArray); // this requires further research // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:title", XmpDirectory.TAG_TITLE, FMT_STRING); // ProcessXmpDateTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:date", XmpDirectory.TAG_DATE); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:type", XmpDirectory.TAG_TYPE, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:description", XmpDirectory.TAG_DESCRIPTION, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:relation", XmpDirectory.TAG_RELATION, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:coverage", XmpDirectory.TAG_COVERAGE, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:creator", XmpDirectory.TAG_CREATOR, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:publisher", XmpDirectory.TAG_PUBLISHER, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:contributor", XmpDirectory.TAG_CONTRIBUTOR, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:rights", XmpDirectory.TAG_RIGHTS, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:format", XmpDirectory.TAG_FORMAT, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:identifier", XmpDirectory.TAG_IDENTIFIER, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:language", XmpDirectory.TAG_LANGUAGE, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:audience", XmpDirectory.TAG_AUDIENCE, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:provenance", XmpDirectory.TAG_PROVENANCE, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:rightsHolder", XmpDirectory.TAG_RIGHTS_HOLDER, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:instructionalMethod", XmpDirectory.TAG_INSTRUCTIONAL_METHOD, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:accrualMethod", XmpDirectory.TAG_ACCRUAL_METHOD, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:accrualPeriodicity", XmpDirectory.TAG_ACCRUAL_PERIODICITY, FMT_STRING); // ProcessXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:accrualPolicy", XmpDirectory.TAG_ACCRUAL_POLICY, FMT_STRING); }
public XmpDirectory Extract([NotNull] byte[] xmpBytes, int offset, int length) { var directory = new XmpDirectory(); try { var xmpMeta = XmpMetaFactory.ParseFromBuffer(xmpBytes, offset, length); directory.SetXmpMeta(xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } return(directory); }
/// <summary> /// Performs the XMP data extraction. /// <para /> /// The extraction is done with Adobe's XMPCore library. /// </summary> public XmpDirectory Extract([NotNull] byte[] xmpBytes) { var directory = new XmpDirectory(); try { var xmpMeta = XmpMetaFactory.ParseFromBuffer(xmpBytes); ProcessXmpTags(directory, xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } return(directory); }
/// <exception cref="XmpException"/> private static void ProcessXmpDateTag([NotNull] IXmpMeta meta, [NotNull] XmpDirectory directory, int tagType) { string schemaNs; string propName; if (!XmpDirectory.TagSchemaMap.TryGetValue(tagType, out schemaNs) || !XmpDirectory.TagPropNameMap.TryGetValue(tagType, out propName)) { return; } var cal = meta.GetPropertyCalendar(schemaNs, propName); if (cal != null) { directory.Set(tagType, cal.GetTime()); } }
public XmpDirectory Extract([NotNull] byte[] xmpBytes, int offset, int length) { if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset), "Must be zero or greater."); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), "Must be zero or greater."); } if (xmpBytes.Length < offset + length) { throw new ArgumentException("Extends beyond length of byte array.", nameof(length)); } // Trim any trailing null bytes // https://github.com/drewnoakes/metadata-extractor-dotnet/issues/154 while (xmpBytes[offset + length - 1] == 0) { length--; } var directory = new XmpDirectory(); try { // Limit photoshop:DocumentAncestors node as it can reach over 100000 items and make parsing extremely slow. // This is not a typical value but it may happen https://forums.adobe.com/thread/2081839 var parseOptions = new ParseOptions(); parseOptions.SetXMPNodesToLimit(new Dictionary <string, int>() { { "photoshop:DocumentAncestors", 1000 } }); var xmpMeta = XmpMetaFactory.ParseFromBuffer(xmpBytes, offset, length, parseOptions); directory.SetXmpMeta(xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } return(directory); }
internal static TreeDirectory GetHierarchicalDirectory(XmpDirectory directories) { TreeDirectory root = new TreeDirectory(); TreeDirectory[] treeNodes = directories.XmpMeta.Properties.Where(x => x.Path != null).Select(x => new TreeDirectory(x)).ToArray(); var possibleChildrean = treeNodes.Select(x => new { Element = x, PossibleChildrean = treeNodes.Where(y => y.Element.Path != x.Element.Path && y.Element.Path.StartsWith(x.Element.Path)).ToArray() }).ToArray(); var childOfRoot = possibleChildrean.Where(x => !possibleChildrean.Any(y => y.PossibleChildrean.Contains(x.Element))).ToArray(); root.Childrean.AddRange(childOfRoot.Select(x => x.Element)); foreach (var child in childOfRoot) { child.Element.Parent = root; } foreach (var node in possibleChildrean) { TreeDirectory[] childOfNode = node.PossibleChildrean.Where(x => !possibleChildrean.Where(y => node.PossibleChildrean.Contains(y.Element)).Any(y => y.PossibleChildrean.Contains(x))).ToArray(); node.Element.Childrean.AddRange(childOfNode); foreach (var child in childOfNode) { child.Parent = node.Element; } } return root; }
private static void ProcessXmpTag([NotNull] IXmpMeta meta, [NotNull] XmpDirectory directory, int tagType, FormatType formatCode) { string schemaNs; string propName; if (!XmpDirectory.TagSchemaMap.TryGetValue(tagType, out schemaNs) || !XmpDirectory.TagPropNameMap.TryGetValue(tagType, out propName)) { return; } var property = meta.GetPropertyString(schemaNs, propName); if (property == null) { return; } switch (formatCode) { case FormatType.Rational: { // TODO introduce Rational.TryParse var rationalParts = property.Split('/').Take(2).ToArray(); if (rationalParts.Length == 2) { // TODO should this really be parsed as float? float numerator; float denominator; if (float.TryParse(rationalParts[0], out numerator) && float.TryParse(rationalParts[1], out denominator)) { directory.Set(tagType, new Rational((long)numerator, (long)denominator)); } else { directory.AddError($"Unable to parse XMP property {propName} as a Rational."); } } else { directory.AddError($"Error in rational format for tag {tagType}"); } break; } case FormatType.Int: { int value; if (int.TryParse(property, out value)) { directory.Set(tagType, value); } else { directory.AddError($"Unable to parse XMP property {propName} as an int."); } break; } case FormatType.Double: { double value; if (double.TryParse(property, out value)) { directory.Set(tagType, value); } else { directory.AddError($"Unable to parse XMP property {propName} as a double."); } break; } case FormatType.String: { directory.Set(tagType, property); break; } case FormatType.StringArray: { // XMP iterators are 1-based var count = meta.CountArrayItems(schemaNs, propName); var array = new string[count]; for (var i = 1; i <= count; i++) { array[i - 1] = meta.GetArrayItem(schemaNs, propName, i).Value; } directory.Set(tagType, array); break; } default: { directory.AddError($"Unknown format code {formatCode} for tag {tagType}"); break; } } }
/// <summary> /// Performs the XMP data extraction. /// </summary> /// <remarks> /// The extraction is done with Adobe's XMPCore library. /// </remarks> //public XmpDirectory Extract([NotNull] string xmpString) => Extract(Encoding.UTF8.GetBytes(xmpString)); /// <exception cref="XmpException"/> private static void ProcessXmpTags(XmpDirectory directory, IXmpMeta xmpMeta) { // store the XMPMeta object on the directory in case others wish to use it directory.SetXmpMeta(xmpMeta); // read all the tags and send them to the directory // I've added some popular tags, feel free to add more tags ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagLensInfo, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagLens, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagCameraSerialNumber, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagFirmware, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagMake, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagModel, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagExposureTime, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagExposureProgram, FormatType.Int); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagApertureValue, FormatType.Rational); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagFNumber, FormatType.Rational); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagFocalLength, FormatType.Rational); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagShutterSpeed, FormatType.Rational); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagDateTimeOriginal, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagDateTimeDigitized, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagBaseUrl, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagCreateDate, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagCreatorTool, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagIdentifier, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagMetadataDate, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagModifyDate, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagNickname, FormatType.String); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagRating, FormatType.Double); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagLabel, FormatType.String); // this requires further research // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:title", XmpDirectory.TAG_TITLE, FMT_STRING); ProcessXmpTag(xmpMeta, directory, XmpDirectory.TagSubject, FormatType.StringArray); // processXmpDateTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:date", XmpDirectory.TAG_DATE); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:type", XmpDirectory.TAG_TYPE, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:description", XmpDirectory.TAG_DESCRIPTION, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:relation", XmpDirectory.TAG_RELATION, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:coverage", XmpDirectory.TAG_COVERAGE, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:creator", XmpDirectory.TAG_CREATOR, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:publisher", XmpDirectory.TAG_PUBLISHER, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:contributor", XmpDirectory.TAG_CONTRIBUTOR, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:rights", XmpDirectory.TAG_RIGHTS, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:format", XmpDirectory.TAG_FORMAT, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:identifier", XmpDirectory.TAG_IDENTIFIER, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:language", XmpDirectory.TAG_LANGUAGE, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:audience", XmpDirectory.TAG_AUDIENCE, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:provenance", XmpDirectory.TAG_PROVENANCE, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:rightsHolder", XmpDirectory.TAG_RIGHTS_HOLDER, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:instructionalMethod", XmpDirectory.TAG_INSTRUCTIONAL_METHOD, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:accrualMethod", XmpDirectory.TAG_ACCRUAL_METHOD, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:accrualPeriodicity", XmpDirectory.TAG_ACCRUAL_PERIODICITY, FMT_STRING); // processXmpTag(xmpMeta, directory, Schema.DUBLIN_CORE_SPECIFIC_PROPERTIES, "dc:accrualPolicy", XmpDirectory.TAG_ACCRUAL_POLICY, FMT_STRING); foreach (var prop in xmpMeta.Properties) { var path = prop.Path; var value = prop.Value; if (path != null && value != null) directory.AddProperty(path, value); } }
/// <summary> /// Performs the XMP data extraction. /// </summary> /// <remarks> /// The extraction is done with Adobe's XMPCore library. /// </remarks> public XmpDirectory Extract([NotNull] byte[] xmpBytes) { var directory = new XmpDirectory(); try { var xmpMeta = XmpMetaFactory.ParseFromBuffer(xmpBytes); ProcessXmpTags(directory, xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } return directory; }
/// <summary>Reads an property value with given namespace URI and property name.</summary> /// <remarks>Reads an property value with given namespace URI and property name. Add property value to directory if exists</remarks> /// <exception cref="XmpException"/> private static void ProcessXmpTag([NotNull] IXmpMeta meta, [NotNull] XmpDirectory directory, int tagType, FormatType formatCode) { string schemaNs; string propName; if (!XmpDirectory.TagSchemaMap.TryGetValue(tagType, out schemaNs) || !XmpDirectory.TagPropNameMap.TryGetValue(tagType, out propName)) { return; } var property = meta.GetPropertyString(schemaNs, propName); if (property == null) { return; } switch (formatCode) { case FormatType.Rational: { var rationalParts = property.Split(new[] { '/' }, 2); if (rationalParts.Length == 2) { try { var rational = new Rational((long)float.Parse(rationalParts[0]), (long)float.Parse(rationalParts[1])); directory.Set(tagType, rational); } catch (FormatException) { directory.AddError($"Unable to parse XMP property {propName} as a Rational."); } } else { directory.AddError("Error in rational format for tag " + tagType); } break; } case FormatType.Int: { try { directory.Set(tagType, int.Parse(property)); } catch (FormatException) { directory.AddError($"Unable to parse XMP property {propName} as an int."); } break; } case FormatType.Double: { try { directory.Set(tagType, double.Parse(property)); } catch (FormatException) { directory.AddError($"Unable to parse XMP property {propName} as an double."); } break; } case FormatType.String: { directory.Set(tagType, property); break; } case FormatType.StringArray: { //XMP iterators are 1-based var count = meta.CountArrayItems(schemaNs, propName); var array = new string[count]; for (var i = 1; i <= count; ++i) { array[i - 1] = meta.GetArrayItem(schemaNs, propName, i).Value; } directory.Set(tagType, array); break; } default: { directory.AddError($"Unknown format code {formatCode} for tag {tagType}"); break; } } }