context: // ==========================================================
  // 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.12 $
  // $Date: 2011/12/22 14:54:22 $
  // $Id: FreeImageBitmap.cs,v 1.12 2011/12/22 14:54:22 drolon Exp $
  // ==========================================================
  
  using System;
  using System.Drawing;
  using System.Drawing.Imaging;
  using System.IO;
  using System.IO.Compression;
  using System.Runtime.InteropServices;
  using System.Runtime.Serialization;
  using System.Collections;
  using System.Collections.Generic;
  using FreeImageAPI.Metadata;
  using System.Diagnostics;
  
  namespace FreeImageAPI
  {
  	/// <summary>
  	/// Encapsulates a FreeImage-bitmap.
  	/// </summary>
  	[Serializable, Guid("64a4c935-b757-499c-ab8c-6110316a9e51")]
  	public class FreeImageBitmap : MarshalByRefObject, ICloneable, IDisposable, IEnumerable, ISerializable
  	{
  		#region Fields
  
  		/// <summary>
  		/// Indicates whether this instance is disposed.
  		/// </summary>
  		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  		private bool disposed;
  
  		/// <summary>
  		/// Tab object.
  		/// </summary>
  		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  		private object tag;
  
  		/// <summary>
  		/// Object used to syncronize lock methods.
  		/// </summary>
  		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  		private object lockObject = new object();
  
  		/// <summary>
  		/// Holds information used by SaveAdd() methods.
  		/// </summary>
  		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  		private SaveInformation saveInformation = new SaveInformation();
  
  		/// <summary>
  		/// The stream that this instance was loaded from or
  		/// null if it has been cloned or deserialized.
  		/// </summary>
  		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  		private Stream stream;
  
  		/// <summary>
  		/// True if the stream must be disposed with this
  		/// instance.
  		/// </summary>
  		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  		private bool disposeStream;
  
  		/// <summary>
  		/// The number of frames contained by a mutlipage bitmap.
  		/// Default value is 1 and only changed if needed.
  		/// </summary>
  		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  		private int frameCount = 1;
  
  		/// <summary>
  		/// The index of the loaded frame.
  		/// Default value is 0 and only changed if needed.
  		/// </summary>
  		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  		private int frameIndex = 0;
  
  		/// <summary>
  		/// Format of the sourceimage.
  		/// </summary>
  		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  		private FREE_IMAGE_FORMAT originalFormat = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
  
  		/// <summary>
  		/// Handle to the encapsulated FreeImage-bitmap.
  		/// </summary>
  		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  		private FIBITMAP dib;
  
  		private const string ErrorLoadingBitmap = "Unable to load bitmap.";
  		private const string ErrorLoadingFrame = "Unable to load frame.";
  		private const string ErrorCreatingBitmap = "Unable to create bitmap.";
  		private const string ErrorUnloadBitmap = "Unable to unload bitmap.";
  
  		#endregion
  
  		#region Constructors and Destructor
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class.
  		/// </summary>
  		protected FreeImageBitmap()
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class.
  		/// For internal use only.
  		/// </summary>
  		/// <exception cref="Exception">The operation failed.</exception>
  		internal protected FreeImageBitmap(FIBITMAP dib)
  		{
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorLoadingBitmap);
  			}
  			this.dib = dib;
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified image.
  		/// </summary>
  		/// <param name="original">The original to clone from.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
  		public FreeImageBitmap(FreeImageBitmap original)
  		{
  			if (original == null)
  			{
  				throw new ArgumentNullException("original");
  			}
  			original.EnsureNotDisposed();
  			dib = FreeImage.Clone(original.dib);
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorLoadingBitmap);
  			}
  			originalFormat = original.originalFormat;
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified image with the specified size.
  		/// </summary>
  		/// <param name="original">The original to clone from.</param>
  		/// <param name="newSize">The Size structure that represent the
  		/// size of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// Width or height of <paramref name="newSize"/> are less or equal zero.
  		/// </exception>
  		public FreeImageBitmap(FreeImageBitmap original, Size newSize)
  			: this(original, newSize.Width, newSize.Height)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified image with the specified size.
  		/// </summary>
  		/// <param name="original">The original to clone from.</param>
  		/// <param name="width">Width of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="height">Height of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
  		public FreeImageBitmap(FreeImageBitmap original, int width, int height)
  		{
  			if (original == null)
  			{
  				throw new ArgumentNullException("original");
  			}
  			if (width <= 0)
  			{
  				throw new ArgumentOutOfRangeException("width");
  			}
  			if (height <= 0)
  			{
  				throw new ArgumentOutOfRangeException("height");
  			}
  			original.EnsureNotDisposed();
  			dib = FreeImage.Rescale(original.dib, width, height, FREE_IMAGE_FILTER.FILTER_BICUBIC);
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorLoadingBitmap);
  			}
  			originalFormat = original.originalFormat;
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified image.
  		/// </summary>
  		/// <param name="original">The original to clone from.</param>
  		/// <remarks>
  		/// Although this constructor supports creating images in both formats
  		/// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
  		/// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
  		/// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
  		/// images respectively. Currently, there is no  support for automatic premultiplying images in
  		/// <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		/// <exception cref="Exception">The operation failed.</exception>
  		public FreeImageBitmap(Image original)
  			: this(original as Bitmap)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified image with the specified size.
  		/// </summary>
  		/// <param name="original">The original to clone from.</param>
  		/// <param name="newSize">The Size structure that represent the
  		/// size of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <remarks>
  		/// Although this constructor supports creating images in both formats
  		/// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
  		/// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
  		/// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
  		/// images respectively. Currently, there is no  support for automatic premultiplying images in
  		/// <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// Width or height of <paramref name="newSize" /> are less or equal zero.
  		/// </exception>
  		public FreeImageBitmap(Image original, Size newSize)
  			: this(original as Bitmap, newSize.Width, newSize.Height)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified image with the specified size.
  		/// </summary>
  		/// <param name="original">The original to clone from.</param>
  		/// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <remarks>
  		/// Although this constructor supports creating images in both formats
  		/// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
  		/// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
  		/// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
  		/// images respectively. Currently, there is no  support for automatic premultiplying images in
  		/// <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
  		public FreeImageBitmap(Image original, int width, int height)
  			: this(original as Bitmap, width, height)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified image.
  		/// </summary>
  		/// <param name="original">The original to clone from.</param>
  		/// <remarks>
  		/// Although this constructor supports creating images in both formats
  		/// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
  		/// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
  		/// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
  		/// images respectively. Currently, there is no  support for automatic premultiplying images in
  		/// <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		/// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
  		/// <exception cref="Exception">The operation failed.</exception>
  		public FreeImageBitmap(Bitmap original)
  		{
  			if (original == null)
  			{
  				throw new ArgumentNullException("original");
  			}
  			dib = FreeImage.CreateFromBitmap(original, true);
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorLoadingBitmap);
  			}
  			originalFormat = FreeImage.GetFormat(original.RawFormat);
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified image with the specified size.
  		/// </summary>
  		/// <param name="original">The original to clone from.</param>
  		/// <param name="newSize">The Size structure that represent the
  		/// size of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <remarks>
  		/// Although this constructor supports creating images in both formats
  		/// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
  		/// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
  		/// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
  		/// images respectively. Currently, there is no  support for automatic premultiplying images in
  		/// <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// Width or height of <paramref name="newSize"/> are less or equal zero.
  		/// </exception>
  		public FreeImageBitmap(Bitmap original, Size newSize)
  			: this(original, newSize.Width, newSize.Height)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified image with the specified size.
  		/// </summary>
  		/// <param name="original">The original to clone from.</param>
  		/// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <remarks>
  		/// Although this constructor supports creating images in both formats
  		/// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
  		/// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
  		/// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
  		/// images respectively. Currently, there is no  support for automatic premultiplying images in
  		/// <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
  		public FreeImageBitmap(Bitmap original, int width, int height)
  		{
  			if (original == null)
  			{
  				throw new ArgumentNullException("original");
  			}
  			if (width <= 0)
  			{
  				throw new ArgumentOutOfRangeException("width");
  			}
  			if (height <= 0)
  			{
  				throw new ArgumentOutOfRangeException("height");
  			}
  			FIBITMAP temp = FreeImage.CreateFromBitmap(original, true);
  			if (temp.IsNull)
  			{
  				throw new Exception(ErrorLoadingBitmap);
  			}
  			dib = FreeImage.Rescale(temp, width, height, FREE_IMAGE_FILTER.FILTER_BICUBIC);
  			FreeImage.Unload(temp);
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorLoadingBitmap);
  			}
  			originalFormat = FreeImage.GetFormat(original.RawFormat);
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified stream.
  		/// </summary>
  		/// <param name="stream">Stream to read from.</param>
  		/// <param name="useIcm">Ignored.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
  		/// <remarks>
  		/// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		public FreeImageBitmap(Stream stream, bool useIcm)
  			: this(stream)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified stream.
  		/// </summary>
  		/// <param name="stream">Stream to read from.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
  		/// <remarks>
  		/// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		public FreeImageBitmap(Stream stream)
  			: this(stream, FREE_IMAGE_FORMAT.FIF_UNKNOWN, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified stream in the specified format.
  		/// </summary>
  		/// <param name="stream">Stream to read from.</param>
  		/// <param name="format">Format of the image.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
  		/// <remarks>
  		/// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		public FreeImageBitmap(Stream stream, FREE_IMAGE_FORMAT format)
  			: this(stream, format, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified stream with the specified loading flags.
  		/// </summary>
  		/// <param name="stream">Stream to read from.</param>
  		/// <param name="flags">Flags to enable or disable plugin-features.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
  		/// <remarks>
  		/// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		public FreeImageBitmap(Stream stream, FREE_IMAGE_LOAD_FLAGS flags)
  			: this(stream, FREE_IMAGE_FORMAT.FIF_UNKNOWN, flags)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified stream in the specified format
  		/// with the specified loading flags.
  		/// </summary>
  		/// <param name="stream">Stream to read from.</param>
  		/// <param name="format">Format of the image.</param>
  		/// <param name="flags">Flags to enable or disable plugin-features.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
  		/// <remarks>
  		/// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		public FreeImageBitmap(Stream stream, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS flags)
  		{
  			if (stream == null)
  			{
  				throw new ArgumentNullException("stream");
  			}
  			this.stream = stream;
  			disposeStream = false;
  			LoadFromStream(stream, format, flags);
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file.
  		/// </summary>
  		/// <param name="filename">The complete name of the file to load.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
  		/// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
  		public FreeImageBitmap(string filename)
  			: this(filename, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file.
  		/// </summary>
  		/// <param name="filename">The complete name of the file to load.</param>
  		/// <param name="useIcm">Ignored.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
  		/// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
  		public FreeImageBitmap(string filename, bool useIcm)
  			: this(filename)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file
  		/// with the specified loading flags.
  		/// </summary>
  		/// <param name="filename">The complete name of the file to load.</param>
  		/// <param name="flags">Flags to enable or disable plugin-features.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
  		/// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
  		public FreeImageBitmap(string filename, FREE_IMAGE_LOAD_FLAGS flags)
  			: this(filename, FREE_IMAGE_FORMAT.FIF_UNKNOWN, flags)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file
  		/// in the specified format.
  		/// </summary>
  		/// <param name="filename">The complete name of the file to load.</param>
  		/// <param name="format">Format of the image.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
  		/// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
  		public FreeImageBitmap(string filename, FREE_IMAGE_FORMAT format)
  			: this(filename, format, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file
  		/// in the specified format with the specified loading flags.
  		/// </summary>
  		/// <param name="filename">The complete name of the file to load.</param>
  		/// <param name="format">Format of the image.</param>
  		/// <param name="flags">Flags to enable or disable plugin-features.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
  		/// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
  		public FreeImageBitmap(string filename, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS flags)
  		{
  			if (filename == null)
  			{
  				throw new ArgumentNullException("filename");
  			}
  			if (!File.Exists(filename))
  			{
  				throw new FileNotFoundException("filename");
  			}
  
  			saveInformation.filename = filename;
  			stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
  			disposeStream = true;
  			LoadFromStream(stream, format, flags);
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
  		/// bases on the specified size.
  		/// </summary>
  		/// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		public FreeImageBitmap(int width, int height)
  		{
  			dib = FreeImage.Allocate(
  				width,
  				height,
  				24,
  				FreeImage.FI_RGBA_RED_MASK,
  				FreeImage.FI_RGBA_GREEN_MASK,
  				FreeImage.FI_RGBA_BLUE_MASK);
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorCreatingBitmap);
  			}
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified resource.
  		/// </summary>
  		/// <param name="type">The class used to extract the resource.</param>
  		/// <param name="resource">The name of the resource.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		public FreeImageBitmap(Type type, string resource)
  			: this(type.Module.Assembly.GetManifestResourceStream(type, resource))
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size
  		/// and with the resolution of the specified <see cref="System.Drawing.Graphics"/> object.
  		/// </summary>
  		/// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="g">The Graphics object that specifies the resolution for the new <see cref="FreeImageBitmap"/>.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="g"/> is a null reference.</exception>
  		public FreeImageBitmap(int width, int height, Graphics g)
  			: this(width, height)
  		{
  			FreeImage.SetResolutionX(dib, (uint)g.DpiX);
  			FreeImage.SetResolutionY(dib, (uint)g.DpiY);
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size and format.
  		/// </summary>
  		/// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="format">The PixelFormat enumeration for the new <see cref="FreeImageBitmap"/>.</param>
  		/// <remarks>
  		/// Although this constructor supports creating images in both formats
  		/// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
  		/// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
  		/// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
  		/// images respectively. Currently, there is no  support for automatic premultiplying images in
  		/// <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
  		public FreeImageBitmap(int width, int height, PixelFormat format)
  		{
  			if (width <= 0)
  			{
  				throw new ArgumentOutOfRangeException("width");
  			}
  			if (height <= 0)
  			{
  				throw new ArgumentOutOfRangeException("height");
  			}
  			uint bpp, redMask, greenMask, blueMask;
  			FREE_IMAGE_TYPE type;
  			if (!FreeImage.GetFormatParameters(format, out type, out bpp, out redMask, out greenMask, out blueMask))
  			{
  				throw new ArgumentException("format is invalid");
  			}
  			dib = FreeImage.AllocateT(type, width, height, (int)bpp, redMask, greenMask, blueMask);
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorCreatingBitmap);
  			}
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size and type.
  		/// Only non standard bitmaps are supported.
  		/// </summary>	
  		/// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="type">The type of the bitmap.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="type"/> is FIT_BITMAP or FIT_UNKNOWN.</exception>
  		/// <exception cref="ArgumentException"><paramref name="type"/> is invalid.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
  		public FreeImageBitmap(int width, int height, FREE_IMAGE_TYPE type)
  		{
  			if (width <= 0)
  			{
  				throw new ArgumentOutOfRangeException("width");
  			}
  			if (height <= 0)
  			{
  				throw new ArgumentOutOfRangeException("height");
  			}
  			if ((type == FREE_IMAGE_TYPE.FIT_BITMAP) || (type == FREE_IMAGE_TYPE.FIT_UNKNOWN))
  			{
  				throw new ArgumentException("type is invalid.");
  			}
  			dib = FreeImage.AllocateT(type, width, height, 0, 0u, 0u, 0u);
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorCreatingBitmap);
  			}
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
  		/// pixel format and pixel data.
  		/// </summary>
  		/// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="stride">Integer that specifies the byte offset between the beginning
  		/// of one scan line and the next. This is usually (but not necessarily)
  		/// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
  		/// multiplied by the width of the bitmap. The value passed to this parameter must
  		/// be a multiple of four..</param>
  		/// <param name="format">The PixelFormat enumeration for the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="scan0">Pointer to an array of bytes that contains the pixel data.</param>
  		/// <remarks>
  		/// Although this constructor supports creating images in both formats
  		/// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
  		/// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
  		/// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
  		/// images respectively. Currently, there is no  support for automatic premultiplying images in
  		/// <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
  		public FreeImageBitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0)
  		{
  			if (width <= 0)
  			{
  				throw new ArgumentOutOfRangeException("width");
  			}
  			if (height <= 0)
  			{
  				throw new ArgumentOutOfRangeException("height");
  			}
  			uint bpp, redMask, greenMask, blueMask;
  			FREE_IMAGE_TYPE type;
  			bool topDown = (stride > 0);
  			stride = (stride > 0) ? stride : (stride * -1);
  
  			if (!FreeImage.GetFormatParameters(format, out type, out bpp, out redMask, out greenMask, out blueMask))
  			{
  				throw new ArgumentException("format is invalid.");
  			}
  
  			dib = FreeImage.ConvertFromRawBits(
  				scan0, type, width, height, stride, bpp, redMask, greenMask, blueMask, topDown);
  
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorCreatingBitmap);
  			}
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
  		/// pixel format and pixel data.
  		/// </summary>
  		/// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="stride">Integer that specifies the byte offset between the beginning
  		/// of one scan line and the next. This is usually (but not necessarily)
  		/// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
  		/// multiplied by the width of the bitmap. The value passed to this parameter must
  		/// be a multiple of four..</param>
  		/// <param name="format">The PixelFormat enumeration for the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="bits">Array of bytes containing the bitmap data.</param>
  		/// <remarks>
  		/// Although this constructor supports creating images in both formats
  		/// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
  		/// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
  		/// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
  		/// images respectively. Currently, there is no  support for automatic premultiplying images in
  		/// <see cref="FreeImageBitmap"/>.
  		/// </remarks>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="bits"/> is null</exception>
  		public FreeImageBitmap(int width, int height, int stride, PixelFormat format, byte[] bits)
  		{
  			if (width <= 0)
  			{
  				throw new ArgumentOutOfRangeException("width");
  			}
  			if (height <= 0)
  			{
  				throw new ArgumentOutOfRangeException("height");
  			}
  			if (bits == null)
  			{
  				throw new ArgumentNullException("bits");
  			}
  			uint bpp, redMask, greenMask, blueMask;
  			FREE_IMAGE_TYPE type;
  			bool topDown = (stride > 0);
  			stride = (stride > 0) ? stride : (stride * -1);
  
  			if (!FreeImage.GetFormatParameters(format, out type, out bpp, out redMask, out greenMask, out blueMask))
  			{
  				throw new ArgumentException("format is invalid.");
  			}
  
  			dib = FreeImage.ConvertFromRawBits(
  				bits, type, width, height, stride, bpp, redMask, greenMask, blueMask, topDown);
  
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorCreatingBitmap);
  			}
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
  		/// pixel format and pixel data.
  		/// </summary>
  		/// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="stride">Integer that specifies the byte offset between the beginning
  		/// of one scan line and the next. This is usually (but not necessarily)
  		/// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
  		/// multiplied by the width of the bitmap. The value passed to this parameter must
  		/// be a multiple of four..</param>
  		/// <param name="bpp">The color depth of the new <see cref="FreeImageBitmap"/></param>
  		/// <param name="type">The type for the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="scan0">Pointer to an array of bytes that contains the pixel data.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentException">Format is invalid.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
  		public FreeImageBitmap(int width, int height, int stride, int bpp, FREE_IMAGE_TYPE type, IntPtr scan0)
  		{
  			if (width <= 0)
  			{
  				throw new ArgumentOutOfRangeException("width");
  			}
  			if (height <= 0)
  			{
  				throw new ArgumentOutOfRangeException("height");
  			}
  			uint redMask, greenMask, blueMask;
  			bool topDown = (stride > 0);
  			stride = (stride > 0) ? stride : (stride * -1);
  
  			if (!FreeImage.GetTypeParameters(type, bpp, out redMask, out greenMask, out blueMask))
  			{
  				throw new ArgumentException("bpp and type are invalid or not supported.");
  			}
  
  			dib = FreeImage.ConvertFromRawBits(
  				scan0, type, width, height, stride, (uint)bpp, redMask, greenMask, blueMask, topDown);
  
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorCreatingBitmap);
  			}
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
  		/// pixel format and pixel data.
  		/// </summary>
  		/// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="stride">Integer that specifies the byte offset between the beginning
  		/// of one scan line and the next. This is usually (but not necessarily)
  		/// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
  		/// multiplied by the width of the bitmap. The value passed to this parameter must
  		/// be a multiple of four..</param>
  		/// <param name="bpp">The color depth of the new <see cref="FreeImageBitmap"/></param>
  		/// <param name="type">The type for the new <see cref="FreeImageBitmap"/>.</param>
  		/// <param name="bits">Array of bytes containing the bitmap data.</param>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="ArgumentException">Format is invalid.</exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="bits"/> is null</exception>
  		public FreeImageBitmap(int width, int height, int stride, int bpp, FREE_IMAGE_TYPE type, byte[] bits)
  		{
  			if (width <= 0)
  			{
  				throw new ArgumentOutOfRangeException("width");
  			}
  			if (height <= 0)
  			{
  				throw new ArgumentOutOfRangeException("height");
  			}
  			if (bits == null)
  			{
  				throw new ArgumentNullException("bits");
  			}
  			uint redMask, greenMask, blueMask;
  			bool topDown = (stride > 0);
  			stride = (stride > 0) ? stride : (stride * -1);
  
  			if (!FreeImage.GetTypeParameters(type, bpp, out redMask, out greenMask, out blueMask))
  			{
  				throw new ArgumentException("bpp and type are invalid or not supported.");
  			}
  
  			dib = FreeImage.ConvertFromRawBits(
  				bits, type, width, height, stride, (uint)bpp, redMask, greenMask, blueMask, topDown);
  
  			if (dib.IsNull)
  			{
  				throw new Exception(ErrorCreatingBitmap);
  			}
  			AddMemoryPressure();
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="FreeImageBitmap"/> class.
  		/// </summary>
  		/// <exception cref="Exception">The operation failed.</exception>
  		/// <exception cref="SerializationException">The operation failed.</exception>
  		public FreeImageBitmap(SerializationInfo info, StreamingContext context)
  		{
  			try
  			{
  				byte[] data = (byte[])info.GetValue("Bitmap Data", typeof(byte[]));
  				if ((data != null) && (data.Length > 0))
  				{
  					MemoryStream memory = new MemoryStream(data);
  					FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_TIFF;
  					dib = FreeImage.LoadFromStream(memory, ref format);
  
  					if (dib.IsNull)
  					{
  						throw new Exception(ErrorLoadingBitmap);
  					}
  
  					AddMemoryPressure();
  				}
  			}
  			catch (Exception ex)
  			{
  				throw new SerializationException("Deserialization failed.", ex);
  			}
  		}
  
  		/// <summary>
  		/// Frees all managed and unmanaged ressources.
  		/// </summary>
  		~FreeImageBitmap()
  		{
  			Dispose(false);
  		}
  
  		#endregion
  
  		#region Operators
  
  		/// <summary>
  		/// Converts a <see cref="FreeImageBitmap"/> instance to a <see cref="Bitmap"/> instance.
  		/// </summary>
  		/// <param name="value">A <see cref="FreeImageBitmap"/> instance.</param>
  		/// <returns>A new instance of <see cref="Bitmap"/> initialized to <paramref name="value"/>.</returns>
  		/// <remarks>
  		/// The explicit conversion from <see cref="FreeImageBitmap"/> into Bitmap
  		/// allows to create an instance on the fly and use it as if
  		/// was a Bitmap. This way it can be directly used with a
  		/// PixtureBox for example without having to call any
  		/// conversion operations.
  		/// </remarks>
  		public static explicit operator Bitmap(FreeImageBitmap value)
  		{
  			return value.ToBitmap();
  		}
  
  		/// <summary>
  		/// Converts a <see cref="Bitmap"/> instance to a <see cref="FreeImageBitmap"/> instance.
  		/// </summary>
  		/// <param name="value">A <see cref="Bitmap"/> instance.</param>
  		/// <returns>A new instance of <see cref="FreeImageBitmap"/> initialized to <paramref name="value"/>.</returns>
  		/// <remarks>
  		/// The explicit conversion from <see cref="Bitmap"/> into <see cref="FreeImageBitmap"/>
  		/// allows to create an instance on the fly to perform
  		/// image processing operations and converting it back.
  		/// </remarks>
  		public static explicit operator FreeImageBitmap(Bitmap value)
  		{
  			return new FreeImageBitmap(value);
  		}
  
  		/// <summary>
  		/// Determines whether two specified <see cref="FreeImageBitmap"/> objects have the same value.
  		/// </summary>
  		/// <param name="left">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
  		/// <param name="right">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
  		/// <returns>
  		/// <b>true</b> if the value of left is the same as the value of right; otherwise, <b>false</b>.
  		/// </returns>
  		public static bool operator ==(FreeImageBitmap left, FreeImageBitmap right)
  		{
  			if (object.ReferenceEquals(left, right))
  			{
  				return true;
  			}
  			else if (object.ReferenceEquals(left, null) || object.ReferenceEquals(right, null))
  			{
  				return false;
  			}
  			else
  			{
  				left.EnsureNotDisposed();
  				right.EnsureNotDisposed();
  				return FreeImage.Compare(left.dib, right.dib, FREE_IMAGE_COMPARE_FLAGS.COMPLETE);
  			}
  		}
  
  		/// <summary>
  		/// Determines whether two specified <see cref="FreeImageBitmap"/> objects have different values.
  		/// </summary>
  		/// <param name="left">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
  		/// <param name="right">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
  		/// <returns>
  		/// true if the value of left is different from the value of right; otherwise, <b>false</b>.
  		/// </returns>
  		public static bool operator !=(FreeImageBitmap left, FreeImageBitmap right)
  		{
  			return (!(left == right));
  		}
  
  		#endregion
  
  		#region Properties
  
  		/// <summary>
  		/// Type of the bitmap.
  		/// </summary>
  		public FREE_IMAGE_TYPE ImageType
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetImageType(dib);
  			}
  		}
  
  		/// <summary>
  		/// Number of palette entries.
  		/// </summary>
  		public int ColorsUsed
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return (int)FreeImage.GetColorsUsed(dib);
  			}
  		}
  
  		/// <summary>
  		/// The number of unique colors actually used by the bitmap. This might be different from
  		/// what ColorsUsed returns, which actually returns the palette size for palletised images.
  		/// Works for FIT_BITMAP type bitmaps only.
  		/// </summary>
  		public int UniqueColors
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetUniqueColors(dib);
  			}
  		}
  
  		/// <summary>
  		/// The size of one pixel in the bitmap in bits.
  		/// </summary>
  		public int ColorDepth
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return (int)FreeImage.GetBPP(dib);
  			}
  		}
  
  		/// <summary>
  		/// Width of the bitmap in pixel units.
  		/// </summary>
  		public int Width
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return (int)FreeImage.GetWidth(dib);
  			}
  		}
  
  		/// <summary>
  		/// Height of the bitmap in pixel units.
  		/// </summary>
  		public int Height
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return (int)FreeImage.GetHeight(dib);
  			}
  		}
  
  		/// <summary>
  		/// Returns the width of the bitmap in bytes, rounded to the next 32-bit boundary.
  		/// </summary>
  		public int Pitch
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return (int)FreeImage.GetPitch(dib);
  			}
  		}
  
  		/// <summary>
  		/// Size of the bitmap in memory.
  		/// </summary>
  		public int DataSize
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return (int)FreeImage.GetDIBSize(dib);
  			}
  		}
  
  		/// <summary>
  		/// Returns a structure that represents the palette of a FreeImage bitmap.
  		/// </summary>
  		/// <exception cref="InvalidOperationException"><see cref="HasPalette"/> is false.</exception>
  		public Palette Palette
  		{
  			get
  			{
  				EnsureNotDisposed();
  				if (HasPalette)
  				{
  					return new Palette(dib);
  				}
  				throw new InvalidOperationException("This bitmap does not have a palette.");
  			}
  		}
  
  		/// <summary>
  		/// Gets whether the bitmap is RGB 555.
  		/// </summary>
  		public bool IsRGB555
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.IsRGB555(dib);
  			}
  		}
  
  		/// <summary>
  		/// Gets whether the bitmap is RGB 565.
  		/// </summary>
  		public bool IsRGB565
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.IsRGB565(dib);
  			}
  		}
  
  		/// <summary>
  		/// Gets the horizontal resolution, in pixels per inch, of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public float HorizontalResolution
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return (float)FreeImage.GetResolutionX(dib);
  			}
  			private set
  			{
  				EnsureNotDisposed();
  				FreeImage.SetResolutionX(dib, (uint)value);
  			}
  		}
  
  		/// <summary>
  		/// Gets the vertical resolution, in pixels per inch, of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public float VerticalResolution
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return (float)FreeImage.GetResolutionY(dib);
  			}
  			private set
  			{
  				EnsureNotDisposed();
  				FreeImage.SetResolutionY(dib, (uint)value);
  			}
  		}
  
  		/// <summary>
  		/// Returns the <see cref="BITMAPINFOHEADER"/> structure of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public BITMAPINFOHEADER InfoHeader
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetInfoHeaderEx(dib);
  			}
  		}
  
  		/// <summary>
  		/// Returns the <see cref="BITMAPINFO"/> structure of a this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public BITMAPINFO Info
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetInfoEx(dib);
  			}
  		}
  
  		/// <summary>
  		/// Investigates the color type of this <see cref="FreeImageBitmap"/>
  		/// by reading the bitmaps pixel bits and analysing them.
  		/// </summary>
  		public FREE_IMAGE_COLOR_TYPE ColorType
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetColorType(dib);
  			}
  		}
  
  		/// <summary>
  		/// Bit pattern describing the red color component of a pixel in this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public uint RedMask
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetRedMask(dib);
  			}
  		}
  
  		/// <summary>
  		/// Bit pattern describing the green color component of a pixel in this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public uint GreenMask
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetGreenMask(dib);
  			}
  		}
  
  		/// <summary>
  		/// Bit pattern describing the blue color component of a pixel in this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public uint BlueMask
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetBlueMask(dib);
  			}
  		}
  
  		/// <summary>
  		/// Number of transparent colors in a palletised <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public int TransparencyCount
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return (int)FreeImage.GetTransparencyCount(dib);
  			}
  		}
  
  		/// <summary>
  		/// Get or sets transparency table of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public byte[] TransparencyTable
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetTransparencyTableEx(dib);
  			}
  			set
  			{
  				EnsureNotDisposed();
  				FreeImage.SetTransparencyTable(dib, value);
  			}
  		}
  
  		/// <summary>
  		/// Gets or sets whether this <see cref="FreeImageBitmap"/> is transparent.
  		/// </summary>
  		public bool IsTransparent
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.IsTransparent(dib);
  			}
  			set
  			{
  				EnsureNotDisposed();
  				FreeImage.SetTransparent(dib, value);
  			}
  		}
  
  		/// <summary>
  		/// Gets whether this <see cref="FreeImageBitmap"/> has a file background color.
  		/// </summary>
  		public bool HasBackgroundColor
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.HasBackgroundColor(dib);
  			}
  		}
  
  		/// <summary>
  		/// Gets or sets the background color of this <see cref="FreeImageBitmap"/>.
  		/// In case the value is null, the background color is removed.
  		/// </summary>
  		/// <exception cref="InvalidOperationException">Get: There is no background color available.</exception>
  		/// <exception cref="Exception">Set: Setting background color failed.</exception>
  		public Color? BackgroundColor
  		{
  			get
  			{
  				EnsureNotDisposed();
  				if (!FreeImage.HasBackgroundColor(dib))
  				{
  					throw new InvalidOperationException("No background color available.");
  				}
  				RGBQUAD rgbq;
  				FreeImage.GetBackgroundColor(dib, out rgbq);
  				return rgbq.Color;
  			}
  			set
  			{
  				EnsureNotDisposed();
  				if (!FreeImage.SetBackgroundColor(dib, (value.HasValue ? new RGBQUAD[] { value.Value } : null)))
  				{
  					throw new Exception("Setting background color failed.");
  				}
  			}
  		}
  
  		/// <summary>
  		/// Pointer to the data-bits of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public IntPtr Bits
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetBits(dib);
  			}
  		}
  
  		/// <summary>
  		/// Width, in bytes, of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public int Line
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return (int)FreeImage.GetLine(dib);
  			}
  		}
  
  		/// <summary>
  		/// Pointer to the scanline of the top most pixel row of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public IntPtr Scan0
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetScanLine(dib, (int)(FreeImage.GetHeight(dib) - 1));
  			}
  		}
  
  		/// <summary>
  		/// Width, in bytes, of this <see cref="FreeImageBitmap"/>.
  		/// In case this <see cref="FreeImageBitmap"/> is top down <b>Stride</b> will be positive, else negative.
  		/// </summary>
  		public int Stride
  		{
  			get
  			{
  				return -Line;
  			}
  		}
  
  		/// <summary>
  		/// Gets attribute flags for the pixel data of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public unsafe int Flags
  		{
  			get
  			{
  				EnsureNotDisposed();
  				int result = 0;
  				byte alpha;
  				int cd = ColorDepth;
  
  				if ((cd == 32) || (FreeImage.GetTransparencyCount(dib) != 0))
  				{
  					result += (int)ImageFlags.HasAlpha;
  				}
  
  				if (cd == 32)
  				{
  					uint width = FreeImage.GetWidth(dib);
  					uint height = FreeImage.GetHeight(dib);
  					for (int y = 0; y < height; y++)
  					{
  						RGBQUAD* scanline = (RGBQUAD*)FreeImage.GetScanLine(dib, y);
  						for (int x = 0; x < width; x++)
  						{
  							alpha = scanline[x].Color.A;
  							if (alpha != byte.MinValue && alpha != byte.MaxValue)
  							{
  								result += (int)ImageFlags.HasTranslucent;
  								y = (int)height;
  								break;
  							}
  						}
  					}
  				}
  				else if (FreeImage.GetTransparencyCount(dib) != 0)
  				{
  					byte[] transTable = FreeImage.GetTransparencyTableEx(dib);
  					for (int i = 0; i < transTable.Length; i++)
  					{
  						if (transTable[i] != byte.MinValue && transTable[i] != byte.MaxValue)
  						{
  							result += (int)ImageFlags.HasTranslucent;
  							break;
  						}
  					}
  				}
  
  				if (FreeImage.GetICCProfileEx(dib).IsCMYK)
  				{
  					result += (int)ImageFlags.ColorSpaceCmyk;
  				}
  				else
  				{
  					result += (int)ImageFlags.ColorSpaceRgb;
  				}
  
  				if (FreeImage.GetColorType(dib) == FREE_IMAGE_COLOR_TYPE.FIC_MINISBLACK ||
  					FreeImage.GetColorType(dib) == FREE_IMAGE_COLOR_TYPE.FIC_MINISWHITE)
  				{
  					result += (int)ImageFlags.ColorSpaceGray;
  				}
  
  				if (originalFormat == FREE_IMAGE_FORMAT.FIF_BMP ||
  					originalFormat == FREE_IMAGE_FORMAT.FIF_FAXG3 ||
  					originalFormat == FREE_IMAGE_FORMAT.FIF_ICO ||
  					originalFormat == FREE_IMAGE_FORMAT.FIF_JPEG ||
  					originalFormat == FREE_IMAGE_FORMAT.FIF_PCX ||
  					originalFormat == FREE_IMAGE_FORMAT.FIF_PNG ||
  					originalFormat == FREE_IMAGE_FORMAT.FIF_PSD ||
  					originalFormat == FREE_IMAGE_FORMAT.FIF_TIFF)
  				{
  					result += (int)ImageFlags.HasRealDpi;
  				}
  
  				return result;
  			}
  		}
  
  		/// <summary>
  		/// Gets the width and height of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public SizeF PhysicalDimension
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return new SizeF((float)FreeImage.GetWidth(dib), (float)FreeImage.GetHeight(dib));
  			}
  		}
  
  		/// <summary>
  		/// Gets the pixel format for this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public PixelFormat PixelFormat
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetPixelFormat(dib);
  			}
  		}
  
  		/// <summary>
  		/// Gets IDs of the property items stored in this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public int[] PropertyIdList
  		{
  			get
  			{
  				EnsureNotDisposed();
  				List<int> list = new List<int>();
  				ImageMetadata metaData = new ImageMetadata(dib, true);
  
  				foreach (MetadataModel metadataModel in metaData)
  				{
  					foreach (MetadataTag metadataTag in metadataModel)
  					{
  						list.Add(metadataTag.ID);
  					}
  				}
  
  				return list.ToArray();
  			}
  		}
  
  		/// <summary>
  		/// Gets all the property items (pieces of metadata) stored in this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public PropertyItem[] PropertyItems
  		{
  			get
  			{
  				EnsureNotDisposed();
  				List<PropertyItem> list = new List<PropertyItem>();
  				ImageMetadata metaData = new ImageMetadata(dib, true);
  
  				foreach (MetadataModel metadataModel in metaData)
  				{
  					foreach (MetadataTag metadataTag in metadataModel)
  					{
  						list.Add(metadataTag.GetPropertyItem());
  					}
  				}
  
  				return list.ToArray();
  			}
  		}
  
  		/// <summary>
  		/// Gets the format of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public ImageFormat RawFormat
  		{
  			get
  			{
  				EnsureNotDisposed();
  				Attribute guidAttribute =
  					Attribute.GetCustomAttribute(
  						typeof(FreeImageBitmap), typeof(System.Runtime.InteropServices.GuidAttribute)
  					);
  				return (guidAttribute == null) ?
  					null :
  					new ImageFormat(new Guid(((GuidAttribute)guidAttribute).Value));
  			}
  		}
  
  		/// <summary>
  		/// Gets the width and height, in pixels, of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public Size Size
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return new Size(Width, Height);
  			}
  		}
  
  		/// <summary>
  		/// Gets or sets an object that provides additional data about the <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public Object Tag
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return tag;
  			}
  			set
  			{
  				EnsureNotDisposed();
  				tag = value;
  			}
  		}
  
  		/// <summary>
  		/// Gets whether this <see cref="FreeImageBitmap"/> has been disposed.
  		/// </summary>
  		public bool IsDisposed
  		{
  			get
  			{
  				return disposed;
  			}
  		}
  
  		/// <summary>
  		/// Gets a new instance of a metadata representing class.
  		/// </summary>
  		public ImageMetadata Metadata
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return new ImageMetadata(dib, true);
  			}
  		}
  
  		/// <summary>
  		/// Gets or sets the comment of this <see cref="FreeImageBitmap"/>.
  		/// Supported formats are JPEG, PNG and GIF.
  		/// </summary>
  		public string Comment
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetImageComment(dib);
  			}
  			set
  			{
  				EnsureNotDisposed();
  				FreeImage.SetImageComment(dib, value);
  			}
  		}
  
  		/// <summary>
  		/// Returns whether this <see cref="FreeImageBitmap"/> has a palette.
  		/// </summary>
  		public bool HasPalette
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return (FreeImage.GetPalette(dib) != IntPtr.Zero);
  			}
  		}
  
  		/// <summary>
  		/// Gets or sets the entry used as transparent color in this <see cref="FreeImageBitmap"/>.
  		/// Only works for 1-, 4- and 8-bpp.
  		/// </summary>
  		public int TransparentIndex
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetTransparentIndex(dib);
  			}
  			set
  			{
  				EnsureNotDisposed();
  				FreeImage.SetTransparentIndex(dib, value);
  			}
  		}
  
  		/// <summary>
  		/// Gets the number of frames in this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public int FrameCount
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return frameCount;
  			}
  		}
  
  		/// <summary>
  		/// Gets the ICCProfile structure of this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		public FIICCPROFILE ICCProfile
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return FreeImage.GetICCProfileEx(dib);
  			}
  		}
  
  		/// <summary>
  		/// Gets the format of the original image in case
  		/// this <see cref="FreeImageBitmap"/> was loaded from a file or stream.
  		/// </summary>
  		public FREE_IMAGE_FORMAT ImageFormat
  		{
  			get
  			{
  				EnsureNotDisposed();
  				return originalFormat;
  			}
  		}
  
  		/// <summary>
  		/// Gets the encapsulated FIBITMAP.
  		/// </summary>
  		internal FIBITMAP Dib
  		{
  			get { EnsureNotDisposed(); return dib; }
  		}
  
  		#endregion
  
  		#region Methods
  
  		/// <summary>
  		/// Gets the bounds of this <see cref="FreeImageBitmap"/> in the specified unit.
  		/// </summary>
  		/// <param name="pageUnit">One of the <see cref="System.Drawing.GraphicsUnit"/> values indicating
  		/// the unit of measure for the bounding rectangle.</param>
  		/// <returns>The <see cref="System.Drawing.RectangleF"/> that represents the bounds of this
  		/// <see cref="FreeImageBitmap"/>, in the specified unit.</returns>
  		public RectangleF GetBounds(ref GraphicsUnit pageUnit)
  		{
  			EnsureNotDisposed();
  			pageUnit = GraphicsUnit.Pixel;
  			return new RectangleF(
  					0f,
  					0f,
  					(float)FreeImage.GetWidth(dib),
  					(float)FreeImage.GetHeight(dib));
  		}
  
  		/// <summary>
  		/// Gets the specified property item from this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		/// <param name="propid">The ID of the property item to get.</param>
  		/// <returns>The <see cref="PropertyItem"/> this method gets.</returns>
  		public PropertyItem GetPropertyItem(int propid)
  		{
  			EnsureNotDisposed();
  			ImageMetadata metadata = new ImageMetadata(dib, true);
  			foreach (MetadataModel metadataModel in metadata)
  			{
  				foreach (MetadataTag tag in metadataModel)
  				{
  					if (tag.ID == propid)
  					{
  						return tag.GetPropertyItem();
  					}
  				}
  			}
  			return null;
  		}
  
  		/// <summary>
  		/// Returns a thumbnail for this <see cref="FreeImageBitmap"/>.
  		/// </summary>
  		/// <param name="thumbWidth">The width, in pixels, of the requested thumbnail image.</param>
  		/// <param name="thumbHeight">The height, in pixels, of the requested thumbnail image.</param>
  		/// <param name="callback">Ignored.</param>
  		/// <param name="callBackData">Ignored.</param>
  		/// <returns>A <see cref="FreeImageBitmap"/> that represents the thumbnail.</returns>
  		public FreeImageBitmap GetThumbnailImage(int thumbWidth, int thumbHeight,
  			Image.GetThumbnailImageAbort callback, IntPtr callBackData)
  		{
  			EnsureNotDisposed();
  			FreeImageBitmap result = null;
  			FIBITMAP newDib = FreeImage.Rescale(
  				dib, thumbWidth, thumbHeight, FREE_IMAGE_FILTER.FILTER_BICUBIC);
  			if (!newDib.IsNull)
  			{
  				result = new FreeImageBitmap(newDib);
  			}
  			return result;
  		}
  
  		/// <summary>
  		/// Returns a thumbnail for this <see cref="FreeImageBitmap"/>, keeping aspect ratio.
  		/// <paramref name="maxPixelSize"/> defines the maximum width or height
  		/// of the thumbnail.
  		/// </summary>
  		/// <param name="maxPixelSize">Thumbnail square size.</param>
  		/// <param name="convert">When true HDR images are transperantly
  		/// converted to standard images.</param>
  		/// <returns>The thumbnail in a new instance.</returns>
  		public FreeImageBitmap GetThumbnailImage(int maxPixelSize, bool convert)
  		{
  			EnsureNotDisposed();
  			FreeImageBitmap result = null;
  			FIBITMAP newDib = FreeImage.MakeThumbnail(dib, maxPixelSize, convert);
  			if (!newDib.IsNull)
  			{
  				result = new FreeImageBitmap(newDib);
  			}
  			return result;
  		}
  
  		/// <summary>
  		/// Converts this <see cref="FreeImageBitmap"/> instance to a <see cref="Bitmap"/> instance.
  		/// </summary>
  		/// <returns>A new instance of <see cref="Bitmap"/> initialized this instance.</returns>
  		public Bitmap ToBitmap()
  		{
  			EnsureNotDisposed();
  			return FreeImage.GetBitmap(dib, true);
  		}
  
  		/// <summary>
  		/// Returns an instance of <see cref="Scanline&lt;T&gt;"/>, representing the scanline
  		/// specified by <paramref name="scanline"/> of this <see cref="FreeImageBitmap"/>.
  		/// Since FreeImage bitmaps are always bottum up aligned, keep in mind that scanline 0 is the
  		/// bottom-most line of the image.
  		/// </summary>
  		/// <param name="scanline">Number of the scanline to retrieve.</param>
  		/// <returns>An instance of <see cref="Scanline&lt;T&gt;"/> representing the
  		/// <paramref name="scanline"/>th scanline.</returns>
  		/// <remarks>
  		/// List of return-types of <b>T</b>:<para/>
  		/// <list type="table">
  		/// <listheader><term>Color Depth / Type</term><description><see cref="Type">Result Type</see></description></listheader>
  		/// <item><term>1 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI1BIT"/></description></item>
  		/// <item><term>4 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI4BIT"/></description></item>
  		/// <item><term>8 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="Byte"/></description></item>
  		/// <item><term>16 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="UInt16"/></description></item>
  		/// <item><term>16 - 555 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB555"/></description></item>
  		/// <item><term>16 - 565 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB565"/></description></item>
  		/// <item><term>24 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBTRIPLE"/></description></item>
  		/// <item><term>32 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBQUAD"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_COMPLEX"/></term><description><see cref="FICOMPLEX"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_DOUBLE"/></term><description><see cref="Double"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_FLOAT"/></term><description><see cref="Single"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT16"/></term><description><see cref="Int16"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT32"/></term><description><see cref="Int32"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGB16"/></term><description><see cref="FIRGB16"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBA16"/></term><description><see cref="FIRGBA16"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBAF"/></term><description><see cref="FIRGBAF"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBF"/></term><description><see cref="FIRGBF"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT16"/></term><description><see cref="UInt16"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT32"/></term><description><see cref="UInt32"/></description></item>
  		/// </list>
  		/// </remarks>
  		/// <example>
  		/// <code>
  		/// FreeImageBitmap bitmap = new FreeImageBitmap(@"C:\Pictures\picture.bmp");
  		/// if (bitmap.ColorDepth == 32)
  		/// {
  		/// 	Scanline&lt;RGBQUAD&gt; scanline = bitmap.GetScanline&lt;RGBQUAD&gt;(0);
  		/// 	foreach (RGBQUAD pixel in scanline)
  		/// 	{
  		///			Console.WriteLine(pixel);
  		/// 	}
  		///	}
  		/// </code>
  		/// </example>
  		/// <exception cref="ArgumentException">
  		/// The bitmap's type or color depth are not supported.
  		/// </exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="scanline"/> is no valid value.
  		/// </exception>
  		public Scanline<T> GetScanline<T>(int scanline) where T : struct
  		{
  			EnsureNotDisposed();
  			return new Scanline<T>(dib, scanline);
  		}
  
  		/// <summary>
  		/// Returns an instance of <see cref="Scanline&lt;T&gt;"/>, representing the scanline
  		/// specified by <paramref name="scanline"/> of this <see cref="FreeImageBitmap"/>.
  		/// Since FreeImage bitmaps are always bottum up aligned, keep in mind that scanline 0 is the
  		/// bottom-most line of the image.
  		/// </summary>
  		/// <param name="scanline">Number of the scanline to retrieve.</param>
  		/// <returns>An instance of <see cref="Scanline&lt;T&gt;"/> representing the
  		/// <paramref name="scanline"/>th scanline.</returns>
  		/// <remarks>
  		/// List of return-types of <b>T</b>:<para/>
  		/// <list type="table">
  		/// <listheader><term>Color Depth / Type</term><description><see cref="Type">Result Type</see></description></listheader>
  		/// <item><term>1 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI1BIT"/></description></item>
  		/// <item><term>4 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI4BIT"/></description></item>
  		/// <item><term>8 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="Byte"/></description></item>
  		/// <item><term>16 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="UInt16"/></description></item>
  		/// <item><term>16 - 555 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB555"/></description></item>
  		/// <item><term>16 - 565 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB565"/></description></item>
  		/// <item><term>24 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBTRIPLE"/></description></item>
  		/// <item><term>32 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBQUAD"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_COMPLEX"/></term><description><see cref="FICOMPLEX"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_DOUBLE"/></term><description><see cref="Double"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_FLOAT"/></term><description><see cref="Single"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT16"/></term><description><see cref="Int16"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT32"/></term><description><see cref="Int32"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGB16"/></term><description><see cref="FIRGB16"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBA16"/></term><description><see cref="FIRGBA16"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBAF"/></term><description><see cref="FIRGBAF"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBF"/></term><description><see cref="FIRGBF"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT16"/></term><description><see cref="UInt16"/></description></item>
  		/// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT32"/></term><description><see cref="UInt32"/></description></item>
  		/// </list>
  		/// </remarks>
  		/// <example>
  		/// <code>
  		/// FreeImageBitmap bitmap = new FreeImageBitmap(@"C:\Pictures\picture.bmp");
  		/// if (bitmap.ColorDepth == 32)
  		/// {
  		/// 	Scanline&lt;RGBQUAD&gt; scanline = (Scanline&lt;RGBQUAD&gt;)bitmap.GetScanline(0);
  		/// 	foreach (RGBQUAD pixel in scanline)
  		/// 	{
  		///			Console.WriteLine(pixel);
  		/// 	}
  		///	}
  		/// </code>
  		/// </example>
  		/// <exception cref="ArgumentException">
  		/// The type of the bitmap or color depth are not supported.
  		/// </exception>
  		/// <exception cref="ArgumentOutOfRangeException">
  		/// <paramref name="scanline"/> is no valid value.
  		/// </exception>
  		public object GetScanline(int scanline)
  		{
  			EnsureNotDisposed();
  			object result = null;
  			int width = (int)FreeImage.GetWidth(dib);
  
  			switch (FreeImage.GetImageType(dib))
  			{
  				case FREE_IMAGE_TYPE.FIT_BITMAP:
  
  					switch (FreeImage.GetBPP(dib))
  					{
  						case 1u: result = new Scanline<FI1BIT>(dib, scanline, width); break;
  						case 4u: result = new Scanline<FI4BIT>(dib, scanline, width); break;
  						case 8u: result = new Scanline<Byte>(dib, scanline, width); break;
  						case 16u:
  							if ((RedMask == FreeImage.FI16_555_RED_MASK) &&
  								(GreenMask == FreeImage.FI16_555_GREEN_MASK) &&
  								(BlueMask == FreeImage.FI16_555_BLUE_MASK))
  							{
  								result = new Scanline<FI16RGB555>(dib, scanline, width);
  							}
  							else if ((RedMask == FreeImage.FI16_565_RED_MASK) &&
  								(GreenMask == FreeImage.FI16_565_GREEN_MASK) &&
  								(BlueMask == FreeImage.FI16_565_BLUE_MASK))
  							{
  								result = new Scanline<FI16RGB565>(dib, scanline, width);
  							}
  							else
  							{
  
gt: 								result = new Scanline<UInt16>(dib, scanline, width);