Holds XMP (Extensible Metadata Platform) metadata.
Inheritance: TagLib.Image.ImageTag
        /// <summary>
        ///    Parses the XMP file identified by resource and replaces the XMP
        ///    tag of file by the parsed data.
        /// </summary>
        public static bool ParseXmpSidecar(this TagLib.Image.File file, TagLib.File.IFileAbstraction resource)
        {
            string xmp;

            try {
                using (var stream = resource.ReadStream) {
                    using (var reader = new StreamReader (stream)) {
                        xmp = reader.ReadToEnd ();
                    }
                }
            } catch (Exception e) {
                Log.DebugFormat ("Sidecar cannot be read for file {0}", file.Name);
                Log.DebugException (e);
                return false;
            }

            XmpTag tag = null;
            try {
                tag = new XmpTag (xmp, file);
            } catch (Exception e) {
                Log.DebugFormat ("Metadata of Sidecar cannot be parsed for file {0}", file.Name);
                Log.DebugException (e);
                return false;
            }

            var xmp_tag = file.GetTag (TagLib.TagTypes.XMP, true) as XmpTag;
            xmp_tag.ReplaceFrom (tag);
            return true;
        }
		private void ValidateSimpleType (XmpTag tag) {
			var tree = tag.NodeTree;

			Assert.IsTrue (tree != null);
			Assert.AreEqual (1, tree.Children.Count);
			Assert.AreEqual (XmpNodeType.Simple, tree.Children[0].Type);
			Assert.AreEqual (XmpTag.XAP_NS, tree.Children[0].Namespace);
			Assert.AreEqual ("CreateDate", tree.Children[0].Name);
			Assert.AreEqual ("2002-08-15T17:10:04Z", tree.Children[0].Value);
		}
 private void AddAllQualifiersTo(XmlNode xml)
 {
     if (qualifiers == null)
     {
         return;
     }
     foreach (var collection in qualifiers.Values)
     {
         foreach (XmpNode node in collection.Values)
         {
             XmlAttribute attr = XmpTag.CreateAttribute(xml.OwnerDocument, node.Name, node.Namespace);
             attr.Value = node.Value;
             xml.Attributes.Append(attr);
         }
     }
 }
        public static XmpTag Create
        (

            /*
             * string copyright, string title, string model, string creator,
             * string make, double? focalLength, uint? focalLengthIn35mmFilm,
             * string comment, string[] keywords, uint? rating, DateTime? dateTime,
             * string software, double? ExposureTime, double? FNumber, uint? ISOSpeedRatings
             */
        )
        {
            XmpTag xmpTag = new XmpTag();

            /*
             * xmpTag.SetLangAltNode(XmpTag.DC_NS, "rights", copyright);
             * xmpTag.SetLangAltNode(XmpTag.DC_NS, "title", title);
             * xmpTag.SetTextNode(XmpTag.TIFF_NS, "Model", model);
             * xmpTag.SetCollectionNode(XmpTag.DC_NS, "creator", new string[] { creator }, XmpNodeType.Seq);
             * xmpTag.SetTextNode(XmpTag.TIFF_NS, "Make", make);
             * xmpTag.SetRationalNode(XmpTag.EXIF_NS, "FocalLength", focalLength.HasValue ? (double)focalLength : 0);
             * xmpTag.SetTextNode(XmpTag.EXIF_NS, "FocalLengthIn35mmFilm", focalLengthIn35mmFilm.HasValue ? focalLengthIn35mmFilm.Value.ToString() : String.Empty);
             * xmpTag.SetLangAltNode(XmpTag.DC_NS, "description", comment);
             * xmpTag.SetLangAltNode(XmpTag.EXIF_NS, "UserComment", comment);
             * xmpTag.SetCollectionNode(XmpTag.DC_NS, "subject", keywords, XmpNodeType.Bag);
             * xmpTag.SetTextNode(XmpTag.XAP_NS, "Rating", rating != null ? rating.ToString() : null);
             * xmpTag.SetTextNode(XmpTag.XAP_NS, "CreateDate", dateTime != null ? dateTime.ToString() : null);
             * xmpTag.SetTextNode (XmpTag.XAP_NS, "CreatorTool", software);
             * xmpTag.SetRationalNode(XmpTag.EXIF_NS, "ExposureTime", ExposureTime.HasValue ? (double)ExposureTime : 0);
             * xmpTag.SetRationalNode(XmpTag.EXIF_NS, "FNumber", FNumber.HasValue ? (double)FNumber : 0);
             * xmpTag.SetCollectionNode(XmpTag.EXIF_NS, "ISOSpeedRatings", new string[] { ISOSpeedRatings.ToString() }, XmpNodeType.Seq);
             */
            return(xmpTag);

            // TODO: Edit factory method of XmpTag
            // This method should be able to configure the object in all possible ways.
            // Add as many parameters as needed,
            // and assign their values to each field by using the API.
        }
