/// <summary> /// Performs the XMP data extraction, adding found values to the specified instance of /// <see cref="Com.Drew.Metadata.Metadata"/> /// . /// <p/> /// The extraction is done with Adobe's XMPCore library. /// </summary> public virtual void Extract(string xmpString, Com.Drew.Metadata.Metadata metadata) { XmpDirectory directory = metadata.GetOrCreateDirectory <XmpDirectory>(); try { XMPMeta xmpMeta = XMPMetaFactory.ParseFromString(xmpString); ProcessXmpTags(directory, xmpMeta); } catch (XMPException e) { directory.AddError("Error processing XMP data: " + e.Message); } }
/// <summary>Version specifically for dealing with XMP found in JPEG segments.</summary> /// <remarks> /// Version specifically for dealing with XMP found in JPEG segments. This form of XMP has a peculiar preamble, which /// must be removed before parsing the XML. /// </remarks> /// <param name="segmentBytes">The byte array from which the metadata should be extracted.</param> /// <param name="metadata"> /// The /// <see cref="Com.Drew.Metadata.Metadata"/> /// object into which extracted values should be merged. /// </param> /// <param name="segmentType"> /// The /// <see cref="Com.Drew.Imaging.Jpeg.JpegSegmentType"/> /// being read. /// </param> public virtual void Extract(sbyte[] segmentBytes, Com.Drew.Metadata.Metadata metadata, JpegSegmentType segmentType) { XmpDirectory directory = metadata.GetOrCreateDirectory <XmpDirectory>(); // XMP in a JPEG file has a 29 byte preamble which is not valid XML. int preambleLength = 29; // check for the header length if (segmentBytes.Length <= preambleLength + 1) { directory.AddError(Sharpen.Extensions.StringFormat("Xmp data segment must contain at least %d bytes", preambleLength + 1)); return; } ByteArrayReader reader = new ByteArrayReader(segmentBytes); string preamble = Sharpen.Runtime.GetStringForBytes(segmentBytes, 0, preambleLength); if (!"http://ns.adobe.com/xap/1.0/\x0".Equals(preamble)) { directory.AddError("XMP data segment doesn't begin with 'http://ns.adobe.com/xap/1.0/'"); return; } sbyte[] xmlBytes = new sbyte[segmentBytes.Length - preambleLength]; System.Array.Copy(segmentBytes, 29, xmlBytes, 0, xmlBytes.Length); Extract(xmlBytes, metadata); }
/// <summary> /// Performs the XMP data extraction, adding found values to the specified instance of /// <see cref="Com.Drew.Metadata.Metadata"/> /// . /// <p> /// The extraction is done with Adobe's XMPCore library. /// </summary> public virtual void Extract([NotNull] string xmpString, [NotNull] Com.Drew.Metadata.Metadata metadata) { XmpDirectory directory = new XmpDirectory(); try { XMPMeta xmpMeta = XMPMetaFactory.ParseFromString(xmpString); ProcessXmpTags(directory, xmpMeta); } catch (XMPException e) { directory.AddError("Error processing XMP data: " + e.Message); } if (!directory.IsEmpty()) { metadata.AddDirectory(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="Com.Adobe.Xmp.XMPException"/> private static void ProcessXmpTag([NotNull] XMPMeta meta, [NotNull] XmpDirectory directory, int tagType, int formatCode) { string schemaNS = XmpDirectory._tagSchemaMap.Get(tagType); string propName = XmpDirectory._tagPropNameMap.Get(tagType); string property = meta.GetPropertyString(schemaNS, propName); if (property == null) { return; } switch (formatCode) { case FmtRational: { string[] rationalParts = property.Split("/", 2); if (rationalParts.Length == 2) { try { Rational rational = new Rational((long)float.Parse(rationalParts[0]), (long)float.Parse(rationalParts[1])); directory.SetRational(tagType, rational); } catch (FormatException) { directory.AddError(Sharpen.Extensions.StringFormat("Unable to parse XMP property %s as a Rational.", propName)); } } else { directory.AddError("Error in rational format for tag " + tagType); } break; } case FmtInt: { try { directory.SetInt(tagType, (int)Sharpen.Extensions.ValueOf(property)); } catch (FormatException) { directory.AddError(Sharpen.Extensions.StringFormat("Unable to parse XMP property %s as an int.", propName)); } break; } case FmtDouble: { try { directory.SetDouble(tagType, (double)double.Parse(property)); } catch (FormatException) { directory.AddError(Sharpen.Extensions.StringFormat("Unable to parse XMP property %s as an double.", propName)); } break; } case FmtString: { directory.SetString(tagType, property); break; } case FmtStringArray: { //XMP iterators are 1-based int count = meta.CountArrayItems(schemaNS, propName); string[] array = new string[count]; for (int i = 1; i <= count; ++i) { array[i - 1] = meta.GetArrayItem(schemaNS, propName, i).GetValue(); } directory.SetStringArray(tagType, array); break; } default: { directory.AddError(Sharpen.Extensions.StringFormat("Unknown format code %d for tag %d", formatCode, tagType)); break; } } }
/// <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="Com.Adobe.Xmp.XMPException"/> private void ProcessXmpTag(XMPMeta meta, XmpDirectory directory, string schemaNS, string propName, int tagType, int formatCode) { string property = meta.GetPropertyString(schemaNS, propName); if (property == null) { return; } switch (formatCode) { case FmtRational: { string[] rationalParts = property.Split("/", 2); if (rationalParts.Length == 2) { try { Rational rational = new Rational((long)float.Parse(rationalParts[0]), (long)float.Parse(rationalParts[1])); directory.SetRational(tagType, rational); } catch (FormatException) { directory.AddError(Sharpen.Extensions.StringFormat("Unable to parse XMP property %s as a Rational.", propName)); } } else { directory.AddError("Error in rational format for tag " + tagType); } break; } case FmtInt: { try { directory.SetInt(tagType, Sharpen.Extensions.ValueOf(property)); } catch (FormatException) { directory.AddError(Sharpen.Extensions.StringFormat("Unable to parse XMP property %s as an int.", propName)); } break; } case FmtDouble: { try { directory.SetDouble(tagType, double.Parse(property)); } catch (FormatException) { directory.AddError(Sharpen.Extensions.StringFormat("Unable to parse XMP property %s as an double.", propName)); } break; } case FmtString: { directory.SetString(tagType, property); break; } default: { directory.AddError(Sharpen.Extensions.StringFormat("Unknown format code %d for tag %d", formatCode, tagType)); break; } } }
/// <summary> /// Performs the XMP data extraction, adding found values to the specified instance of /// <see cref="Com.Drew.Metadata.Metadata"/> /// . /// <p> /// The extraction is done with Adobe's XMPCore library. /// </summary> public virtual void Extract([NotNull] sbyte[] xmpBytes, [NotNull] Com.Drew.Metadata.Metadata metadata) { XmpDirectory directory = new XmpDirectory(); try { XMPMeta xmpMeta = XMPMetaFactory.ParseFromBuffer(xmpBytes); ProcessXmpTags(directory, xmpMeta); } catch (XMPException e) { directory.AddError("Error processing XMP data: " + e.Message); } if (!directory.IsEmpty()) { metadata.AddDirectory(directory); } }