// ========================================================== // FreeImage 3 .NET wrapper // Original FreeImage 3 functions and .NET compatible derived functions // // Design and implementation by // - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net) // - Carsten Klein (cklein05@users.sourceforge.net) // // Contributors: // - David Boland (davidboland@vodafone.ie) // // Main reference : MSDN Knowlede Base // // This file is part of FreeImage 3 // // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER // THIS DISCLAIMER. // // Use at your own risk! // ========================================================== // ========================================================== // CVS // $Revision: 1.8 $ // $Date: 2009/02/27 16:34:31 $ // $Id: MetadataModel.cs,v 1.8 2009/02/27 16:34:31 cklein05 Exp $ // ========================================================== using System; using System.Collections; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Diagnostics; namespace FreeImageAPI.Metadata { /// /// Base class that represents a collection of all tags contained in a metadata model. /// /// /// The MetedataModel class is an abstract base class, which is inherited by /// several derived classes, one for each existing metadata model. /// public abstract class MetadataModel : IEnumerable { /// /// Handle to the encapsulated FreeImage-bitmap. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] protected readonly FIBITMAP dib; /// /// Initializes a new instance of this class. /// /// Handle to a FreeImage bitmap. /// /// is null. protected MetadataModel(FIBITMAP dib) { if (dib.IsNull) { throw new ArgumentNullException("dib"); } this.dib = dib; } /// /// Retrieves the datamodel that this instance represents. /// public abstract FREE_IMAGE_MDMODEL Model { get; } /// /// Adds new tag to the bitmap or updates its value in case it already exists. /// will be used as key. /// /// The tag to add or update. /// Returns true on success, false on failure. /// /// is null. /// /// The tags model differs from this instances model. public bool AddTag(MetadataTag tag) { if (tag == null) { throw new ArgumentNullException("tag"); } if (tag.Model != Model) { throw new ArgumentException("tag.Model"); } return tag.AddToImage(dib); } /// /// Adds a list of tags to the bitmap or updates their values in case they already exist. /// will be used as key. /// /// A list of tags to add or update. /// Returns the number of successfully added tags. /// /// is null. public int AddTag(IEnumerable list) { if (list == null) { throw new ArgumentNullException("list"); } int count = 0; foreach (MetadataTag tag in list) { if (tag.Model == Model && tag.AddToImage(dib)) { count++; } } return count; } /// /// Removes the specified tag from the bitmap. /// /// The key of the tag. /// Returns true on success, false on failure. /// /// is null. public bool RemoveTag(string key) { if (key == null) { throw new ArgumentNullException("key"); } return FreeImage.SetMetadata(Model, dib, key, FITAG.Zero); } /// /// Destroys the metadata model /// which will remove all tags of this model from the bitmap. /// /// Returns true on success, false on failure. public bool DestoryModel() { return FreeImage.SetMetadata(Model, dib, null, FITAG.Zero); } /// /// Returns the specified metadata tag. /// /// The key of the tag. /// The metadata tag. /// /// is null. public MetadataTag GetTag(string key) { if (key == null) { throw new ArgumentNullException("key"); } MetadataTag tag; return FreeImage.GetMetadata(Model, dib, key, out tag) ? tag : null; } /// /// Returns whether the specified tag exists. /// /// The key of the tag. /// True in case the tag exists, else false. /// /// is null. public bool TagExists(string key) { if (key == null) { throw new ArgumentNullException("key"); } MetadataTag tag; return FreeImage.GetMetadata(Model, dib, key, out tag); } /// /// Returns a list of all metadata tags this instance represents. /// public List List { get { List list = new List((int)FreeImage.GetMetadataCount(Model, dib)); MetadataTag tag; FIMETADATA mdHandle = FreeImage.FindFirstMetadata(Model, dib, out tag); if (!mdHandle.IsNull) { do { list.Add(tag); } while (FreeImage.FindNextMetadata(mdHandle, out tag)); FreeImage.FindCloseMetadata(mdHandle); } return list; } } /// /// Returns the tag at the given index. /// /// Index of the tag to return. /// The tag at the given index. protected MetadataTag GetTagFromIndex(int index) { if (index >= Count || index < 0) { throw new ArgumentOutOfRangeException("index"); } MetadataTag tag; int count = 0; FIMETADATA mdHandle = FreeImage.FindFirstMetadata(Model, dib, out tag); if (!mdHandle.IsNull) { try { do { if (count++ == index) { break; } } while (FreeImage.FindNextMetadata(mdHandle, out tag)); } finally { FreeImage.FindCloseMetadata(mdHandle); } } return tag; } /// /// Returns the metadata tag at the given index. This operation is slow when accessing all tags. /// /// Index of the tag. /// The metadata tag. /// /// is greater or equal Count /// or index is less than zero. public MetadataTag this[int index] { get { return GetTagFromIndex(index); } } /// /// Retrieves an object that can iterate through the individual MetadataTags in this MetadataModel. /// /// An for the /// . public IEnumerator GetEnumerator() { return List.GetEnumerator(); } /// /// Returns the number of metadata tags this instance represents. /// public int Count { get { return (int)FreeImage.GetMetadataCount(Model, dib); } } /// /// Returns whether this model exists in the bitmaps metadata structure. /// public bool Exists { get { return Count > 0; } } /// /// Searches for a pattern in each metadata tag and returns the result as a list. /// /// The regular expression to use for the search. /// A bitfield that controls which fields should be searched in. /// A list containing all found metadata tags. /// /// is null. /// /// is empty. public List RegexSearch(string searchPattern, MD_SEARCH_FLAGS flags) { if (searchPattern == null) { throw new ArgumentNullException("searchString"); } if (searchPattern.Length == 0) { throw new ArgumentException("searchString is empty"); } List result = new List(Count); Regex regex = new Regex(searchPattern); List list = List; foreach (MetadataTag tag in list) { if (((flags & MD_SEARCH_FLAGS.KEY) > 0) && regex.Match(tag.Key).Success) { result.Add(tag); continue; } if (((flags & MD_SEARCH_FLAGS.DESCRIPTION) > 0) && regex.Match(tag.Description).Success) { result.Add(tag); continue; } if (((flags & MD_SEARCH_FLAGS.TOSTRING) > 0) && regex.Match(tag.ToString()).Success) { result.Add(tag); continue; } } result.Capacity = result.Count; return result; } /// /// Returns the value of the specified tag. /// /// Type of the tag's data. /// The key of the tag. /// The value of the specified tag. protected T? GetTagValue(string key) where T : struct { if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } MetadataTag tag = GetTag(key); if (tag != null) { T[] value = tag.Value as T[]; if ((value != null) && (value.Length != 0)) { return value[0]; } } return null; } /// /// Returns an array containing the data of the specified tag. /// /// The type of the tag's data. /// The key of the tag. /// An array containing the data of the specified tag. protected T[] GetTagArray(string key) where T : struct { if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } MetadataTag tag = GetTag(key); return (tag == null) ? null : tag.Value as T[]; } /// /// Returns the string contained by the specified tag. /// /// The key of the tag. /// The string contained by the specified tag. protected string GetTagText(string key) { if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } MetadataTag tag = GetTag(key); return (tag == null) ? null : tag.Value as string; } /// /// Returns an array containg the data of the specified tag /// as unsigned 32bit integer. /// /// The key of the tag. /// An array containg the data of the specified tag /// as unsigned 32bit integer. protected uint[] GetUInt32Array(string key) { if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } uint[] result = null; MetadataTag tag = GetTag(key); if (tag != null) { object value = tag.Value; if (value != null) { if (value is ushort[]) { ushort[] array = (ushort[])value; result = new uint[array.Length]; for (int i = 0, j = array.Length; i < j; i++) { result[i] = (uint)array[i]; } } else if (value is uint[]) { result = (uint[])value; } } } return result; } /// /// Returns the value of the tag as unsigned 32bit integer. /// /// The key of the tag. /// The value of the tag as unsigned 32bit integer. protected uint? GetUInt32Value(string key) { uint[] value = GetUInt32Array(key); return value == null ? default(uint?) : value[0]; } /// /// Sets the value of the specified tag. /// /// The type of the tag's data. /// The key of the tag. /// The new value of the specified tag or null. protected void SetTagValue(string key, T? value) where T : struct { SetTagValue(key, value.HasValue ? new T[] { value.Value } : null); } /// /// Sets the value of the specified tag. /// /// The key of the tag. /// The new value of the specified tag or null. protected void SetTagValue(string key, object value) { if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } if (value == null) { RemoveTag(key); } else { MetadataTag tag = GetTag(key); if (tag == null) { tag = new MetadataTag(Model); tag.Key = key; tag.Value = value; AddTag(tag); } else { tag.Value = value; } } } /// /// Sets the value of the specified tag as undefined. /// /// The key of the tag. /// The new value of the specified tag or null. protected void SetTagValueUndefined(string key, byte[] value) { if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } if (value == null) { RemoveTag(key); } else { MetadataTag tag = GetTag(key); if (tag == null) { tag = new MetadataTag(Model); tag.Key = key; tag.SetValue(value, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED); AddTag(tag); } else { tag.Value = value; } } } /// /// Returns the equivalent for the /// specified . /// /// The string containing the . /// The equivalent for the /// specified . protected static DirectionReference? ToDirectionType(string s) { if (string.IsNullOrEmpty(s)) return null; switch (s[0]) { case 'T': return DirectionReference.TrueDirection; case 'M': return DirectionReference.MagneticDirection; default: return DirectionReference.Undefined; } } /// /// Returns the equivalent for the /// specified . /// /// The to convert. /// The equivalent for the /// specified . protected static string ToString(DirectionReference? type) { if (type.HasValue) { switch (type.Value) { case DirectionReference.TrueDirection: return "T"; case DirectionReference.MagneticDirection: return "M"; default: return "\0"; } } return null; } /// /// Returns the equivalent for the /// specified . /// /// The string containing the . /// The equivalent for the /// specified . protected static VelocityUnit? ToUnitType(string s) { if (string.IsNullOrEmpty(s)) return null; switch (s[0]) { case 'K': return VelocityUnit.Kilometers; case 'M': return VelocityUnit.Miles; case 'N': return VelocityUnit.Knots; default: return VelocityUnit.Undefinied; } } /// /// Returns the equivalent for the /// specified . /// /// The to convert. /// The equivalent for the /// specified . protected static string ToString(VelocityUnit? type) { if (type.HasValue) { switch (type.Value) { case VelocityUnit.Kilometers: return "K"; case VelocityUnit.Miles: return "M"; case VelocityUnit.Knots: return "N"; default: return "\0"; } } return null; } /// /// Returns the equivalent for the /// specified . /// /// The string containing the . /// The equivalent for the /// specified . protected static LongitudeType? ToLongitudeType(string s) { if (string.IsNullOrEmpty(s)) return null; switch (s[0]) { case 'E': return LongitudeType.East; case 'W': return LongitudeType.West; default: return LongitudeType.Undefined; } } /// /// Returns the equivalent for the /// specified . /// /// The to convert. /// The equivalent for the /// specified . protected static string ToString(LongitudeType? type) { if (type.HasValue) { switch (type.Value) { case LongitudeType.East: return "E"; case LongitudeType.West: return "W"; default: return "\0"; } } return null; } /// /// Returns the equivalent for the /// specified . /// /// The string containing the . /// The equivalent for the /// specified . protected static LatitudeType? ToLatitudeType(string s) { if (string.IsNullOrEmpty(s)) return null; switch (s[0]) { case 'N': return LatitudeType.North; case 'S': return LatitudeType.South; default: return LatitudeType.Undefined; } } /// /// Returns the equivalent for the /// specified . /// /// The to convert. /// The equivalent for the /// specified . protected static string ToString(LatitudeType? type) { if (type.HasValue) { switch (type.Value) { case LatitudeType.North: return "N"; case LatitudeType.South: return "S"; default: return "\0"; } } return null; } /// /// Returns the equivalent for the /// specified . /// /// The string containing the . /// The equivalent for the /// specified . protected static InteroperabilityMode? ToInteroperabilityType(string s) { if (string.IsNullOrEmpty(s)) return null; if (s.StartsWith("R98")) return InteroperabilityMode.R98; if (s.StartsWith("THM")) return InteroperabilityMode.THM; return InteroperabilityMode.Undefined; } /// /// Returns the equivalent for the /// specified . /// /// The to convert. /// The equivalent for the /// specified . protected static string ToString(InteroperabilityMode? type) { if (type.HasValue) { switch (type.Value) { case InteroperabilityMode.R98: return "R98"; case InteroperabilityMode.THM: return "THM"; default: return "\0\0\0"; } } return null; } /// /// Specified different unit types. /// public enum VelocityUnit { /// /// No or unknown type. /// Undefinied, /// /// Kilometers per hour. /// Kilometers, /// /// Miles per hour. /// Miles, /// /// Knots. /// Knots, } /// /// Specifies different direction types. /// public enum DirectionReference { /// /// No or unknown direction type. /// Undefined, /// /// True direction. /// TrueDirection, /// /// Magnatic direction. /// MagneticDirection, } /// /// Specifies the type of a latitude value. /// public enum LatitudeType { /// /// No or unknown type. /// Undefined, /// /// North. /// North, /// /// South. /// South, } /// /// Specifies the type of a longitude value. /// public enum LongitudeType { /// /// No or unknown type. /// Undefined, /// /// East. /// East, /// /// West. /// West, } /// /// Specifies different altitude types. /// public enum AltitudeType { /// /// No or unknown type. /// Undefined, /// /// East. /// AboveSeaLevel, /// /// West. /// BelowSeaLevel, } /// /// Specifies interoperability types. /// public enum InteroperabilityMode { /// /// No or unknown type. /// Undefined, /// /// Indicates a file conforming to R98 file specification of Recommended /// Exif Interoperability Rules (ExifR98) or to DCF basic file stipulated /// by Design Rule for Camera File System. /// R98, /// /// Indicates a file conforming to DCF thumbnail file stipulated by Design /// rule for Camera File System. /// THM, } /// /// Specifies orientation of images. /// public enum ExifImageOrientation : ushort { /// /// Undefinied orientation. /// Undefined, /// /// TopLeft. /// TopLeft = 1, /// /// TopRight. /// TopRight, /// /// BottomRight. /// BottomRight, /// /// BottomLeft. /// BottomLeft, /// /// LeftTop. /// LeftTop, /// /// RightTop. /// RightTop, /// /// RightBottom. /// RightBottom, /// /// LeftBottom. /// LeftBottom, } /// /// Converts the model of the MetadataModel object to its equivalent string representation. /// /// The string representation of the value of this instance. public override string ToString() { return Model.ToString(); } } }