Exemple #5
0
		/// <summary>
		/// Loads all metadata found in the XMP file.
		/// </summary>
		/// <example>LoadXmplFile("c:\dir\metadata.xmp")</example>
		public void LoadXmpFile(string path)
		{
			if(!File.Exists(path))
				throw new FileNotFoundException(path);

			var xmp = new XmpTag(File.ReadAllText(path, Encoding.UTF8), null);
			LoadProperties(xmp, this);
		}
Exemple #6
0
		/// <summary>
		/// Saves all the metadata that fits in XMP to a file.
		/// </summary>
		/// <example>SaveXmplFile("c:\dir\metadata.xmp")</example>
		public void SaveXmpFile(string path)
		{
			var tag = new XmpTag();
			SaveInImageTag(tag);
			File.WriteAllText(path, tag.Render(), Encoding.UTF8);
		}
Exemple #7
0
		static string GetRights(XmpTag xmp)
		{
			var rightsNode = xmp.FindNode("http://purl.org/dc/elements/1.1/", "rights");
			if (rightsNode == null)
				return null;
			foreach (var child in rightsNode.Children)
			{
				if (child.Namespace == "http://www.w3.org/1999/02/22-rdf-syntax-ns#" && child.Name == "li" &&
					HasLangQualifier(child, "en"))
				{
					return child.Value;
				}
			}
			return null;
		}
Exemple #8
0
		void SetRights(XmpTag xmp, string rights)
		{
			var rightsNode = xmp.FindNode("http://purl.org/dc/elements/1.1/", "rights");
			if (rightsNode == null)
			{
				if (string.IsNullOrEmpty(rights))
					return; // leave it missing.
				// No existing rights node, and we have some. We use (default lang) rights for copyright too, and there seems to be no way to
				// make the base node without setting that. So set it to something meaningless.
				// This will typically never happen, since our dialog requires a non-empty copyright.
				// I'm not entirely happy with it, but as far as I can discover the current version of taglib cannot
				// set the 'en' alternative of dc:rights without setting the  default alternative. In fact, I'm not sure the
				// result of doing so would technically be valid xmp; the standard calls for every langauge alternation
				// to have a default.
				xmp.SetLangAltNode("http://purl.org/dc/elements/1.1/", "rights", "Unknown");
				rightsNode = xmp.FindNode("http://purl.org/dc/elements/1.1/", "rights");
			}
			foreach (var child in rightsNode.Children)
			{
				if (child.Namespace == "http://www.w3.org/1999/02/22-rdf-syntax-ns#" && child.Name == "li" &&
					HasLangQualifier(child, "en"))
				{
					if (string.IsNullOrEmpty(rights))
					{
						rightsNode.RemoveChild(child);
						// enhance: possibly we should remove rightsNode, if it now has no children, and if taglib can.
						// However, we always require a copyright, so this will typically not happen.
					}
					else
						child.Value = rights;
					return;
				}
			}
			// Didn't find an existing rights:en node.
			if (string.IsNullOrEmpty(rights))
				return; // leave it missing.
			var childNode = new XmpNode(XmpTag.RDF_NS, "li", rights);
			childNode.AddQualifier(new XmpNode(XmpTag.XML_NS, "lang", "en"));

			rightsNode.AddChild(childNode);
		}
