1 // ==========================================================
2 // FreeImage 3 .NET wrapper
3 // Original FreeImage 3 functions and .NET compatible derived functions
4 //
5 // Design and implementation by
6 // - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
7 // - Carsten Klein (cklein05@users.sourceforge.net)
8 //
9 // Contributors:
10 // - David Boland (davidboland@vodafone.ie)
11 //
12 // Main reference : MSDN Knowlede Base
13 //
14 // This file is part of FreeImage 3
15 //
16 // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
17 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
18 // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
19 // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
20 // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
21 // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
22 // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
23 // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
24 // THIS DISCLAIMER.
25 //
26 // Use at your own risk!
27 // ==========================================================
28 
29 // ==========================================================
30 // CVS
31 // $Revision: 1.8 $
32 // $Date: 2009/02/27 16:34:31 $
33 // $Id: MetadataModel.cs,v 1.8 2009/02/27 16:34:31 cklein05 Exp $
34 // ==========================================================
35 
36 using System;
37 using System.Collections;
38 using System.Collections.Generic;
39 using System.Text.RegularExpressions;
40 using System.Diagnostics;
41 
42 namespace FreeImageAPI.Metadata
43 {
44 	/// <summary>
45 	/// Base class that represents a collection of all tags contained in a metadata model.
46 	/// </summary>
47 	/// <remarks>
48 	/// The <b>MetedataModel</b> class is an abstract base class, which is inherited by
49 	/// several derived classes, one for each existing metadata model.
50 	/// </remarks>
51 	public abstract class MetadataModel : IEnumerable
52 	{
53 		/// <summary>
54 		/// Handle to the encapsulated FreeImage-bitmap.
55 		/// </summary>
56 		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
57 		protected readonly FIBITMAP dib;
58 
59 		/// <summary>
60 		/// Initializes a new instance of this class.
61 		/// </summary>
62 		/// <param name="dib">Handle to a FreeImage bitmap.</param>
63 		/// <exception cref="ArgumentNullException">
64 		/// <paramref name="dib"/> is null.</exception>
MetadataModel(FIBITMAP dib)65 		protected MetadataModel(FIBITMAP dib)
66 		{
67 			if (dib.IsNull)
68 			{
69 				throw new ArgumentNullException("dib");
70 			}
71 			this.dib = dib;
72 		}
73 
74 		/// <summary>
75 		/// Retrieves the datamodel that this instance represents.
76 		/// </summary>
77 		public abstract FREE_IMAGE_MDMODEL Model
78 		{
79 			get;
80 		}
81 
82 		/// <summary>
83 		/// Adds new tag to the bitmap or updates its value in case it already exists.
84 		/// <see cref="FreeImageAPI.Metadata.MetadataTag.Key"/> will be used as key.
85 		/// </summary>
86 		/// <param name="tag">The tag to add or update.</param>
87 		/// <returns>Returns true on success, false on failure.</returns>
88 		/// <exception cref="ArgumentNullException">
89 		/// <paramref name="tag"/> is null.</exception>
90 		/// <exception cref="ArgumentException">
91 		/// The tags model differs from this instances model.</exception>
AddTag(MetadataTag tag)92 		public bool AddTag(MetadataTag tag)
93 		{
94 			if (tag == null)
95 			{
96 				throw new ArgumentNullException("tag");
97 			}
98 			if (tag.Model != Model)
99 			{
100 				throw new ArgumentException("tag.Model");
101 			}
102 			return tag.AddToImage(dib);
103 		}
104 
105 		/// <summary>
106 		/// Adds a list of tags to the bitmap or updates their values in case they already exist.
107 		/// <see cref="FreeImageAPI.Metadata.MetadataTag.Key"/> will be used as key.
108 		/// </summary>
109 		/// <param name="list">A list of tags to add or update.</param>
110 		/// <returns>Returns the number of successfully added tags.</returns>
111 		/// <exception cref="ArgumentNullException">
112 		/// <paramref name="list"/> is null.</exception>
AddTag(IEnumerable<MetadataTag> list)113 		public int AddTag(IEnumerable<MetadataTag> list)
114 		{
115 			if (list == null)
116 			{
117 				throw new ArgumentNullException("list");
118 			}
119 			int count = 0;
120 			foreach (MetadataTag tag in list)
121 			{
122 				if (tag.Model == Model && tag.AddToImage(dib))
123 				{
124 					count++;
125 				}
126 			}
127 			return count;
128 		}
129 
130 		/// <summary>
131 		/// Removes the specified tag from the bitmap.
132 		/// </summary>
133 		/// <param name="key">The key of the tag.</param>
134 		/// <returns>Returns true on success, false on failure.</returns>
135 		/// <exception cref="ArgumentNullException">
136 		/// <paramref name="key"/> is null.</exception>
RemoveTag(string key)137 		public bool RemoveTag(string key)
138 		{
139 			if (key == null)
140 			{
141 				throw new ArgumentNullException("key");
142 			}
143 			return FreeImage.SetMetadata(Model, dib, key, FITAG.Zero);
144 		}
145 
146 		/// <summary>
147 		/// Destroys the metadata model
148 		/// which will remove all tags of this model from the bitmap.
149 		/// </summary>
150 		/// <returns>Returns true on success, false on failure.</returns>
DestoryModel()151 		public bool DestoryModel()
152 		{
153 			return FreeImage.SetMetadata(Model, dib, null, FITAG.Zero);
154 		}
155 
156 		/// <summary>
157 		/// Returns the specified metadata tag.
158 		/// </summary>
159 		/// <param name="key">The key of the tag.</param>
160 		/// <returns>The metadata tag.</returns>
161 		/// <exception cref="ArgumentNullException">
162 		/// <paramref name="key"/> is null.</exception>
GetTag(string key)163 		public MetadataTag GetTag(string key)
164 		{
165 			if (key == null)
166 			{
167 				throw new ArgumentNullException("key");
168 			}
169 			MetadataTag tag;
170 			return FreeImage.GetMetadata(Model, dib, key, out tag) ? tag : null;
171 		}
172 
173 		/// <summary>
174 		/// Returns whether the specified tag exists.
175 		/// </summary>
176 		/// <param name="key">The key of the tag.</param>
177 		/// <returns>True in case the tag exists, else false.</returns>
178 		/// <exception cref="ArgumentNullException">
179 		/// <paramref name="key"/> is null.</exception>
TagExists(string key)180 		public bool TagExists(string key)
181 		{
182 			if (key == null)
183 			{
184 				throw new ArgumentNullException("key");
185 			}
186 			MetadataTag tag;
187 			return FreeImage.GetMetadata(Model, dib, key, out tag);
188 		}
189 
190 		/// <summary>
191 		/// Returns a list of all metadata tags this instance represents.
192 		/// </summary>
193 		public List<MetadataTag> List
194 		{
195 			get
196 			{
197 				List<MetadataTag> list = new List<MetadataTag>((int)FreeImage.GetMetadataCount(Model, dib));
198 				MetadataTag tag;
199 				FIMETADATA mdHandle = FreeImage.FindFirstMetadata(Model, dib, out tag);
200 				if (!mdHandle.IsNull)
201 				{
202 					do
203 					{
204 						list.Add(tag);
205 					}
206 					while (FreeImage.FindNextMetadata(mdHandle, out tag));
207 					FreeImage.FindCloseMetadata(mdHandle);
208 				}
209 				return list;
210 			}
211 		}
212 
213 		/// <summary>
214 		/// Returns the tag at the given index.
215 		/// </summary>
216 		/// <param name="index">Index of the tag to return.</param>
217 		/// <returns>The tag at the given index.</returns>
GetTagFromIndex(int index)218 		protected MetadataTag GetTagFromIndex(int index)
219 		{
220 			if (index >= Count || index < 0)
221 			{
222 				throw new ArgumentOutOfRangeException("index");
223 			}
224 			MetadataTag tag;
225 			int count = 0;
226 			FIMETADATA mdHandle = FreeImage.FindFirstMetadata(Model, dib, out tag);
227 			if (!mdHandle.IsNull)
228 			{
229 				try
230 				{
231 					do
232 					{
233 						if (count++ == index)
234 						{
235 							break;
236 						}
237 					}
238 					while (FreeImage.FindNextMetadata(mdHandle, out tag));
239 				}
240 				finally
241 				{
242 					FreeImage.FindCloseMetadata(mdHandle);
243 				}
244 			}
245 			return tag;
246 		}
247 
248 		/// <summary>
249 		/// Returns the metadata tag at the given index. This operation is slow when accessing all tags.
250 		/// </summary>
251 		/// <param name="index">Index of the tag.</param>
252 		/// <returns>The metadata tag.</returns>
253 		/// <exception cref="ArgumentOutOfRangeException">
254 		/// <paramref name="index"/> is greater or equal <b>Count</b>
255 		/// or index is less than zero.</exception>
256 		public MetadataTag this[int index]
257 		{
258 			get
259 			{
260 				return GetTagFromIndex(index);
261 			}
262 		}
263 
264 		/// <summary>
265 		/// Retrieves an object that can iterate through the individual MetadataTags in this MetadataModel.
266 		/// </summary>
267 		/// <returns>An <see cref="IEnumerator"/> for the
268 		/// <see cref="FreeImageAPI.Metadata.MetadataModel"/>.</returns>
GetEnumerator()269 		public IEnumerator GetEnumerator()
270 		{
271 			return List.GetEnumerator();
272 		}
273 
274 		/// <summary>
275 		/// Returns the number of metadata tags this instance represents.
276 		/// </summary>
277 		public int Count
278 		{
279 			get { return (int)FreeImage.GetMetadataCount(Model, dib); }
280 		}
281 
282 		/// <summary>
283 		/// Returns whether this model exists in the bitmaps metadata structure.
284 		/// </summary>
285 		public bool Exists
286 		{
287 			get
288 			{
289 				return Count > 0;
290 			}
291 		}
292 
293 		/// <summary>
294 		/// Searches for a pattern in each metadata tag and returns the result as a list.
295 		/// </summary>
296 		/// <param name="searchPattern">The regular expression to use for the search.</param>
297 		/// <param name="flags">A bitfield that controls which fields should be searched in.</param>
298 		/// <returns>A list containing all found metadata tags.</returns>
299 		/// <exception cref="ArgumentNullException">
300 		/// <typeparamref name="searchPattern"/> is null.</exception>
301 		/// <exception cref="ArgumentException">
302 		/// <typeparamref name="searchPattern"/> is empty.</exception>
RegexSearch(string searchPattern, MD_SEARCH_FLAGS flags)303 		public List<MetadataTag> RegexSearch(string searchPattern, MD_SEARCH_FLAGS flags)
304 		{
305 			if (searchPattern == null)
306 			{
307 				throw new ArgumentNullException("searchString");
308 			}
309 			if (searchPattern.Length == 0)
310 			{
311 				throw new ArgumentException("searchString is empty");
312 			}
313 			List<MetadataTag> result = new List<MetadataTag>(Count);
314 			Regex regex = new Regex(searchPattern);
315 			List<MetadataTag> list = List;
316 			foreach (MetadataTag tag in list)
317 			{
318 				if (((flags & MD_SEARCH_FLAGS.KEY) > 0) && regex.Match(tag.Key).Success)
319 				{
320 					result.Add(tag);
321 					continue;
322 				}
323 				if (((flags & MD_SEARCH_FLAGS.DESCRIPTION) > 0) && regex.Match(tag.Description).Success)
324 				{
325 					result.Add(tag);
326 					continue;
327 				}
328 				if (((flags & MD_SEARCH_FLAGS.TOSTRING) > 0) && regex.Match(tag.ToString()).Success)
329 				{
330 					result.Add(tag);
331 					continue;
332 				}
333 			}
334 			result.Capacity = result.Count;
335 			return result;
336 		}
337 
338 		/// <summary>
339 		/// Returns the value of the specified tag.
340 		/// </summary>
341 		/// <typeparam name="T">Type of the tag's data.</typeparam>
342 		/// <param name="key">The key of the tag.</param>
343 		/// <returns>The value of the specified tag.</returns>
344 		protected T? GetTagValue<T>(string key) where T : struct
345 		{
346 			if (string.IsNullOrEmpty(key))
347 			{
348 				throw new ArgumentNullException("key");
349 			}
350 			MetadataTag tag = GetTag(key);
351 			if (tag != null)
352 			{
353 				T[] value = tag.Value as T[];
354 				if ((value != null) && (value.Length != 0))
355 				{
356 					return value[0];
357 				}
358 			}
359 			return null;
360 		}
361 
362 		/// <summary>
363 		/// Returns an array containing the data of the specified tag.
364 		/// </summary>
365 		/// <typeparam name="T">The type of the tag's data.</typeparam>
366 		/// <param name="key">The key of the tag.</param>
367 		/// <returns>An array containing the data of the specified tag.</returns>
368 		protected T[] GetTagArray<T>(string key) where T : struct
369 		{
370 			if (string.IsNullOrEmpty(key))
371 			{
372 				throw new ArgumentNullException("key");
373 			}
374 			MetadataTag tag = GetTag(key);
375 			return (tag == null) ? null : tag.Value as T[];
376 		}
377 
378 		/// <summary>
379 		/// Returns the string contained by the specified tag.
380 		/// </summary>
381 		/// <param name="key">The key of the tag.</param>
382 		/// <returns>The string contained by the specified tag.</returns>
GetTagText(string key)383 		protected string GetTagText(string key)
384 		{
385 			if (string.IsNullOrEmpty(key))
386 			{
387 				throw new ArgumentNullException("key");
388 			}
389 			MetadataTag tag = GetTag(key);
390 			return (tag == null) ? null : tag.Value as string;
391 		}
392 
393 		/// <summary>
394 		/// Returns an array containg the data of the specified tag
395 		/// as unsigned 32bit integer.
396 		/// </summary>
397 		/// <param name="key">The key of the tag.</param>
398 		/// <returns>An array containg the data of the specified tag
399 		/// as unsigned 32bit integer.</returns>
GetUInt32Array(string key)400 		protected uint[] GetUInt32Array(string key)
401 		{
402 			if (string.IsNullOrEmpty(key))
403 			{
404 				throw new ArgumentNullException("key");
405 			}
406 			uint[] result = null;
407 			MetadataTag tag = GetTag(key);
408 			if (tag != null)
409 			{
410 				object value = tag.Value;
411 				if (value != null)
412 				{
413 					if (value is ushort[])
414 					{
415 						ushort[] array = (ushort[])value;
416 						result = new uint[array.Length];
417 						for (int i = 0, j = array.Length; i < j; i++)
418 						{
419 							result[i] = (uint)array[i];
420 						}
421 					}
422 					else if (value is uint[])
423 					{
424 						result = (uint[])value;
425 					}
426 				}
427 			}
428 			return result;
429 		}
430 
431 		/// <summary>
432 		/// Returns the value of the tag as unsigned 32bit integer.
433 		/// </summary>
434 		/// <param name="key">The key of the tag.</param>
435 		/// <returns>The value of the tag as unsigned 32bit integer.</returns>
GetUInt32Value(string key)436 		protected uint? GetUInt32Value(string key)
437 		{
438 			uint[] value = GetUInt32Array(key);
439 			return value == null ? default(uint?) : value[0];
440 		}
441 
442 		/// <summary>
443 		/// Sets the value of the specified tag.
444 		/// </summary>
445 		/// <typeparam name="T">The type of the tag's data.</typeparam>
446 		/// <param name="key">The key of the tag.</param>
447 		/// <param name="value">The new value of the specified tag or null.</param>
448 		protected void SetTagValue<T>(string key, T? value) where T : struct
449 		{
SetTagValueFreeImageAPI.Metadata.MetadataModel.__anon3450 			SetTagValue(key, value.HasValue ? new T[] { value.Value } : null);
451 		}
452 
453 		/// <summary>
454 		/// Sets the value of the specified tag.
455 		/// </summary>
456 		/// <param name="key">The key of the tag.</param>
457 		/// <param name="value">The new value of the specified tag or null.</param>
SetTagValue(string key, object value)458 		protected void SetTagValue(string key, object value)
459 		{
460 			if (string.IsNullOrEmpty(key))
461 			{
462 				throw new ArgumentNullException("key");
463 			}
464 			if (value == null)
465 			{
466 				RemoveTag(key);
467 			}
468 			else
469 			{
470 				MetadataTag tag = GetTag(key);
471 				if (tag == null)
472 				{
473 					tag = new MetadataTag(Model);
474 					tag.Key = key;
475 					tag.Value = value;
476 					AddTag(tag);
477 				}
478 				else
479 				{
480 					tag.Value = value;
481 				}
482 			}
483 		}
484 
485 		/// <summary>
486 		/// Sets the value of the specified tag as undefined.
487 		/// </summary>
488 		/// <param name="key">The key of the tag.</param>
489 		/// <param name="value">The new value of the specified tag or null.</param>
SetTagValueUndefined(string key, byte[] value)490 		protected void SetTagValueUndefined(string key, byte[] value)
491 		{
492 			if (string.IsNullOrEmpty(key))
493 			{
494 				throw new ArgumentNullException("key");
495 			}
496 			if (value == null)
497 			{
498 				RemoveTag(key);
499 			}
500 			else
501 			{
502 				MetadataTag tag = GetTag(key);
503 				if (tag == null)
504 				{
505 					tag = new MetadataTag(Model);
506 					tag.Key = key;
507 					tag.SetValue(value, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED);
508 					AddTag(tag);
509 				}
510 				else
511 				{
512 					tag.Value = value;
513 				}
514 			}
515 		}
516 
517 		/// <summary>
518 		/// Returns the equivalent <see cref="DirectionReference"/> for the
519 		/// specified <see cref="String"/>.
520 		/// </summary>
521 		/// <param name="s">The string containing the <see cref="DirectionReference"/>.</param>
522 		/// <returns>The equivalent <see cref="DirectionReference"/> for the
523 		/// specified <see cref="String"/>.</returns>
ToDirectionType(string s)524 		protected static DirectionReference? ToDirectionType(string s)
525 		{
526 			if (string.IsNullOrEmpty(s))
527 				return null;
528 			switch (s[0])
529 			{
530 				case 'T':
531 					return DirectionReference.TrueDirection;
532 				case 'M':
533 					return DirectionReference.MagneticDirection;
534 				default:
535 					return DirectionReference.Undefined;
536 			}
537 		}
538 
539 		/// <summary>
540 		/// Returns the equivalent <see cref="String"/> for the
541 		/// specified <see cref="DirectionReference"/>.
542 		/// </summary>
543 		/// <param name="type">The <see cref="DirectionReference"/> to convert.</param>
544 		/// <returns>The equivalent <see cref="String"/> for the
545 		/// specified <see cref="DirectionReference"/>.</returns>
546 		protected static string ToString(DirectionReference? type)
547 		{
548 			if (type.HasValue)
549 			{
550 				switch (type.Value)
551 				{
552 					case DirectionReference.TrueDirection:
553 						return "T";
554 					case DirectionReference.MagneticDirection:
555 						return "M";
556 					default:
557 						return "\0";
558 				}
559 			}
560 			return null;
561 		}
562 
563 		/// <summary>
564 		/// Returns the equivalent <see cref="VelocityUnit"/> for the
565 		/// specified <see cref="String"/>.
566 		/// </summary>
567 		/// <param name="s">The string containing the <see cref="VelocityUnit"/>.</param>
568 		/// <returns>The equivalent <see cref="VelocityUnit"/> for the
569 		/// specified <see cref="String"/>.</returns>
ToUnitType(string s)570 		protected static VelocityUnit? ToUnitType(string s)
571 		{
572 			if (string.IsNullOrEmpty(s))
573 				return null;
574 			switch (s[0])
575 			{
576 				case 'K':
577 					return VelocityUnit.Kilometers;
578 				case 'M':
579 					return VelocityUnit.Miles;
580 				case 'N':
581 					return VelocityUnit.Knots;
582 				default:
583 					return VelocityUnit.Undefinied;
584 			}
585 		}
586 
587 		/// <summary>
588 		/// Returns the equivalent <see cref="String"/> for the
589 		/// specified <see cref="VelocityUnit"/>.
590 		/// </summary>
591 		/// <param name="type">The <see cref="VelocityUnit"/> to convert.</param>
592 		/// <returns>The equivalent <see cref="String"/> for the
593 		/// specified <see cref="VelocityUnit"/>.</returns>
594 		protected static string ToString(VelocityUnit? type)
595 		{
596 			if (type.HasValue)
597 			{
598 				switch (type.Value)
599 				{
600 					case VelocityUnit.Kilometers:
601 						return "K";
602 					case VelocityUnit.Miles:
603 						return "M";
604 					case VelocityUnit.Knots:
605 						return "N";
606 					default:
607 						return "\0";
608 				}
609 			}
610 			return null;
611 		}
612 
613 		/// <summary>
614 		/// Returns the equivalent <see cref="LongitudeType"/> for the
615 		/// specified <see cref="String"/>.
616 		/// </summary>
617 		/// <param name="s">The string containing the <see cref="LongitudeType"/>.</param>
618 		/// <returns>The equivalent <see cref="LongitudeType"/> for the
619 		/// specified <see cref="String"/>.</returns>
ToLongitudeType(string s)620 		protected static LongitudeType? ToLongitudeType(string s)
621 		{
622 			if (string.IsNullOrEmpty(s))
623 				return null;
624 			switch (s[0])
625 			{
626 				case 'E':
627 					return LongitudeType.East;
628 				case 'W':
629 					return LongitudeType.West;
630 				default:
631 					return LongitudeType.Undefined;
632 			}
633 		}
634 
635 		/// <summary>
636 		/// Returns the equivalent <see cref="String"/> for the
637 		/// specified <see cref="LongitudeType"/>.
638 		/// </summary>
639 		/// <param name="type">The <see cref="LongitudeType"/> to convert.</param>
640 		/// <returns>The equivalent <see cref="String"/> for the
641 		/// specified <see cref="LongitudeType"/>.</returns>
642 		protected static string ToString(LongitudeType? type)
643 		{
644 			if (type.HasValue)
645 			{
646 				switch (type.Value)
647 				{
648 					case LongitudeType.East:
649 						return "E";
650 					case LongitudeType.West:
651 						return "W";
652 					default:
653 						return "\0";
654 				}
655 			}
656 			return null;
657 		}
658 
659 		/// <summary>
660 		/// Returns the equivalent <see cref="LatitudeType"/> for the
661 		/// specified <see cref="String"/>.
662 		/// </summary>
663 		/// <param name="s">The string containing the <see cref="LatitudeType"/>.</param>
664 		/// <returns>The equivalent <see cref="LatitudeType"/> for the
665 		/// specified <see cref="String"/>.</returns>
ToLatitudeType(string s)666 		protected static LatitudeType? ToLatitudeType(string s)
667 		{
668 			if (string.IsNullOrEmpty(s))
669 				return null;
670 			switch (s[0])
671 			{
672 				case 'N':
673 					return LatitudeType.North;
674 				case 'S':
675 					return LatitudeType.South;
676 				default:
677 					return LatitudeType.Undefined;
678 			}
679 		}
680 
681 		/// <summary>
682 		/// Returns the equivalent <see cref="String"/> for the
683 		/// specified <see cref="LatitudeType"/>.
684 		/// </summary>
685 		/// <param name="type">The <see cref="LatitudeType"/> to convert.</param>
686 		/// <returns>The equivalent <see cref="String"/> for the
687 		/// specified <see cref="LatitudeType"/>.</returns>
688 		protected static string ToString(LatitudeType? type)
689 		{
690 			if (type.HasValue)
691 			{
692 				switch (type.Value)
693 				{
694 					case LatitudeType.North:
695 						return "N";
696 					case LatitudeType.South:
697 						return "S";
698 					default:
699 						return "\0";
700 				}
701 			}
702 			return null;
703 		}
704 
705 		/// <summary>
706 		/// Returns the equivalent <see cref="InteroperabilityMode"/> for the
707 		/// specified <see cref="String"/>.
708 		/// </summary>
709 		/// <param name="s">The string containing the <see cref="InteroperabilityMode"/>.</param>
710 		/// <returns>The equivalent <see cref="InteroperabilityMode"/> for the
711 		/// specified <see cref="String"/>.</returns>
ToInteroperabilityType(string s)712 		protected static InteroperabilityMode? ToInteroperabilityType(string s)
713 		{
714 			if (string.IsNullOrEmpty(s))
715 				return null;
716 			if (s.StartsWith("R98"))
717 				return InteroperabilityMode.R98;
718 			if (s.StartsWith("THM"))
719 				return InteroperabilityMode.THM;
720 			return InteroperabilityMode.Undefined;
721 		}
722 
723 		/// <summary>
724 		/// Returns the equivalent <see cref="String"/> for the
725 		/// specified <see cref="InteroperabilityMode"/>.
726 		/// </summary>
727 		/// <param name="type">The <see cref="InteroperabilityMode"/> to convert.</param>
728 		/// <returns>The equivalent <see cref="String"/> for the
729 		/// specified <see cref="InteroperabilityMode"/>.</returns>
730 		protected static string ToString(InteroperabilityMode? type)
731 		{
732 			if (type.HasValue)
733 			{
734 				switch (type.Value)
735 				{
736 					case InteroperabilityMode.R98:
737 						return "R98";
738 					case InteroperabilityMode.THM:
739 						return "THM";
740 					default:
741 						return "\0\0\0";
742 				}
743 			}
744 			return null;
745 		}
746 
747 		/// <summary>
748 		/// Specified different unit types.
749 		/// </summary>
750 		public enum VelocityUnit
751 		{
752 			/// <summary>
753 			/// No or unknown type.
754 			/// </summary>
755 			Undefinied,
756 
757 			/// <summary>
758 			/// Kilometers per hour.
759 			/// </summary>
760 			Kilometers,
761 
762 			/// <summary>
763 			/// Miles per hour.
764 			/// </summary>
765 			Miles,
766 
767 			/// <summary>
768 			/// Knots.
769 			/// </summary>
770 			Knots,
771 		}
772 
773 		/// <summary>
774 		/// Specifies different direction types.
775 		/// </summary>
776 		public enum DirectionReference
777 		{
778 			/// <summary>
779 			/// No or unknown direction type.
780 			/// </summary>
781 			Undefined,
782 
783 			/// <summary>
784 			/// True direction.
785 			/// </summary>
786 			TrueDirection,
787 
788 			/// <summary>
789 			/// Magnatic direction.
790 			/// </summary>
791 			MagneticDirection,
792 		}
793 
794 		/// <summary>
795 		/// Specifies the type of a latitude value.
796 		/// </summary>
797 		public enum LatitudeType
798 		{
799 			/// <summary>
800 			/// No or unknown type.
801 			/// </summary>
802 			Undefined,
803 
804 			/// <summary>
805 			/// North.
806 			/// </summary>
807 			North,
808 
809 			/// <summary>
810 			/// South.
811 			/// </summary>
812 			South,
813 		}
814 
815 		/// <summary>
816 		/// Specifies the type of a longitude value.
817 		/// </summary>
818 		public enum LongitudeType
819 		{
820 			/// <summary>
821 			/// No or unknown type.
822 			/// </summary>
823 			Undefined,
824 
825 			/// <summary>
826 			/// East.
827 			/// </summary>
828 			East,
829 
830 			/// <summary>
831 			/// West.
832 			/// </summary>
833 			West,
834 		}
835 
836 		/// <summary>
837 		/// Specifies different altitude types.
838 		/// </summary>
839 		public enum AltitudeType
840 		{
841 			/// <summary>
842 			/// No or unknown type.
843 			/// </summary>
844 			Undefined,
845 
846 			/// <summary>
847 			/// East.
848 			/// </summary>
849 			AboveSeaLevel,
850 
851 			/// <summary>
852 			/// West.
853 			/// </summary>
854 			BelowSeaLevel,
855 		}
856 
857 		/// <summary>
858 		/// Specifies interoperability types.
859 		/// </summary>
860 		public enum InteroperabilityMode
861 		{
862 			/// <summary>
863 			/// No or unknown type.
864 			/// </summary>
865 			Undefined,
866 
867 			/// <summary>
868 			/// Indicates a file conforming to R98 file specification of Recommended
869 			/// Exif Interoperability Rules (ExifR98) or to DCF basic file stipulated
870 			/// by Design Rule for Camera File System.
871 			/// </summary>
872 			R98,
873 
874 			/// <summary>
875 			/// Indicates a file conforming to DCF thumbnail file stipulated by Design
876 			/// rule for Camera File System.
877 			/// </summary>
878 			THM,
879 		}
880 
881 		/// <summary>
882 		/// Specifies orientation of images.
883 		/// </summary>
884 		public enum ExifImageOrientation : ushort
885 		{
886 			/// <summary>
887 			/// Undefinied orientation.
888 			/// </summary>
889 			Undefined,
890 
891 			/// <summary>
892 			/// TopLeft.
893 			/// </summary>
894 			TopLeft = 1,
895 
896 			/// <summary>
897 			/// TopRight.
898 			/// </summary>
899 			TopRight,
900 
901 			/// <summary>
902 			/// BottomRight.
903 			/// </summary>
904 			BottomRight,
905 
906 			/// <summary>
907 			/// BottomLeft.
908 			/// </summary>
909 			BottomLeft,
910 
911 			/// <summary>
912 			/// LeftTop.
913 			/// </summary>
914 			LeftTop,
915 
916 			/// <summary>
917 			/// RightTop.
918 			/// </summary>
919 			RightTop,
920 
921 			/// <summary>
922 			/// RightBottom.
923 			/// </summary>
924 			RightBottom,
925 
926 			/// <summary>
927 			/// LeftBottom.
928 			/// </summary>
929 			LeftBottom,
930 		}
931 
932 		/// <summary>
933 		/// Converts the model of the MetadataModel object to its equivalent string representation.
934 		/// </summary>
935 		/// <returns>The string representation of the value of this instance.</returns>
ToString()936 		public override string ToString()
937 		{
938 			return Model.ToString();
939 		}
940 	}
941 }