XMP stands for eXtensible Metadata Platform. This is a specific type of XML that was first introduced by Adobe Systems. XMP defines a metadata model that can be used with any defined set of metadata items. It also defines some schemas for basic properties for recording the history of image modifications. XMP records metadata in a Resource Description Framework syntax (RDF) that is expressed in XML.
XMP can be used in the following graphics formats supported by Graphics Mill for .NET: JPEG and TIFF.
To read XMP metadata in Graphics Mill for .NET, you will need to read the Xmp property value of the opened reader. Currently, only few readers provide this property:
The Xmp property returns a string containing an XML code. This XML code is the XMP metadata. As you probably do not want to parse this XML on your own, pass it as a parameter to the constructor of the XmpData class. This class represents a tree-like structure of the metadata. This structure is a hierarchical collection of nodes.
The nodes can be of several different types:
Each node is a descendant of the XmpNode class.
The nodes contain tags. The tags belong to different schemas. A schema is a pre-defined set of some properties (tags); schemas are identified by their namespaces which follow the usage of XML namespaces. The use of namespaces helps to avoid conflicts between properties with the same name but different meanings. Namespaces in Graphics Mill for .NET are represented by the XmpNamespace class. Graphics Mill for .NET contains several namespaces that are defined in the XMP specification, but you may add your own ones.
Now, when you know how XMP data is organized, you can read it from a file. The following example demonstrates how to iterate through all properties in the XmpData collection using the Values property.
Dim reader As New Aurigma.GraphicsMill.Codecs.JpegReader("C:\IMG_0001.jpg") 'Check if XMP data are present in the file If reader.Xmp <> Nothing Then 'Get an XML code from the reader Dim xmp As New Aurigma.GraphicsMill.Codecs.XmpData(reader.Xmp) 'Go through all simple value nodes and print them along with their tags Dim node As Aurigma.GraphicsMill.Codecs.XmpNode For Each node In xmp.Values If node.NodeType = Aurigma.GraphicsMill.Codecs.XmpNodeType.SimpleProperty Then Console.WriteLine("{0}: {1}", node.Name, node.ToString()) End If Next node End If
Aurigma.GraphicsMill.Codecs.JpegReader reader = new Aurigma.GraphicsMill.Codecs.JpegReader(@"C:\IMG_0001.jpg"); //Check if XMP data are present in the file if (reader.Xmp != null) { //Get an XML code from the reader Aurigma.GraphicsMill.Codecs.XmpData xmp = new Aurigma.GraphicsMill.Codecs.XmpData(reader.Xmp); //Go through all simple value nodes and print them along with their tags foreach (Aurigma.GraphicsMill.Codecs.XmpNode node in xmp.Values) { if (node.NodeType == Aurigma.GraphicsMill.Codecs.XmpNodeType.SimpleProperty) Console.WriteLine("{0}: {1}", node.Name, node.ToString()); } }
However, you may not only iterate through all XMP properties but also get only specific ones that you need. The following example shows how to do it.
Dim reader As New Aurigma.GraphicsMill.Codecs.JpegReader("C:\IMG_0001.jpg") 'Check if XMP data are present in the file If reader.Xmp <> Nothing Then 'Get an XML code from the reader Dim xmp As New Aurigma.GraphicsMill.Codecs.XmpData(reader.Xmp) 'Print the value of the xmp:CreatorTool tag if it exists If xmp.Contains(Aurigma.GraphicsMill.Codecs.XmpTagNames.XmpCreatorTool) Then Console.WriteLine("This image was created using {0}", _ xmp.Item(Aurigma.GraphicsMill.Codecs.XmpTagNames.XmpCreatorTool)) End If End If
Aurigma.GraphicsMill.Codecs.JpegReader reader = new Aurigma.GraphicsMill.Codecs.JpegReader(@"C:\IMG_0001.jpg"); //Check if XMP data are present in the file if (reader.Xmp != null) { //Get an XML code from the reader Aurigma.GraphicsMill.Codecs.XmpData xmp = new Aurigma.GraphicsMill.Codecs.XmpData(reader.Xmp); //Print the value of the xmp:CreatorTool tag if it exists if (xmp.Contains(Aurigma.GraphicsMill.Codecs.XmpTagNames.XmpCreatorTool)) { Console.WriteLine("This image was created using {0}", xmp[Aurigma.GraphicsMill.Codecs.XmpTagNames.XmpCreatorTool]); } }
To write XMP metadata in Graphics Mill for .NET, you will need to modify the Xmp property value of the opened writer. Currently, only few writers provide this property:
The Xmp property of these writers has the same meaning as the Xmp property of the corresponding readers and is a string containing an XML code. You can construct this string yourself, but this approach is error-prone. A better way is to do it using the XmpData class.
The XmpData class provides the AddNode(XmpNode) method which adds any descendant of the XmpNode class to the current tree. You can also remove unwanted nodes using the Remove(Object) method. After you are done with the tree, call the Save() method which returns a string suitable for setting it as a value of the Xmp property.
The following example demonstrates how to add an XMP property and save it with the file.
Dim reader As New Aurigma.GraphicsMill.Codecs.JpegReader("C:\IMG_0001.jpg") Dim xmp As Aurigma.GraphicsMill.Codecs.XmpData 'Check if XMP data are present in the file and... If reader.Xmp <> Nothing Then '...get an XML code from the reader xmp = New Aurigma.GraphicsMill.Codecs.XmpData(reader.Xmp) Else '...or create an empty structure xmp = New Aurigma.GraphicsMill.Codecs.XmpData End If 'Check if the dc:Creator tag exists and remove it in this case If xmp.Contains(Aurigma.GraphicsMill.Codecs.XmpTagNames.DCCreator) Then xmp.Remove(Aurigma.GraphicsMill.Codecs.XmpTagNames.DCCreator) 'Otherwise, add it Else Dim node As New Aurigma.GraphicsMill.Codecs.XmpValueNode( _ Aurigma.GraphicsMill.Codecs.XmpNodeType.SimpleProperty, _ "John Doe", Aurigma.GraphicsMill.Codecs.XmpTagNames.DCCreator) xmp.AddNode(node) End If 'Copy the bitmap of the original file Dim bitmap As New Aurigma.GraphicsMill.Bitmap Dim frame As Aurigma.GraphicsMill.Codecs.IFrame = reader.LoadFrame(0) frame.GetBitmap(bitmap) frame.Dispose() Dim writer As New Aurigma.GraphicsMill.Codecs.JpegWriter("C:\IMG_0002.jpg") 'Save modified metadata with the file writer.Xmp = xmp.Save() frame = New Aurigma.GraphicsMill.Codecs.JpegFrame(bitmap, 70, False) writer.AddFrame(frame)
Aurigma.GraphicsMill.Codecs.JpegReader reader = new Aurigma.GraphicsMill.Codecs.JpegReader(@"C:\IMG_0001.jpg"); Aurigma.GraphicsMill.Codecs.XmpData xmp = null; //Check if XMP data are present in the file and... if (reader.Xmp != null) { //...get an XML code from the reader xmp = new Aurigma.GraphicsMill.Codecs.XmpData(reader.Xmp); } else { //...or create an empty structure xmp = new Aurigma.GraphicsMill.Codecs.XmpData(); } //Check if the dc:Creator tag exists and remove it in this case if (xmp.Contains(Aurigma.GraphicsMill.Codecs.XmpTagNames.DCCreator)) { xmp.Remove(Aurigma.GraphicsMill.Codecs.XmpTagNames.DCCreator); } //Otherwise, add it else { Aurigma.GraphicsMill.Codecs.XmpValueNode node = new Aurigma.GraphicsMill.Codecs.XmpValueNode( Aurigma.GraphicsMill.Codecs.XmpNodeType.SimpleProperty, "John Doe", Aurigma.GraphicsMill.Codecs.XmpTagNames.DCCreator); xmp.AddNode(node); } //Copy the bitmap of the original file Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap(); Aurigma.GraphicsMill.Codecs.IFrame frame = reader.LoadFrame(0); frame.GetBitmap(bitmap); frame.Dispose(); Aurigma.GraphicsMill.Codecs.JpegWriter writer = new Aurigma.GraphicsMill.Codecs.JpegWriter(@"C:\IMG_0002.jpg"); //Save modified metadata with the file writer.Xmp = xmp.Save(); frame = new Aurigma.GraphicsMill.Codecs.JpegFrame(bitmap, 70, false); writer.AddFrame(frame);