Exemple #9
0
        /// <summary>
        ///    Renders the current instance as child of the given node to the
        ///    given <see cref="XmlNode"/>
        /// </summary>
        /// <param name="parent">
        ///    A <see cref="XmlNode"/> to render the current instance as child of.
        /// </param>
        public void RenderInto(XmlNode parent)
        {
            if (IsRootNode)
            {
                AddAllChildrenTo(parent);
            }
            else if (IsReallySimpleType && parent.Attributes.GetNamedItem(XmpTag.PARSE_TYPE_URI, XmpTag.RDF_NS) == null)
            {
                // Simple values can be added as attributes of the parent node. Not allowed when the parent has an rdf:parseType.
                XmlAttribute attr = XmpTag.CreateAttribute(parent.OwnerDocument, Name, Namespace);
                attr.Value = Value;
                parent.Attributes.Append(attr);
            }
            else if (Type == XmpNodeType.Simple || Type == XmpNodeType.Struct)
            {
                var node = XmpTag.CreateNode(parent.OwnerDocument, Name, Namespace);
                node.InnerText = Value;

                if (Type == XmpNodeType.Struct)
                {
                    // Structured types are always handled as a parseType=Resource node. This way, IsReallySimpleType will
                    // not match for child nodes, which makes sure they are added as extra nodes to this node. Does the
                    // trick well, unit tests that prove this are in XmpSpecTest.
                    XmlAttribute attr = XmpTag.CreateAttribute(parent.OwnerDocument, XmpTag.PARSE_TYPE_URI, XmpTag.RDF_NS);
                    attr.Value = "Resource";
                    node.Attributes.Append(attr);
                }

                AddAllQualifiersTo(node);
                AddAllChildrenTo(node);
                parent.AppendChild(node);
            }
            else if (Type == XmpNodeType.Bag)
            {
                var node = XmpTag.CreateNode(parent.OwnerDocument, Name, Namespace);
                if (QualifierCount > 0)
                {
                    throw new NotImplementedException();
                }
                var bag = XmpTag.CreateNode(parent.OwnerDocument, XmpTag.BAG_URI, XmpTag.RDF_NS);
                foreach (var child in Children)
                {
                    child.RenderInto(bag);
                }
                node.AppendChild(bag);
                parent.AppendChild(node);
            }
            else if (Type == XmpNodeType.Alt)
            {
                var node = XmpTag.CreateNode(parent.OwnerDocument, Name, Namespace);
                if (QualifierCount > 0)
                {
                    throw new NotImplementedException();
                }
                var bag = XmpTag.CreateNode(parent.OwnerDocument, XmpTag.ALT_URI, XmpTag.RDF_NS);
                foreach (var child in Children)
                {
                    child.RenderInto(bag);
                }
                node.AppendChild(bag);
                parent.AppendChild(node);
            }
            else if (Type == XmpNodeType.Seq)
            {
                var node = XmpTag.CreateNode(parent.OwnerDocument, Name, Namespace);
                if (QualifierCount > 0)
                {
                    throw new NotImplementedException();
                }
                var bag = XmpTag.CreateNode(parent.OwnerDocument, XmpTag.SEQ_URI, XmpTag.RDF_NS);
                foreach (var child in Children)
                {
                    child.RenderInto(bag);
                }
                node.AppendChild(bag);
                parent.AppendChild(node);
            }
            else
            {
                // Probably some combination of things we don't fully cover yet.
                Dump();
                throw new NotImplementedException();
            }
        }
Exemple #10
0
        private void TestRender(XmpTag tag, XmpValidator validator)
        {
            string xmp = tag.Render ();

            var parsed_tag = new XmpTag (xmp, null);
            validator (parsed_tag);
        }
Exemple #11
0
 private XmpTag TestParse(string metadata, XmpValidator validator)
 {
     var tag = new XmpTag (metadata, null);
     validator (tag);
     return tag;
 }
