// ==========================================================
// 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();
}
}
}