Exemple #12
0
 public void RenderInto(XmlNode parent)
 {
     if (IsRootNode)
     {
         AddAllChildrenTo(parent);
     }
     else if (IsReallySimpleType && parent.Attributes.GetNamedItem(XmpTag.PARSE_TYPE_URI, XmpTag.RDF_NS) == null)
     {
         XmlAttribute attr = XmpTag.CreateAttribute(parent.OwnerDocument, Name, Namespace);
         attr.Value = Value;
         parent.Attributes.Append(attr);
     }
     else if (Type == XmpNodeType.Simple || Type == XmpNodeType.Struct)
     {
         var node = XmpTag.CreateNode(parent.OwnerDocument, Name, Namespace);
         node.InnerText = Value;
         if (Type == XmpNodeType.Struct)
         {
             XmlAttribute attr = XmpTag.CreateAttribute(parent.OwnerDocument, XmpTag.PARSE_TYPE_URI, XmpTag.RDF_NS);
             attr.Value = "Resource";
             node.Attributes.Append(attr);
         }
         AddAllQualifiersTo(node);
         AddAllChildrenTo(node);
         parent.AppendChild(node);
     }
     else if (Type == XmpNodeType.Bag)
     {
         var node = XmpTag.CreateNode(parent.OwnerDocument, Name, Namespace);
         if (QualifierCount > 0)
         {
             throw new NotImplementedException();
         }
         var bag = XmpTag.CreateNode(parent.OwnerDocument, XmpTag.BAG_URI, XmpTag.RDF_NS);
         foreach (var child in Children)
         {
             child.RenderInto(bag);
         }
         node.AppendChild(bag);
         parent.AppendChild(node);
     }
     else if (Type == XmpNodeType.Alt)
     {
         var node = XmpTag.CreateNode(parent.OwnerDocument, Name, Namespace);
         if (QualifierCount > 0)
         {
             throw new NotImplementedException();
         }
         var bag = XmpTag.CreateNode(parent.OwnerDocument, XmpTag.ALT_URI, XmpTag.RDF_NS);
         foreach (var child in Children)
         {
             child.RenderInto(bag);
         }
         node.AppendChild(bag);
         parent.AppendChild(node);
     }
     else if (Type == XmpNodeType.Seq)
     {
         var node = XmpTag.CreateNode(parent.OwnerDocument, Name, Namespace);
         if (QualifierCount > 0)
         {
             throw new NotImplementedException();
         }
         var bag = XmpTag.CreateNode(parent.OwnerDocument, XmpTag.SEQ_URI, XmpTag.RDF_NS);
         foreach (var child in Children)
         {
             child.RenderInto(bag);
         }
         node.AppendChild(bag);
         parent.AppendChild(node);
     }
     else
     {
         Dump();
         throw new NotImplementedException();
     }
 }
        private void TestBagNode(XmpTag tag, string ns, string name, string[] values)
        {
            var node = tag.FindNode(ns, name);
            Assert.IsFalse(node == null);
            Assert.AreEqual(XmpNodeType.Bag, node.Type);
            Assert.AreEqual(values.Length, node.Children.Count);

            int i = 0;
            foreach (var childNode in node.Children)
            {
                Assert.AreEqual(values[i], childNode.Value);
                Assert.AreEqual(0, childNode.Children.Count);
                i++;
            }
        }
Exemple #14
0
 public NodeIndexVisitor(XmpTag tag)
 {
     this.tag = tag;
 }
Exemple #15
0
 public void ReplaceFrom(XmpTag tag)
 {
     NodeTree = tag.NodeTree;
     nodes    = new Dictionary <string, Dictionary <string, XmpNode> >();
     AcceptVisitors();
 }
Exemple #16
0
			public NodeIndexVisitor (XmpTag tag) {
				this.tag = tag;
			}
Exemple #17
0
		/// <summary>
		///	   Replace the current tag with the given one.
		///	</summary>
		/// <param name="tag">
		///    The tag from which the data should be copied.
		/// </param>
		public void ReplaceFrom (XmpTag tag)
		{
			NodeTree = tag.NodeTree;
			nodes = new Dictionary<string, Dictionary<string, XmpNode>> ();
			AcceptVisitors ();
		}
Exemple #18
0
        private void ValidateStructuredType(XmpTag tag)
        {
            var tree = tag.NodeTree;

            var PG_NS = "http://ns.adobe.com/xap/1.0/t/pg/";
            var DIM_NS = "http://ns.adobe.com/xap/1.0/sType/Dimensions#";

            Assert.IsTrue (tree != null);
            Assert.AreEqual (1, tree.Children.Count);

            var node = tree.Children[0];
            Assert.AreEqual (XmpNodeType.Struct, node.Type);
            Assert.AreEqual (PG_NS, node.Namespace);
            Assert.AreEqual ("MaxPageSize", node.Name);
            Assert.AreEqual (3, node.Children.Count);

            Assert.AreEqual (DIM_NS, node.Children[0].Namespace);
            Assert.AreEqual ("w", node.Children[0].Name);
            Assert.AreEqual ("4", node.Children[0].Value);
            Assert.AreEqual (0, node.Children[0].Children.Count);

            Assert.AreEqual (DIM_NS, node.Children[1].Namespace);
            Assert.AreEqual ("h", node.Children[1].Name);
            Assert.AreEqual ("3", node.Children[1].Value);
            Assert.AreEqual (0, node.Children[1].Children.Count);

            Assert.AreEqual (DIM_NS, node.Children[2].Namespace);
            Assert.AreEqual ("unit", node.Children[2].Name);
            Assert.AreEqual ("inch", node.Children[2].Value);
            Assert.AreEqual (0, node.Children[2].Children.Count);
        }
Exemple #19
0
		/// <summary>
		///    Gets a tag of a specified type from the current instance,
		///    optionally creating a new tag if possible.
		/// </summary>
		/// <param name="type">
		///    A <see cref="TagLib.TagTypes" /> value indicating the
		///    type of tag to read.
		/// </param>
		/// <param name="create">
		///    A <see cref="bool" /> value specifying whether or not to
		///    try and create the tag if one is not found.
		/// </param>
		/// <returns>
		///    A <see cref="Tag" /> object containing the tag that was
		///    found in or added to the current instance. If no
		///    matching tag was found and none was created, <see
		///    langword="null" /> is returned.
		/// </returns>
		public override TagLib.Tag GetTag (TagLib.TagTypes type,
		                                   bool create)
		{
			foreach (Tag tag in ImageTag.AllTags) {
				if ((tag.TagTypes & type) == type)
					return tag;
			}

			if (!create || (type & ImageTag.AllowedTypes) == 0)
				return null;

			ImageTag new_tag = null;
			switch (type) {
			case TagTypes.JpegComment:
				new_tag = new JpegCommentTag ();
				break;

			case TagTypes.GifComment:
				new_tag = new GifCommentTag ();
				break;

			case TagTypes.Png:
				new_tag = new PngTag ();
				break;

			case TagTypes.TiffIFD:
				new_tag = new IFDTag ();
				break;

			case TagTypes.XMP:
				new_tag = new XmpTag ();
				break;
			}

			if (new_tag != null) {
				ImageTag.AddTag (new_tag);
				return new_tag;
			}

			throw new NotImplementedException (String.Format ("Adding tag of type {0} not supported!", type));
		}
Exemple #20
0
		/// <summary>
		/// Update the value of the specified node, or create it.
		/// Seems SetTextNode should work whether or not is already exists, but in some cases it doesn't.
		/// </summary>
		/// <param name="tag"></param>
		/// <param name="ns"></param>
		/// <param name="name"></param>
		/// <param name="val"></param>
		void AddOrModify(XmpTag tag, string ns, string name, string val)
		{
			var node = tag.FindNode(ns, name);
			if (node != null)
				node.Value = val;
			else
				tag.SetTextNode(ns, name, val);
		}