// ========================================================== // 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 { /// /// Encapsulates a FreeImage-bitmap. /// [Serializable, Guid("64a4c935-b757-499c-ab8c-6110316a9e51")] public class FreeImageBitmap : MarshalByRefObject, ICloneable, IDisposable, IEnumerable, ISerializable { #region Fields /// /// Indicates whether this instance is disposed. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] private bool disposed; /// /// Tab object. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] private object tag; /// /// Object used to syncronize lock methods. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] private object lockObject = new object(); /// /// Holds information used by SaveAdd() methods. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] private SaveInformation saveInformation = new SaveInformation(); /// /// The stream that this instance was loaded from or /// null if it has been cloned or deserialized. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] private Stream stream; /// /// True if the stream must be disposed with this /// instance. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] private bool disposeStream; /// /// The number of frames contained by a mutlipage bitmap. /// Default value is 1 and only changed if needed. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] private int frameCount = 1; /// /// The index of the loaded frame. /// Default value is 0 and only changed if needed. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] private int frameIndex = 0; /// /// Format of the sourceimage. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] private FREE_IMAGE_FORMAT originalFormat = FREE_IMAGE_FORMAT.FIF_UNKNOWN; /// /// Handle to the encapsulated FreeImage-bitmap. /// [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 /// /// Initializes a new instance of the class. /// protected FreeImageBitmap() { } /// /// Initializes a new instance of the class. /// For internal use only. /// /// The operation failed. internal protected FreeImageBitmap(FIBITMAP dib) { if (dib.IsNull) { throw new Exception(ErrorLoadingBitmap); } this.dib = dib; AddMemoryPressure(); } /// /// Initializes a new instance of the class /// bases on the specified image. /// /// The original to clone from. /// The operation failed. /// is a null reference. 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(); } /// /// Initializes a new instance of the class /// bases on the specified image with the specified size. /// /// The original to clone from. /// The Size structure that represent the /// size of the new . /// The operation failed. /// is a null reference. /// /// or are less or equal zero. /// public FreeImageBitmap(FreeImageBitmap original, Size newSize) : this(original, newSize.Width, newSize.Height) { } /// /// Initializes a new instance of the class /// bases on the specified image with the specified size. /// /// The original to clone from. /// Width of the new . /// Height of the new . /// The operation failed. /// is a null reference. /// /// or are less or equal zero. 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(); } /// /// Initializes a new instance of the class /// bases on the specified image. /// /// The original to clone from. /// /// Although this constructor supports creating images in both formats /// /// and , 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 /// . /// /// The operation failed. public FreeImageBitmap(Image original) : this(original as Bitmap) { } /// /// Initializes a new instance of the class /// bases on the specified image with the specified size. /// /// The original to clone from. /// The Size structure that represent the /// size of the new . /// /// Although this constructor supports creating images in both formats /// /// and , 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 /// . /// /// The operation failed. /// is a null reference. /// /// or are less or equal zero. /// public FreeImageBitmap(Image original, Size newSize) : this(original as Bitmap, newSize.Width, newSize.Height) { } /// /// Initializes a new instance of the class /// bases on the specified image with the specified size. /// /// The original to clone from. /// The width, in pixels, of the new . /// The height, in pixels, of the new . /// /// Although this constructor supports creating images in both formats /// /// and , 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 /// . /// /// The operation failed. /// is a null reference. /// /// or are less or equal zero. public FreeImageBitmap(Image original, int width, int height) : this(original as Bitmap, width, height) { } /// /// Initializes a new instance of the class /// bases on the specified image. /// /// The original to clone from. /// /// Although this constructor supports creating images in both formats /// /// and , 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 /// . /// /// is a null reference. /// The operation failed. 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(); } /// /// Initializes a new instance of the class /// bases on the specified image with the specified size. /// /// The original to clone from. /// The Size structure that represent the /// size of the new . /// /// Although this constructor supports creating images in both formats /// /// and , 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 /// . /// /// The operation failed. /// is a null reference. /// /// or are less or equal zero. /// public FreeImageBitmap(Bitmap original, Size newSize) : this(original, newSize.Width, newSize.Height) { } /// /// Initializes a new instance of the class /// bases on the specified image with the specified size. /// /// The original to clone from. /// The width, in pixels, of the new . /// The height, in pixels, of the new . /// /// Although this constructor supports creating images in both formats /// /// and , 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 /// . /// /// The operation failed. /// is a null reference. /// /// or are less or equal zero. 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(); } /// /// Initializes a new instance of the class /// bases on the specified stream. /// /// Stream to read from. /// Ignored. /// The operation failed. /// is a null reference. /// /// You must keep the stream open for the lifetime of the . /// public FreeImageBitmap(Stream stream, bool useIcm) : this(stream) { } /// /// Initializes a new instance of the class /// bases on the specified stream. /// /// Stream to read from. /// The operation failed. /// is a null reference. /// /// You must keep the stream open for the lifetime of the . /// public FreeImageBitmap(Stream stream) : this(stream, FREE_IMAGE_FORMAT.FIF_UNKNOWN, FREE_IMAGE_LOAD_FLAGS.DEFAULT) { } /// /// Initializes a new instance of the class /// bases on the specified stream in the specified format. /// /// Stream to read from. /// Format of the image. /// The operation failed. /// is a null reference. /// /// You must keep the stream open for the lifetime of the . /// public FreeImageBitmap(Stream stream, FREE_IMAGE_FORMAT format) : this(stream, format, FREE_IMAGE_LOAD_FLAGS.DEFAULT) { } /// /// Initializes a new instance of the class /// bases on the specified stream with the specified loading flags. /// /// Stream to read from. /// Flags to enable or disable plugin-features. /// The operation failed. /// is a null reference. /// /// You must keep the stream open for the lifetime of the . /// public FreeImageBitmap(Stream stream, FREE_IMAGE_LOAD_FLAGS flags) : this(stream, FREE_IMAGE_FORMAT.FIF_UNKNOWN, flags) { } /// /// Initializes a new instance of the class /// bases on the specified stream in the specified format /// with the specified loading flags. /// /// Stream to read from. /// Format of the image. /// Flags to enable or disable plugin-features. /// The operation failed. /// is a null reference. /// /// You must keep the stream open for the lifetime of the . /// 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); } /// /// Initializes a new instance of the class bases on the specified file. /// /// The complete name of the file to load. /// The operation failed. /// is a null reference. /// does not exist. public FreeImageBitmap(string filename) : this(filename, FREE_IMAGE_LOAD_FLAGS.DEFAULT) { } /// /// Initializes a new instance of the class bases on the specified file. /// /// The complete name of the file to load. /// Ignored. /// The operation failed. /// is a null reference. /// does not exist. public FreeImageBitmap(string filename, bool useIcm) : this(filename) { } /// /// Initializes a new instance of the class bases on the specified file /// with the specified loading flags. /// /// The complete name of the file to load. /// Flags to enable or disable plugin-features. /// The operation failed. /// is a null reference. /// does not exist. public FreeImageBitmap(string filename, FREE_IMAGE_LOAD_FLAGS flags) : this(filename, FREE_IMAGE_FORMAT.FIF_UNKNOWN, flags) { } /// /// Initializes a new instance of the class bases on the specified file /// in the specified format. /// /// The complete name of the file to load. /// Format of the image. /// The operation failed. /// is a null reference. /// does not exist. public FreeImageBitmap(string filename, FREE_IMAGE_FORMAT format) : this(filename, format, FREE_IMAGE_LOAD_FLAGS.DEFAULT) { } /// /// Initializes a new instance of the class bases on the specified file /// in the specified format with the specified loading flags. /// /// The complete name of the file to load. /// Format of the image. /// Flags to enable or disable plugin-features. /// The operation failed. /// is a null reference. /// does not exist. 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); } /// /// Initializes a new instance of the class /// bases on the specified size. /// /// The width, in pixels, of the new . /// The height, in pixels, of the new . /// The operation failed. 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(); } /// /// Initializes a new instance of the class bases on the specified resource. /// /// The class used to extract the resource. /// The name of the resource. /// The operation failed. public FreeImageBitmap(Type type, string resource) : this(type.Module.Assembly.GetManifestResourceStream(type, resource)) { } /// /// Initializes a new instance of the class bases on the specified size /// and with the resolution of the specified object. /// /// The width, in pixels, of the new . /// The height, in pixels, of the new . /// The Graphics object that specifies the resolution for the new . /// The operation failed. /// is a null reference. public FreeImageBitmap(int width, int height, Graphics g) : this(width, height) { FreeImage.SetResolutionX(dib, (uint)g.DpiX); FreeImage.SetResolutionY(dib, (uint)g.DpiY); } /// /// Initializes a new instance of the class bases on the specified size and format. /// /// The width, in pixels, of the new . /// The height, in pixels, of the new . /// The PixelFormat enumeration for the new . /// /// Although this constructor supports creating images in both formats /// /// and , 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 /// . /// /// The operation failed. /// is invalid. /// /// or are less or equal zero. 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(); } /// /// Initializes a new instance of the class bases on the specified size and type. /// Only non standard bitmaps are supported. /// /// The width, in pixels, of the new . /// The height, in pixels, of the new . /// The type of the bitmap. /// The operation failed. /// /// is FIT_BITMAP or FIT_UNKNOWN. /// is invalid. /// /// or are less or equal zero. 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(); } /// /// Initializes a new instance of the class bases on the specified size, /// pixel format and pixel data. /// /// The width, in pixels, of the new . /// The height, in pixels, of the new . /// 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.. /// The PixelFormat enumeration for the new . /// Pointer to an array of bytes that contains the pixel data. /// /// Although this constructor supports creating images in both formats /// /// and , 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 /// . /// /// The operation failed. /// is invalid. /// /// or are less or equal zero. 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(); } /// /// Initializes a new instance of the class bases on the specified size, /// pixel format and pixel data. /// /// The width, in pixels, of the new . /// The height, in pixels, of the new . /// 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.. /// The PixelFormat enumeration for the new . /// Array of bytes containing the bitmap data. /// /// Although this constructor supports creating images in both formats /// /// and , 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 /// . /// /// The operation failed. /// is invalid. /// /// or are less or equal zero. /// is null 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(); } /// /// Initializes a new instance of the class bases on the specified size, /// pixel format and pixel data. /// /// The width, in pixels, of the new . /// The height, in pixels, of the new . /// 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.. /// The color depth of the new /// The type for the new . /// Pointer to an array of bytes that contains the pixel data. /// The operation failed. /// is invalid. /// /// or are less or equal zero. 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(); } /// /// Initializes a new instance of the class bases on the specified size, /// pixel format and pixel data. /// /// The width, in pixels, of the new . /// The height, in pixels, of the new . /// 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.. /// The color depth of the new /// The type for the new . /// Array of bytes containing the bitmap data. /// The operation failed. /// is invalid. /// /// or are less or equal zero. /// is null 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(); } /// /// Initializes a new instance of the class. /// /// The operation failed. /// The operation failed. 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); } } /// /// Frees all managed and unmanaged ressources. /// ~FreeImageBitmap() { Dispose(false); } #endregion #region Operators /// /// Converts a instance to a instance. /// /// A instance. /// A new instance of initialized to . /// /// The explicit conversion from 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. /// public static explicit operator Bitmap(FreeImageBitmap value) { return value.ToBitmap(); } /// /// Converts a instance to a instance. /// /// A instance. /// A new instance of initialized to . /// /// The explicit conversion from into /// allows to create an instance on the fly to perform /// image processing operations and converting it back. /// public static explicit operator FreeImageBitmap(Bitmap value) { return new FreeImageBitmap(value); } /// /// Determines whether two specified objects have the same value. /// /// A or a null reference (Nothing in Visual Basic). /// A or a null reference (Nothing in Visual Basic). /// /// true if the value of left is the same as the value of right; otherwise, false. /// 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); } } /// /// Determines whether two specified objects have different values. /// /// A or a null reference (Nothing in Visual Basic). /// A or a null reference (Nothing in Visual Basic). /// /// true if the value of left is different from the value of right; otherwise, false. /// public static bool operator !=(FreeImageBitmap left, FreeImageBitmap right) { return (!(left == right)); } #endregion #region Properties /// /// Type of the bitmap. /// public FREE_IMAGE_TYPE ImageType { get { EnsureNotDisposed(); return FreeImage.GetImageType(dib); } } /// /// Number of palette entries. /// public int ColorsUsed { get { EnsureNotDisposed(); return (int)FreeImage.GetColorsUsed(dib); } } /// /// 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. /// public int UniqueColors { get { EnsureNotDisposed(); return FreeImage.GetUniqueColors(dib); } } /// /// The size of one pixel in the bitmap in bits. /// public int ColorDepth { get { EnsureNotDisposed(); return (int)FreeImage.GetBPP(dib); } } /// /// Width of the bitmap in pixel units. /// public int Width { get { EnsureNotDisposed(); return (int)FreeImage.GetWidth(dib); } } /// /// Height of the bitmap in pixel units. /// public int Height { get { EnsureNotDisposed(); return (int)FreeImage.GetHeight(dib); } } /// /// Returns the width of the bitmap in bytes, rounded to the next 32-bit boundary. /// public int Pitch { get { EnsureNotDisposed(); return (int)FreeImage.GetPitch(dib); } } /// /// Size of the bitmap in memory. /// public int DataSize { get { EnsureNotDisposed(); return (int)FreeImage.GetDIBSize(dib); } } /// /// Returns a structure that represents the palette of a FreeImage bitmap. /// /// is false. public Palette Palette { get { EnsureNotDisposed(); if (HasPalette) { return new Palette(dib); } throw new InvalidOperationException("This bitmap does not have a palette."); } } /// /// Gets whether the bitmap is RGB 555. /// public bool IsRGB555 { get { EnsureNotDisposed(); return FreeImage.IsRGB555(dib); } } /// /// Gets whether the bitmap is RGB 565. /// public bool IsRGB565 { get { EnsureNotDisposed(); return FreeImage.IsRGB565(dib); } } /// /// Gets the horizontal resolution, in pixels per inch, of this . /// public float HorizontalResolution { get { EnsureNotDisposed(); return (float)FreeImage.GetResolutionX(dib); } private set { EnsureNotDisposed(); FreeImage.SetResolutionX(dib, (uint)value); } } /// /// Gets the vertical resolution, in pixels per inch, of this . /// public float VerticalResolution { get { EnsureNotDisposed(); return (float)FreeImage.GetResolutionY(dib); } private set { EnsureNotDisposed(); FreeImage.SetResolutionY(dib, (uint)value); } } /// /// Returns the structure of this . /// public BITMAPINFOHEADER InfoHeader { get { EnsureNotDisposed(); return FreeImage.GetInfoHeaderEx(dib); } } /// /// Returns the structure of a this . /// public BITMAPINFO Info { get { EnsureNotDisposed(); return FreeImage.GetInfoEx(dib); } } /// /// Investigates the color type of this /// by reading the bitmaps pixel bits and analysing them. /// public FREE_IMAGE_COLOR_TYPE ColorType { get { EnsureNotDisposed(); return FreeImage.GetColorType(dib); } } /// /// Bit pattern describing the red color component of a pixel in this . /// public uint RedMask { get { EnsureNotDisposed(); return FreeImage.GetRedMask(dib); } } /// /// Bit pattern describing the green color component of a pixel in this . /// public uint GreenMask { get { EnsureNotDisposed(); return FreeImage.GetGreenMask(dib); } } /// /// Bit pattern describing the blue color component of a pixel in this . /// public uint BlueMask { get { EnsureNotDisposed(); return FreeImage.GetBlueMask(dib); } } /// /// Number of transparent colors in a palletised . /// public int TransparencyCount { get { EnsureNotDisposed(); return (int)FreeImage.GetTransparencyCount(dib); } } /// /// Get or sets transparency table of this . /// public byte[] TransparencyTable { get { EnsureNotDisposed(); return FreeImage.GetTransparencyTableEx(dib); } set { EnsureNotDisposed(); FreeImage.SetTransparencyTable(dib, value); } } /// /// Gets or sets whether this is transparent. /// public bool IsTransparent { get { EnsureNotDisposed(); return FreeImage.IsTransparent(dib); } set { EnsureNotDisposed(); FreeImage.SetTransparent(dib, value); } } /// /// Gets whether this has a file background color. /// public bool HasBackgroundColor { get { EnsureNotDisposed(); return FreeImage.HasBackgroundColor(dib); } } /// /// Gets or sets the background color of this . /// In case the value is null, the background color is removed. /// /// Get: There is no background color available. /// Set: Setting background color failed. 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."); } } } /// /// Pointer to the data-bits of this . /// public IntPtr Bits { get { EnsureNotDisposed(); return FreeImage.GetBits(dib); } } /// /// Width, in bytes, of this . /// public int Line { get { EnsureNotDisposed(); return (int)FreeImage.GetLine(dib); } } /// /// Pointer to the scanline of the top most pixel row of this . /// public IntPtr Scan0 { get { EnsureNotDisposed(); return FreeImage.GetScanLine(dib, (int)(FreeImage.GetHeight(dib) - 1)); } } /// /// Width, in bytes, of this . /// In case this is top down Stride will be positive, else negative. /// public int Stride { get { return -Line; } } /// /// Gets attribute flags for the pixel data of this . /// 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; } } /// /// Gets the width and height of this . /// public SizeF PhysicalDimension { get { EnsureNotDisposed(); return new SizeF((float)FreeImage.GetWidth(dib), (float)FreeImage.GetHeight(dib)); } } /// /// Gets the pixel format for this . /// public PixelFormat PixelFormat { get { EnsureNotDisposed(); return FreeImage.GetPixelFormat(dib); } } /// /// Gets IDs of the property items stored in this . /// public int[] PropertyIdList { get { EnsureNotDisposed(); List list = new List(); ImageMetadata metaData = new ImageMetadata(dib, true); foreach (MetadataModel metadataModel in metaData) { foreach (MetadataTag metadataTag in metadataModel) { list.Add(metadataTag.ID); } } return list.ToArray(); } } /// /// Gets all the property items (pieces of metadata) stored in this . /// public PropertyItem[] PropertyItems { get { EnsureNotDisposed(); List list = new List(); ImageMetadata metaData = new ImageMetadata(dib, true); foreach (MetadataModel metadataModel in metaData) { foreach (MetadataTag metadataTag in metadataModel) { list.Add(metadataTag.GetPropertyItem()); } } return list.ToArray(); } } /// /// Gets the format of this . /// 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)); } } /// /// Gets the width and height, in pixels, of this . /// public Size Size { get { EnsureNotDisposed(); return new Size(Width, Height); } } /// /// Gets or sets an object that provides additional data about the . /// public Object Tag { get { EnsureNotDisposed(); return tag; } set { EnsureNotDisposed(); tag = value; } } /// /// Gets whether this has been disposed. /// public bool IsDisposed { get { return disposed; } } /// /// Gets a new instance of a metadata representing class. /// public ImageMetadata Metadata { get { EnsureNotDisposed(); return new ImageMetadata(dib, true); } } /// /// Gets or sets the comment of this . /// Supported formats are JPEG, PNG and GIF. /// public string Comment { get { EnsureNotDisposed(); return FreeImage.GetImageComment(dib); } set { EnsureNotDisposed(); FreeImage.SetImageComment(dib, value); } } /// /// Returns whether this has a palette. /// public bool HasPalette { get { EnsureNotDisposed(); return (FreeImage.GetPalette(dib) != IntPtr.Zero); } } /// /// Gets or sets the entry used as transparent color in this . /// Only works for 1-, 4- and 8-bpp. /// public int TransparentIndex { get { EnsureNotDisposed(); return FreeImage.GetTransparentIndex(dib); } set { EnsureNotDisposed(); FreeImage.SetTransparentIndex(dib, value); } } /// /// Gets the number of frames in this . /// public int FrameCount { get { EnsureNotDisposed(); return frameCount; } } /// /// Gets the ICCProfile structure of this . /// public FIICCPROFILE ICCProfile { get { EnsureNotDisposed(); return FreeImage.GetICCProfileEx(dib); } } /// /// Gets the format of the original image in case /// this was loaded from a file or stream. /// public FREE_IMAGE_FORMAT ImageFormat { get { EnsureNotDisposed(); return originalFormat; } } /// /// Gets the encapsulated FIBITMAP. /// internal FIBITMAP Dib { get { EnsureNotDisposed(); return dib; } } #endregion #region Methods /// /// Gets the bounds of this in the specified unit. /// /// One of the values indicating /// the unit of measure for the bounding rectangle. /// The that represents the bounds of this /// , in the specified unit. public RectangleF GetBounds(ref GraphicsUnit pageUnit) { EnsureNotDisposed(); pageUnit = GraphicsUnit.Pixel; return new RectangleF( 0f, 0f, (float)FreeImage.GetWidth(dib), (float)FreeImage.GetHeight(dib)); } /// /// Gets the specified property item from this . /// /// The ID of the property item to get. /// The this method gets. 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; } /// /// Returns a thumbnail for this . /// /// The width, in pixels, of the requested thumbnail image. /// The height, in pixels, of the requested thumbnail image. /// Ignored. /// Ignored. /// A that represents the thumbnail. 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; } /// /// Returns a thumbnail for this , keeping aspect ratio. /// defines the maximum width or height /// of the thumbnail. /// /// Thumbnail square size. /// When true HDR images are transperantly /// converted to standard images. /// The thumbnail in a new instance. 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; } /// /// Converts this instance to a instance. /// /// A new instance of initialized this instance. public Bitmap ToBitmap() { EnsureNotDisposed(); return FreeImage.GetBitmap(dib, true); } /// /// Returns an instance of , representing the scanline /// specified by of this . /// Since FreeImage bitmaps are always bottum up aligned, keep in mind that scanline 0 is the /// bottom-most line of the image. /// /// Number of the scanline to retrieve. /// An instance of representing the /// th scanline. /// /// List of return-types of T: /// /// Color Depth / TypeResult Type /// 1 () /// 4 () /// 8 () /// 16 () /// 16 - 555 () /// 16 - 565 () /// 24 () /// 32 () /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// FreeImageBitmap bitmap = new FreeImageBitmap(@"C:\Pictures\picture.bmp"); /// if (bitmap.ColorDepth == 32) /// { /// Scanline<RGBQUAD> scanline = bitmap.GetScanline<RGBQUAD>(0); /// foreach (RGBQUAD pixel in scanline) /// { /// Console.WriteLine(pixel); /// } /// } /// /// /// /// The bitmap's type or color depth are not supported. /// /// /// is no valid value. /// public Scanline GetScanline(int scanline) where T : struct { EnsureNotDisposed(); return new Scanline(dib, scanline); } /// /// Returns an instance of , representing the scanline /// specified by of this . /// Since FreeImage bitmaps are always bottum up aligned, keep in mind that scanline 0 is the /// bottom-most line of the image. /// /// Number of the scanline to retrieve. /// An instance of representing the /// th scanline. /// /// List of return-types of T: /// /// Color Depth / TypeResult Type /// 1 () /// 4 () /// 8 () /// 16 () /// 16 - 555 () /// 16 - 565 () /// 24 () /// 32 () /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// FreeImageBitmap bitmap = new FreeImageBitmap(@"C:\Pictures\picture.bmp"); /// if (bitmap.ColorDepth == 32) /// { /// Scanline<RGBQUAD> scanline = (Scanline<RGBQUAD>)bitmap.GetScanline(0); /// foreach (RGBQUAD pixel in scanline) /// { /// Console.WriteLine(pixel); /// } /// } /// /// /// /// The type of the bitmap or color depth are not supported. /// /// /// is no valid value. /// 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(dib, scanline, width); break; case 4u: result = new Scanline(dib, scanline, width); break; case 8u: result = new Scanline(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(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(dib, scanline, width); } else { result = new Scanline(dib, scanline, width); } break; case 24u: result = new Scanline(dib, scanline, width); break; case 32u: result = new Scanline(dib, scanline, width); break; default: throw new ArgumentException("Color depth is not supported."); } break; case FREE_IMAGE_TYPE.FIT_COMPLEX: result = new Scanline(dib, scanline, width); break; case FREE_IMAGE_TYPE.FIT_DOUBLE: result = new Scanline(dib, scanline, width); break; case FREE_IMAGE_TYPE.FIT_FLOAT: result = new Scanline(dib, scanline, width); break; case FREE_IMAGE_TYPE.FIT_INT16: result = new Scanline(dib, scanline, width); break; case FREE_IMAGE_TYPE.FIT_INT32: result = new Scanline(dib, scanline, width); break; case FREE_IMAGE_TYPE.FIT_RGB16: result = new Scanline(dib, scanline, width); break; case FREE_IMAGE_TYPE.FIT_RGBA16: result = new Scanline(dib, scanline, width); break; case FREE_IMAGE_TYPE.FIT_RGBAF: result = new Scanline(dib, scanline, width); break; case FREE_IMAGE_TYPE.FIT_RGBF: result = new Scanline(dib, scanline, width); break; case FREE_IMAGE_TYPE.FIT_UINT16: result = new Scanline(dib, scanline, width); break; case FREE_IMAGE_TYPE.FIT_UINT32: result = new Scanline(dib, scanline, width); break; case FREE_IMAGE_TYPE.FIT_UNKNOWN: default: throw new ArgumentException("Type is not supported."); } return result; } /// /// Returns a pointer to the specified scanline. /// Due to FreeImage bitmaps are bottum up, /// scanline 0 is the most bottom line of the image. /// /// Number of the scanline. /// Pointer to the scanline. public IntPtr GetScanlinePointer(int scanline) { EnsureNotDisposed(); return FreeImage.GetScanLine(dib, scanline); } /// /// Returns a list of structures, representing the scanlines of this . /// Due to FreeImage bitmaps are bottum up, scanline 0 is the /// bottom-most line of the image. /// Each color depth has a different representing structure due to different memory layouts. /// /// /// List of return-types of T: /// /// Color Depth / TypeResult Type of IEnmuerable<Scanline<T>> /// 1 () /// 4 () /// 8 () /// 16 () /// 16 - 555 () /// 16 - 565 () /// 24 () /// 32 () /// /// /// /// /// /// /// /// /// /// /// /// /// public IList GetScanlines() { EnsureNotDisposed(); int height = (int)FreeImage.GetHeight(dib); IList list; switch (FreeImage.GetImageType(dib)) { case FREE_IMAGE_TYPE.FIT_BITMAP: switch (FreeImage.GetBPP(dib)) { case 1u: list = new List>(height); break; case 4u: list = new List>(height); break; case 8u: list = new List>(height); break; case 16u: if (FreeImage.IsRGB555(dib)) { list = new List>(height); } else if (FreeImage.IsRGB565(dib)) { list = new List>(height); } else { list = new List>(height); } break; case 24u: list = new List>(height); break; case 32u: list = new List>(height); break; default: throw new ArgumentException("Color depth is not supported."); } break; case FREE_IMAGE_TYPE.FIT_COMPLEX: list = new List>(height); break; case FREE_IMAGE_TYPE.FIT_DOUBLE: list = new List>(height); break; case FREE_IMAGE_TYPE.FIT_FLOAT: list = new List>(height); break; case FREE_IMAGE_TYPE.FIT_INT16: list = new List>(height); break; case FREE_IMAGE_TYPE.FIT_INT32: list = new List>(height); break; case FREE_IMAGE_TYPE.FIT_RGB16: list = new List>(height); break; case FREE_IMAGE_TYPE.FIT_RGBA16: list = new List>(height); break; case FREE_IMAGE_TYPE.FIT_RGBAF: list = new List>(height); break; case FREE_IMAGE_TYPE.FIT_RGBF: list = new List>(height); break; case FREE_IMAGE_TYPE.FIT_UINT16: list = new List>(height); break; case FREE_IMAGE_TYPE.FIT_UINT32: list = new List>(height); break; case FREE_IMAGE_TYPE.FIT_UNKNOWN: default: throw new ArgumentException("Type is not supported."); } for (int i = 0; i < height; i++) { list.Add(GetScanline(i)); } return list; } /// /// Removes the specified property item from this . /// /// The ID of the property item to remove. public void RemovePropertyItem(int propid) { EnsureNotDisposed(); ImageMetadata mdata = new ImageMetadata(dib, true); foreach (MetadataModel model in mdata) { foreach (MetadataTag tag in model) { if (tag.ID == propid) { model.RemoveTag(tag.Key); return; } } } } /// /// This method rotates, flips, or rotates and flips this . /// /// A RotateFlipType member /// that specifies the type of rotation and flip to apply to this . public void RotateFlip(RotateFlipType rotateFlipType) { EnsureNotDisposed(); FIBITMAP newDib = new FIBITMAP(); uint bpp = FreeImage.GetBPP(dib); switch (rotateFlipType) { case RotateFlipType.RotateNoneFlipX: FreeImage.FlipHorizontal(dib); break; case RotateFlipType.RotateNoneFlipY: FreeImage.FlipVertical(dib); break; case RotateFlipType.RotateNoneFlipXY: FreeImage.FlipHorizontal(dib); FreeImage.FlipVertical(dib); break; case RotateFlipType.Rotate90FlipNone: newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d); break; case RotateFlipType.Rotate90FlipX: newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d); FreeImage.FlipHorizontal(newDib); break; case RotateFlipType.Rotate90FlipY: newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d); FreeImage.FlipVertical(newDib); break; case RotateFlipType.Rotate90FlipXY: newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d); FreeImage.FlipHorizontal(newDib); FreeImage.FlipVertical(newDib); break; case RotateFlipType.Rotate180FlipXY: newDib = FreeImage.Clone(dib); break; } ReplaceDib(newDib); } /// /// Copies the metadata from another . /// /// The bitmap to read the metadata from. /// /// is a null reference. /// public void CloneMetadataFrom(FreeImageBitmap bitmap) { if (bitmap == null) { throw new ArgumentNullException("bitmap"); } EnsureNotDisposed(); bitmap.EnsureNotDisposed(); FreeImage.CloneMetadata(dib, bitmap.dib); } /// /// Copies the metadata from another using /// the provided options. /// /// The bitmap to read the metadata from. /// Specifies the way the metadata is copied. /// /// is a null reference. /// public void CloneMetadataFrom(FreeImageBitmap bitmap, FREE_IMAGE_METADATA_COPY flags) { if (bitmap == null) { throw new ArgumentNullException("bitmap"); } EnsureNotDisposed(); bitmap.EnsureNotDisposed(); FreeImage.CloneMetadataEx(bitmap.dib, dib, flags); } /// /// Saves this to the specified file. /// /// A string that contains the name of the file to which /// to save this . /// is null or empty. /// Saving the image failed. public void Save(string filename) { Save(filename, FREE_IMAGE_FORMAT.FIF_UNKNOWN, FREE_IMAGE_SAVE_FLAGS.DEFAULT); } /// /// Saves this to the specified file in the specified format. /// /// A string that contains the name of the file to which /// to save this . /// An that specifies the format of the saved image. /// is null or empty. /// Saving the image failed. public void Save(string filename, FREE_IMAGE_FORMAT format) { Save(filename, format, FREE_IMAGE_SAVE_FLAGS.DEFAULT); } /// /// Saves this to the specified file in the specified format /// using the specified saving flags. /// /// A string that contains the name of the file to which /// to save this . /// An that specifies the format of the saved image. /// Flags to enable or disable plugin-features. /// is null or empty. /// Saving the image failed. public void Save(string filename, FREE_IMAGE_FORMAT format, FREE_IMAGE_SAVE_FLAGS flags) { EnsureNotDisposed(); if (string.IsNullOrEmpty(filename)) { throw new ArgumentException("filename"); } if (!FreeImage.SaveEx(dib, filename, format, flags)) { throw new Exception("Unable to save bitmap"); } saveInformation.filename = filename; saveInformation.format = format; saveInformation.saveFlags = flags; } /// /// Saves this to the specified stream in the specified format. /// /// The stream where this will be saved. /// An that specifies the format of the saved image. /// is a null reference. /// Saving the image failed. public void Save(Stream stream, FREE_IMAGE_FORMAT format) { Save(stream, format, FREE_IMAGE_SAVE_FLAGS.DEFAULT); } /// /// Saves this to the specified stream in the specified format /// using the specified saving flags. /// /// The stream where this will be saved. /// An that specifies the format of the saved image. /// Flags to enable or disable plugin-features. /// is a null reference. /// Saving the image failed. public void Save(Stream stream, FREE_IMAGE_FORMAT format, FREE_IMAGE_SAVE_FLAGS flags) { EnsureNotDisposed(); if (stream == null) { throw new ArgumentNullException("stream"); } if (!FreeImage.SaveToStream(dib, stream, format, flags)) { throw new Exception("Unable to save bitmap"); } saveInformation.filename = null; } /// /// Adds a frame to the file specified in a previous call to the /// method. /// /// /// This instance has not been saved to a file using Save(...) before. public void SaveAdd() { SaveAdd(this); } /// /// Adds a frame to the file specified in a previous call to the method. /// /// The position at which the frame should be inserted. /// /// This instance has not yet been saved to a file using the Save(...) method. /// is out of range. public void SaveAdd(int insertPosition) { SaveAdd(this, insertPosition); } /// /// Adds a frame to the file specified in a previous call to the method. /// /// A that contains the frame to add. /// /// This instance has not yet been saved to a file using the Save(...) method. public void SaveAdd(FreeImageBitmap bitmap) { if (saveInformation.filename == null) { throw new InvalidOperationException("This operation requires a previous call of Save()."); } SaveAdd( saveInformation.filename, bitmap, saveInformation.format, saveInformation.loadFlags, saveInformation.saveFlags); } /// /// Adds a frame to the file specified in a previous call to the method. /// /// A that contains the frame to add. /// The position at which the frame should be inserted. /// /// This instance has not yet been saved to a file using the Save(...) method. /// is out of range. public void SaveAdd(FreeImageBitmap bitmap, int insertPosition) { if (saveInformation.filename == null) { throw new InvalidOperationException("This operation requires a previous call of Save()."); } SaveAdd( saveInformation.filename, bitmap, insertPosition, saveInformation.format, saveInformation.loadFlags, saveInformation.saveFlags); } /// /// Adds a frame to the file specified. /// /// File to add this frame to. /// is a null reference. /// does not exist. /// Saving the image has failed. public void SaveAdd(string filename) { SaveAdd( filename, this, FREE_IMAGE_FORMAT.FIF_UNKNOWN, FREE_IMAGE_LOAD_FLAGS.DEFAULT, FREE_IMAGE_SAVE_FLAGS.DEFAULT); } /// /// Adds a frame to the file specified. /// /// File to add this frame to. /// The position at which the frame should be inserted. /// is a null reference. /// does not exist. /// Saving the image has failed. /// is out of range. public void SaveAdd(string filename, int insertPosition) { SaveAdd( filename, this, insertPosition, FREE_IMAGE_FORMAT.FIF_UNKNOWN, FREE_IMAGE_LOAD_FLAGS.DEFAULT, FREE_IMAGE_SAVE_FLAGS.DEFAULT); } /// /// Adds a frame to the file specified using the specified parameters. /// /// File to add this frame to. /// Format of the image. /// Flags to enable or disable plugin-features. /// Flags to enable or disable plugin-features. /// is a null reference. /// does not exist. /// Saving the image has failed. public void SaveAdd( string filename, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS loadFlags, FREE_IMAGE_SAVE_FLAGS saveFlags) { SaveAdd( filename, this, format, loadFlags, saveFlags); } /// /// Adds a frame to the file specified using the specified parameters. /// /// File to add this frame to. /// The position at which the frame should be inserted. /// Format of the image. /// Flags to enable or disable plugin-features. /// Flags to enable or disable plugin-features. /// is a null reference. /// does not exist. /// Saving the image has failed. /// is out of range. public void SaveAdd( string filename, int insertPosition, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS loadFlags, FREE_IMAGE_SAVE_FLAGS saveFlags) { SaveAdd( filename, this, insertPosition, format, loadFlags, saveFlags); } /// /// Selects the frame specified by the index. /// /// The index of the active frame. /// /// is out of range. /// The operation failed. /// The source of the bitmap is not available. /// public void SelectActiveFrame(int frameIndex) { EnsureNotDisposed(); if ((frameIndex < 0) || (frameIndex >= frameCount)) { throw new ArgumentOutOfRangeException("frameIndex"); } if (frameIndex != this.frameIndex) { if (stream == null) { throw new InvalidOperationException("No source available."); } FREE_IMAGE_FORMAT format = originalFormat; FIMULTIBITMAP mdib = FreeImage.OpenMultiBitmapFromStream(stream, ref format, saveInformation.loadFlags); if (mdib.IsNull) throw new Exception(ErrorLoadingBitmap); try { if (frameIndex >= FreeImage.GetPageCount(mdib)) { throw new ArgumentOutOfRangeException("frameIndex"); } FIBITMAP newDib = FreeImage.LockPage(mdib, frameIndex); if (newDib.IsNull) { throw new Exception(ErrorLoadingFrame); } try { FIBITMAP clone = FreeImage.Clone(newDib); if (clone.IsNull) { throw new Exception(ErrorCreatingBitmap); } ReplaceDib(clone); } finally { if (!newDib.IsNull) { FreeImage.UnlockPage(mdib, newDib, false); } } } finally { if (!FreeImage.CloseMultiBitmapEx(ref mdib)) { throw new Exception(ErrorUnloadBitmap); } } this.frameIndex = frameIndex; } } /// /// Creates a GDI bitmap object from this . /// /// A handle to the GDI bitmap object that this method creates. public IntPtr GetHbitmap() { EnsureNotDisposed(); return FreeImage.GetHbitmap(dib, IntPtr.Zero, false); } /// /// Creates a GDI bitmap object from this . /// /// A structure that specifies the background color. /// This parameter is ignored if the bitmap is totally opaque. /// A handle to the GDI bitmap object that this method creates. public IntPtr GetHbitmap(Color background) { EnsureNotDisposed(); using (FreeImageBitmap temp = new FreeImageBitmap(this)) { temp.BackgroundColor = background; return temp.GetHbitmap(); } } /// /// Returns the handle to an icon. /// /// A Windows handle to an icon with the same image as this . public IntPtr GetHicon() { EnsureNotDisposed(); using (Bitmap bitmap = FreeImage.GetBitmap(dib, true)) { return bitmap.GetHicon(); } } /// /// Creates a GDI bitmap object from this with the same /// color depth as the primary device. /// /// A handle to the GDI bitmap object that this method creates. public IntPtr GetHbitmapForDevice() { EnsureNotDisposed(); return FreeImage.GetBitmapForDevice(dib, IntPtr.Zero, false); } /// /// Gets the of the specified pixel in this . /// /// The x-coordinate of the pixel to retrieve. /// The y-coordinate of the pixel to retrieve. /// A structure that represents the color of the specified pixel. /// The operation failed. /// The type of this bitmap is not supported. public unsafe Color GetPixel(int x, int y) { EnsureNotDisposed(); if (FreeImage.GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP) { if (ColorDepth == 16 || ColorDepth == 24 || ColorDepth == 32) { RGBQUAD rgbq; if (!FreeImage.GetPixelColor(dib, (uint)x, (uint)y, out rgbq)) { throw new Exception("FreeImage.GetPixelColor() failed"); } return rgbq.Color; } else if (ColorDepth == 1 || ColorDepth == 4 || ColorDepth == 8) { byte index; if (!FreeImage.GetPixelIndex(dib, (uint)x, (uint)y, out index)) { throw new Exception("FreeImage.GetPixelIndex() failed"); } RGBQUAD* palette = (RGBQUAD*)FreeImage.GetPalette(dib); return palette[index].Color; } } throw new NotSupportedException("The type of the image is not supported"); } /// /// Makes the default transparent color transparent for this . /// public void MakeTransparent() { EnsureNotDisposed(); MakeTransparent(Color.Transparent); } /// /// Makes the specified color transparent for this . /// /// The structure that represents /// the color to make transparent. /// /// This method is not implemented. public void MakeTransparent(Color transparentColor) { EnsureNotDisposed(); throw new System.NotImplementedException(); } /// /// Sets the of the specified pixel in this . /// /// The x-coordinate of the pixel to set. /// The y-coordinate of the pixel to set. /// A structure that represents the color /// to assign to the specified pixel. /// The operation failed. /// The type of this bitmap is not supported. public unsafe void SetPixel(int x, int y, Color color) { EnsureNotDisposed(); if (FreeImage.GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP) { if (ColorDepth == 16 || ColorDepth == 24 || ColorDepth == 32) { RGBQUAD rgbq = color; if (!FreeImage.SetPixelColor(dib, (uint)x, (uint)y, ref rgbq)) { throw new Exception("FreeImage.SetPixelColor() failed"); } return; } else if (ColorDepth == 1 || ColorDepth == 4 || ColorDepth == 8) { uint colorsUsed = FreeImage.GetColorsUsed(dib); RGBQUAD* palette = (RGBQUAD*)FreeImage.GetPalette(dib); for (int i = 0; i < colorsUsed; i++) { if (palette[i].Color == color) { byte index = (byte)i; if (!FreeImage.SetPixelIndex(dib, (uint)x, (uint)y, ref index)) { throw new Exception("FreeImage.SetPixelIndex() failed"); } return; } } throw new ArgumentOutOfRangeException("color"); } } throw new NotSupportedException("The type of the image is not supported"); } /// /// Sets the resolution for this . /// /// The horizontal resolution, in dots per inch, of this . /// The vertical resolution, in dots per inch, of this . public void SetResolution(float xDpi, float yDpi) { EnsureNotDisposed(); FreeImage.SetResolutionX(dib, (uint)xDpi); FreeImage.SetResolutionY(dib, (uint)yDpi); } /// /// This function is not yet implemented. /// /// /// This method is not implemented. public BitmapData LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format) { throw new NotImplementedException(); } /// /// This function is not yet implemented. /// /// /// This method is not implemented. public BitmapData LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData) { throw new NotImplementedException(); } /// /// This function is not yet implemented. /// /// /// This method is not implemented. public void UnlockBits(BitmapData bitmapdata) { throw new NotImplementedException(); } /// /// Converts this into a different color depth. /// The parameter specifies color depth, greyscale conversion /// and palette reorder. /// Adding the flag /// will first perform a convesion to greyscale. This can be done with any target /// color depth. /// Adding the flag /// will allow the algorithm to reorder the palette. This operation will not be performed to /// non-greyscale images to prevent data loss by mistake. /// /// A bitfield containing information about the conversion /// to perform. /// Returns true on success, false on failure. public bool ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH bpp) { EnsureNotDisposed(); return ReplaceDib(FreeImage.ConvertColorDepth(dib, bpp, false)); } /// /// Converts this to /// initializing a new instance. /// In case source and destination type are the same, the operation fails. /// An error message can be catched using the 'Message' event. /// /// Destination type. /// True to scale linear, else false. /// Returns true on success, false on failure. public bool ConvertType(FREE_IMAGE_TYPE type, bool scaleLinear) { EnsureNotDisposed(); return (ImageType == type) ? false : ReplaceDib(FreeImage.ConvertToType(dib, type, scaleLinear)); } /// /// Converts this to . /// In case source and destination type are the same, the operation fails. /// An error message can be catched using the 'Message' event. /// /// Destination type. /// True to scale linear, else false. /// The converted instance. public FreeImageBitmap GetTypeConvertedInstance(FREE_IMAGE_TYPE type, bool scaleLinear) { EnsureNotDisposed(); FreeImageBitmap result = null; if (ImageType != type) { FIBITMAP newDib = FreeImage.ConvertToType(dib, type, scaleLinear); if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } } return result; } /// /// Converts this into a different color depth initializing /// a new instance. /// The parameter specifies color depth, greyscale conversion /// and palette reorder. /// Adding the flag will /// first perform a convesion to greyscale. This can be done with any target color depth. /// Adding the flag will /// allow the algorithm to reorder the palette. This operation will not be performed to /// non-greyscale images to prevent data loss by mistake. /// /// A bitfield containing information about the conversion /// to perform. /// The converted instance. public FreeImageBitmap GetColorConvertedInstance(FREE_IMAGE_COLOR_DEPTH bpp) { EnsureNotDisposed(); FreeImageBitmap result = null; FIBITMAP newDib = FreeImage.ConvertColorDepth(dib, bpp, false); if (newDib == dib) { newDib = FreeImage.Clone(dib); } if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } return result; } /// /// Rescales this to the specified size using the /// specified filter. /// /// The Size structure that represent the /// size of the new . /// Filter to use for resizing. /// Returns true on success, false on failure. public bool Rescale(Size newSize, FREE_IMAGE_FILTER filter) { return Rescale(newSize.Width, newSize.Height, filter); } /// /// Rescales this to the specified size using the /// specified filter. /// /// Width of the new . /// Height of the new . /// Filter to use for resizing. /// Returns true on success, false on failure. public bool Rescale(int width, int height, FREE_IMAGE_FILTER filter) { EnsureNotDisposed(); return ReplaceDib(FreeImage.Rescale(dib, width, height, filter)); } /// /// Rescales this to the specified size using the /// specified filter initializing a new instance. /// /// The Size structure that represent the /// size of the new . /// Filter to use for resizing. /// The rescaled instance. public FreeImageBitmap GetScaledInstance(Size newSize, FREE_IMAGE_FILTER filter) { return GetScaledInstance(newSize.Width, newSize.Height, filter); } /// /// Rescales this to the specified size using the /// specified filter initializing a new instance. /// /// Width of the new . /// Height of the new . /// Filter to use for resizing. /// The rescaled instance. public FreeImageBitmap GetScaledInstance(int width, int height, FREE_IMAGE_FILTER filter) { EnsureNotDisposed(); FreeImageBitmap result = null; FIBITMAP newDib = FreeImage.Rescale(dib, width, height, filter); if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } return result; } /// /// Enlarges or shrinks this selectively per side and fills /// newly added areas with the specified background color. /// See for further details. /// /// The type of the specified color. /// The number of pixels, the image should be enlarged on its left side. /// Negative values shrink the image on its left side. /// The number of pixels, the image should be enlarged on its top side. /// Negative values shrink the image on its top side. /// The number of pixels, the image should be enlarged on its right side. /// Negative values shrink the image on its right side. /// The number of pixels, the image should be enlarged on its bottom side. /// Negative values shrink the image on its bottom side. /// The color, the enlarged sides of the image should be filled with. /// true on success, false on failure. public bool EnlargeCanvas(int left, int top, int right, int bottom, T? color) where T : struct { return EnlargeCanvas(left, top, right, bottom, color, FREE_IMAGE_COLOR_OPTIONS.FICO_DEFAULT); } /// /// Enlarges or shrinks this selectively per side and fills /// newly added areas with the specified background color. /// See for further details. /// /// The type of the specified color. /// The number of pixels, the image should be enlarged on its left side. /// Negative values shrink the image on its left side. /// The number of pixels, the image should be enlarged on its top side. /// Negative values shrink the image on its top side. /// The number of pixels, the image should be enlarged on its right side. /// Negative values shrink the image on its right side. /// The number of pixels, the image should be enlarged on its bottom side. /// Negative values shrink the image on its bottom side. /// The color, the enlarged sides of the image should be filled with. /// Options that affect the color search process for palletized images. /// true on success, false on failure. public bool EnlargeCanvas(int left, int top, int right, int bottom, T? color, FREE_IMAGE_COLOR_OPTIONS options) where T : struct { EnsureNotDisposed(); return ReplaceDib(FreeImage.EnlargeCanvas(dib, left, top, right, bottom, color, options)); } /// /// Enlarges or shrinks this selectively per side and fills /// newly added areas with the specified background color returning a new instance. /// See for further details. /// /// The type of the specified color. /// The number of pixels, the image should be enlarged on its left side. /// Negative values shrink the image on its left side. /// The number of pixels, the image should be enlarged on its top side. /// Negative values shrink the image on its top side. /// The number of pixels, the image should be enlarged on its right side. /// Negative values shrink the image on its right side. /// The number of pixels, the image should be enlarged on its bottom side. /// Negative values shrink the image on its bottom side. /// The color, the enlarged sides of the image should be filled with. /// The enlarged instance. public FreeImageBitmap GetEnlargedInstance(int left, int top, int right, int bottom, T? color) where T : struct { return GetEnlargedInstance(left, top, right, bottom, color, FREE_IMAGE_COLOR_OPTIONS.FICO_DEFAULT); } /// /// Enlarges or shrinks this selectively per side and fills /// newly added areas with the specified background color returning a new instance. /// See for further details. /// /// The type of the specified color. /// The number of pixels, the image should be enlarged on its left side. /// Negative values shrink the image on its left side. /// The number of pixels, the image should be enlarged on its top side. /// Negative values shrink the image on its top side. /// The number of pixels, the image should be enlarged on its right side. /// Negative values shrink the image on its right side. /// The number of pixels, the image should be enlarged on its bottom side. /// Negative values shrink the image on its bottom side. /// The color, the enlarged sides of the image should be filled with. /// Options that affect the color search process for palletized images. /// The enlarged instance. public FreeImageBitmap GetEnlargedInstance(int left, int top, int right, int bottom, T? color, FREE_IMAGE_COLOR_OPTIONS options) where T : struct { EnsureNotDisposed(); FreeImageBitmap result = null; FIBITMAP newDib = FreeImage.EnlargeCanvas(dib, left, top, right, bottom, color, options); if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } return result; } /// /// Quantizes this from 24 bit to 8bit creating a new /// palette with the specified using the specified /// . /// /// The color reduction algorithm to be used. /// Size of the desired output palette. /// Returns true on success, false on failure. public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize) { return Quantize(algorithm, paletteSize, 0, (RGBQUAD[])null); } /// /// Quantizes this from 24 bit to 8bit creating a new /// palette with the specified using the specified /// and the specified /// palette up to the /// specified length. /// /// The color reduction algorithm to be used. /// Size of the desired output palette. /// The provided palette. /// Returns true on success, false on failure. public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, Palette reservePalette) { return Quantize(algorithm, paletteSize, reservePalette.Length, reservePalette.Data); } /// /// Quantizes this from 24 bit to 8bit creating a new /// palette with the specified using the specified /// and the specified /// palette up to the /// specified length. /// /// The color reduction algorithm to be used. /// Size of the desired output palette. /// Size of the provided palette of ReservePalette. /// The provided palette. /// Returns true on success, false on failure. public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, Palette reservePalette) { return Quantize(algorithm, paletteSize, reserveSize, reservePalette.Data); } /// /// Quantizes this from 24 bit to 8bit creating a new /// palette with the specified using the specified /// and the specified /// palette up to the /// specified length. /// /// The color reduction algorithm to be used. /// Size of the desired output palette. /// Size of the provided palette of ReservePalette. /// The provided palette. /// Returns true on success, false on failure. public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, RGBQUAD[] reservePalette) { EnsureNotDisposed(); return ReplaceDib(FreeImage.ColorQuantizeEx(dib, algorithm, paletteSize, reserveSize, reservePalette)); } /// /// Quantizes this from 24 bit, using the specified /// initializing a new 8 bit instance with the /// specified . /// /// The color reduction algorithm to be used. /// Size of the desired output palette. /// The quantized instance. public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize) { return GetQuantizedInstance(algorithm, paletteSize, 0, (RGBQUAD[])null); } /// /// Quantizes this from 24 bit, using the specified /// and palette /// initializing a new 8 bit instance with the specified . /// /// The color reduction algorithm to be used. /// Size of the desired output palette. /// The provided palette. /// The quantized instance. public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, Palette reservePalette) { return GetQuantizedInstance(algorithm, paletteSize, reservePalette.Length, reservePalette); } /// /// Quantizes this from 24 bit, using the specified /// and up to /// entries from palette initializing /// a new 8 bit instance with the specified . /// /// The color reduction algorithm to be used. /// Size of the desired output palette. /// Size of the provided palette. /// The provided palette. /// The quantized instance. public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, Palette reservePalette) { return GetQuantizedInstance(algorithm, paletteSize, reserveSize, reservePalette.Data); } /// /// Quantizes this from 24 bit, using the specified /// and up to /// entries from palette initializing /// a new 8 bit instance with the specified . /// /// The color reduction algorithm to be used. /// Size of the desired output palette. /// Size of the provided palette. /// The provided palette. /// The quantized instance. public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, RGBQUAD[] reservePalette) { EnsureNotDisposed(); FreeImageBitmap result = null; FIBITMAP newDib = FreeImage.ColorQuantizeEx(dib, algorithm, paletteSize, reserveSize, reservePalette); if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } return result; } /// /// Converts a High Dynamic Range image to a 24-bit RGB image using a global /// operator based on logarithmic compression of luminance values, imitating /// the human response to light. /// /// A gamma correction that is applied after the tone mapping. /// A value of 1 means no correction. /// Scale factor allowing to adjust the brightness of the output image. /// Returns true on success, false on failure. public bool TmoDrago03(double gamma, double exposure) { EnsureNotDisposed(); return ReplaceDib(FreeImage.TmoDrago03(dib, gamma, exposure)); } /// /// Converts a High Dynamic Range image to a 24-bit RGB image using a global operator inspired /// by photoreceptor physiology of the human visual system. /// /// Controls the overall image intensity in the range [-8, 8]. /// Controls the overall image contrast in the range [0.3, 1.0[. /// Returns true on success, false on failure. public bool TmoReinhard05(double intensity, double contrast) { EnsureNotDisposed(); return ReplaceDib(FreeImage.TmoReinhard05(dib, intensity, contrast)); } /// /// Apply the Gradient Domain High Dynamic Range Compression to a RGBF image and convert to 24-bit RGB. /// /// Color saturation (s parameter in the paper) in [0.4..0.6] /// Atenuation factor (beta parameter in the paper) in [0.8..0.9] /// Returns true on success, false on failure. public bool TmoFattal02(double color_saturation, double attenuation) { EnsureNotDisposed(); return ReplaceDib(FreeImage.TmoFattal02(dib, color_saturation, attenuation)); } /// /// This method rotates a 1-, 4-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears. /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer /// multiple of 90. /// /// The angle of rotation. /// Returns true on success, false on failure. public bool Rotate(double angle) { EnsureNotDisposed(); bool result = false; if (ColorDepth == 4) { result = ReplaceDib(FreeImage.Rotate4bit(dib, angle)); } else { result = ReplaceDib(FreeImage.Rotate(dib, angle)); } return result; } /// /// This method rotates a 1-, 4-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears. /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer /// multiple of 90. /// /// The type of the color to use as background. /// The angle of rotation. /// The color used used to fill the bitmap's background. /// Returns true on success, false on failure. public bool Rotate(double angle, T? backgroundColor) where T : struct { EnsureNotDisposed(); bool result = false; if (ColorDepth == 4) { result = ReplaceDib(FreeImage.Rotate4bit(dib, angle)); } else { result = ReplaceDib(FreeImage.Rotate(dib, angle, backgroundColor)); } return result; } /// /// Rotates this by the specified angle initializing a new instance. /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer /// multiple of 90. /// /// The type of the color to use as background. /// The angle of rotation. /// The color used used to fill the bitmap's background. /// The rotated instance. public FreeImageBitmap GetRotatedInstance(double angle, T? backgroundColor) where T : struct { EnsureNotDisposed(); FreeImageBitmap result = null; FIBITMAP newDib; if (ColorDepth == 4) { newDib = FreeImage.Rotate4bit(dib, angle); } else { newDib = FreeImage.Rotate(dib, angle, backgroundColor); } if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } return result; } /// /// Rotates this by the specified angle initializing a new instance. /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer /// multiple of 90. /// /// The angle of rotation. /// The rotated instance. public FreeImageBitmap GetRotatedInstance(double angle) { EnsureNotDisposed(); FreeImageBitmap result = null; FIBITMAP newDib; if (ColorDepth == 4) { newDib = FreeImage.Rotate4bit(dib, angle); } else { newDib = FreeImage.Rotate(dib, angle); } if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } return result; } /// /// This method performs a rotation and / or translation of an 8-bit greyscale, /// 24- or 32-bit image, using a 3rd order (cubic) B-Spline. /// /// The angle of rotation. /// Horizontal image translation. /// Vertical image translation. /// Rotation center x-coordinate. /// Rotation center y-coordinate. /// When true the irrelevant part of the image is set to a black color, /// otherwise, a mirroring technique is used to fill irrelevant pixels. /// Returns true on success, false on failure. public bool Rotate(double angle, double xShift, double yShift, double xOrigin, double yOrigin, bool useMask) { EnsureNotDisposed(); return ReplaceDib(FreeImage.RotateEx(dib, angle, xShift, yShift, xOrigin, yOrigin, useMask)); } /// /// This method performs a rotation and / or translation of an 8-bit greyscale, /// 24- or 32-bit image, using a 3rd order (cubic) B-Spline initializing a new instance. /// /// The angle of rotation. /// Horizontal image translation. /// Vertical image translation. /// Rotation center x-coordinate. /// Rotation center y-coordinate. /// When true the irrelevant part of the image is set to a black color, /// otherwise, a mirroring technique is used to fill irrelevant pixels. /// The rotated instance. public FreeImageBitmap GetRotatedInstance(double angle, double xShift, double yShift, double xOrigin, double yOrigin, bool useMask) { EnsureNotDisposed(); FreeImageBitmap result = null; FIBITMAP newDib = FreeImage.RotateEx( dib, angle, xShift, yShift, xOrigin, yOrigin, useMask); if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } return result; } /// /// Perfoms an histogram transformation on a 8-, 24- or 32-bit image. /// /// The lookup table (LUT). /// It's size is assumed to be 256 in length. /// The color channel to be transformed. /// Returns true on success, false on failure. public bool AdjustCurve(byte[] lookUpTable, FREE_IMAGE_COLOR_CHANNEL channel) { EnsureNotDisposed(); return FreeImage.AdjustCurve(dib, lookUpTable, channel); } /// /// Performs gamma correction on a 8-, 24- or 32-bit image. /// /// The parameter represents the gamma value to use (gamma > 0). /// A value of 1.0 leaves the image alone, less than one darkens it, and greater than one lightens it. /// Returns true on success, false on failure. public bool AdjustGamma(double gamma) { EnsureNotDisposed(); return FreeImage.AdjustGamma(dib, gamma); } /// /// Adjusts the brightness of a 8-, 24- or 32-bit image by a certain amount. /// /// A value 0 means no change, /// less than 0 will make the image darker and greater than 0 will make the image brighter. /// Returns true on success, false on failure. public bool AdjustBrightness(double percentage) { EnsureNotDisposed(); return FreeImage.AdjustBrightness(dib, percentage); } /// /// Adjusts the contrast of a 8-, 24- or 32-bit image by a certain amount. /// /// A value 0 means no change, /// less than 0 will decrease the contrast and greater than 0 will increase the contrast of the image. /// Returns true on success, false on failure. public bool AdjustContrast(double percentage) { EnsureNotDisposed(); return FreeImage.AdjustContrast(dib, percentage); } /// /// Inverts each pixel data. /// /// Returns true on success, false on failure. public bool Invert() { EnsureNotDisposed(); return FreeImage.Invert(dib); } /// /// Computes the image histogram. /// /// Channel to compute from. /// Array of integers containing the histogram. /// Returns true on success, false on failure. public bool GetHistogram(FREE_IMAGE_COLOR_CHANNEL channel, out int[] histogram) { EnsureNotDisposed(); histogram = new int[256]; return FreeImage.GetHistogram(dib, histogram, channel); } /// /// Retrieves the red, green, blue or alpha channel of a 24- or 32-bit image. /// /// The color channel to extract. /// The color channel in a new instance. public FreeImageBitmap GetChannel(FREE_IMAGE_COLOR_CHANNEL channel) { EnsureNotDisposed(); FreeImageBitmap result = null; FIBITMAP newDib = FreeImage.GetChannel(dib, channel); if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } return result; } /// /// Insert a 8-bit dib into a 24- or 32-bit image. /// Both images must have to same width and height. /// /// The to insert. /// The color channel to replace. /// Returns true on success, false on failure. public bool SetChannel(FreeImageBitmap bitmap, FREE_IMAGE_COLOR_CHANNEL channel) { EnsureNotDisposed(); bitmap.EnsureNotDisposed(); return FreeImage.SetChannel(dib, bitmap.dib, channel); } /// /// Retrieves the real part, imaginary part, magnitude or phase of a complex image. /// /// The color channel to extract. /// The color channel in a new instance. public FreeImageBitmap GetComplexChannel(FREE_IMAGE_COLOR_CHANNEL channel) { EnsureNotDisposed(); FreeImageBitmap result = null; FIBITMAP newDib = FreeImage.GetComplexChannel(dib, channel); if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } return result; } /// /// Set the real or imaginary part of a complex image. /// Both images must have to same width and height. /// /// The to insert. /// The color channel to replace. /// Returns true on success, false on failure. public bool SetComplexChannel(FreeImageBitmap bitmap, FREE_IMAGE_COLOR_CHANNEL channel) { EnsureNotDisposed(); bitmap.EnsureNotDisposed(); return FreeImage.SetComplexChannel(dib, bitmap.dib, channel); } /// /// Copy a sub part of this . /// /// The subpart to copy. /// The sub part in a new instance. public FreeImageBitmap Copy(Rectangle rect) { EnsureNotDisposed(); return Copy(rect.Left, rect.Top, rect.Right, rect.Bottom); } /// /// Copy a sub part of this . /// /// Specifies the left position of the cropped rectangle. /// Specifies the top position of the cropped rectangle. /// Specifies the right position of the cropped rectangle. /// Specifies the bottom position of the cropped rectangle. /// The sub part in a new instance. public FreeImageBitmap Copy(int left, int top, int right, int bottom) { EnsureNotDisposed(); FreeImageBitmap result = null; FIBITMAP newDib = FreeImage.Copy(dib, left, top, right, bottom); if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } return result; } /// /// Alpha blend or combine a sub part image with this . /// The bit depth of must be greater than or equal to the bit depth this instance. /// /// The to paste into this instance. /// Specifies the left position of the sub image. /// Specifies the top position of the sub image. /// alpha blend factor. /// The source and destination images are alpha blended if alpha=0..255. /// If alpha > 255, then the source image is combined to the destination image. /// Returns true on success, false on failure. public bool Paste(FreeImageBitmap bitmap, int left, int top, int alpha) { EnsureNotDisposed(); bitmap.EnsureNotDisposed(); return FreeImage.Paste(dib, bitmap.dib, left, top, alpha); } /// /// Alpha blend or combine a sub part image with tthis . /// The bit depth of must be greater than or equal to the bit depth this instance. /// /// The to paste into this instance. /// Specifies the position of the sub image. /// alpha blend factor. /// The source and destination images are alpha blended if alpha=0..255. /// If alpha > 255, then the source image is combined to the destination image. /// Returns true on success, false on failure. public bool Paste(FreeImageBitmap bitmap, Point point, int alpha) { EnsureNotDisposed(); return Paste(bitmap, point.X, point.Y, alpha); } /// /// This method composite a transparent foreground image against a single background color or /// against a background image. /// In case is false and /// and /// are null, a checkerboard will be used as background. /// /// When true the background of this instance is used /// if it contains one. /// Backgroundcolor used in case is false /// and is not null. /// Background used in case /// is false and is a null reference. /// Returns true on success, false on failure. public bool Composite(bool useBitmapBackground, Color? applicationBackground, FreeImageBitmap bitmapBackGround) { EnsureNotDisposed(); bitmapBackGround.EnsureNotDisposed(); RGBQUAD? rgb = applicationBackground; return ReplaceDib( FreeImage.Composite( dib, useBitmapBackground, rgb.HasValue ? new RGBQUAD[] { rgb.Value } : null, bitmapBackGround.dib)); } /// /// Applies the alpha value of each pixel to its color components. /// The aplha value stays unchanged. /// Only works with 32-bits color depth. /// /// Returns true on success, false on failure. public bool PreMultiplyWithAlpha() { EnsureNotDisposed(); return FreeImage.PreMultiplyWithAlpha(dib); } /// /// Solves a Poisson equation, remap result pixels to [0..1] and returns the solution. /// /// Number of cycles in the multigrid algorithm (usually 2 or 3) /// Returns true on success, false on failure. public bool MultigridPoissonSolver(int ncycle) { EnsureNotDisposed(); return ReplaceDib(FreeImage.MultigridPoissonSolver(dib, ncycle)); } /// /// Adjusts an image's brightness, contrast and gamma as well as it may /// optionally invert the image within a single operation. /// /// Percentage brightness value where -100 <= brightness <= 100. /// A value of 0 means no change, less than 0 will make the image darker and greater /// than 0 will make the image brighter. /// Percentage contrast value where -100 <= contrast <= 100. /// A value of 0 means no change, less than 0 will decrease the contrast /// and greater than 0 will increase the contrast of the image. /// Gamma value to be used for gamma correction. /// A value of 1.0 leaves the image alone, less than one darkens it, /// and greater than one lightens it. /// This parameter must not be zero or smaller than zero. /// If so, it will be ignored and no gamma correction will be performed on the image. /// If set to true, the image will be inverted. /// Returns true on success, false on failure. public bool AdjustColors(double brightness, double contrast, double gamma, bool invert) { EnsureNotDisposed(); return FreeImage.AdjustColors(dib, brightness, contrast, gamma, invert); } /// /// Applies color mapping for one or several colors on a 1-, 4- or 8-bit /// palletized or a 16-, 24- or 32-bit high color image. /// /// Array of colors to be used as the mapping source. /// Array of colors to be used as the mapping destination. /// If true, 32-bit images and colors are treated as 24-bit. /// If true, source and destination colors are swapped, that is, /// each destination color is also mapped to the corresponding source color. /// The total number of pixels changed. /// /// or is a null reference. /// /// /// has a different length than . /// public uint ApplyColorMapping(RGBQUAD[] srccolors, RGBQUAD[] dstcolors, bool ignore_alpha, bool swap) { EnsureNotDisposed(); if (srccolors == null) { throw new ArgumentNullException("srccolors"); } if (dstcolors == null) { throw new ArgumentNullException("dstcolors"); } if (srccolors.Length != dstcolors.Length) { throw new ArgumentException("srccolors and dstcolors must have the same length."); } return FreeImage.ApplyColorMapping(dib, srccolors, dstcolors, (uint)srccolors.Length, ignore_alpha, swap); } /// /// Swaps two specified colors on a 1-, 4- or 8-bit palletized /// or a 16-, 24- or 32-bit high color image. /// /// One of the two colors to be swapped. /// The other of the two colors to be swapped. /// If true, 32-bit images and colors are treated as 24-bit. /// The total number of pixels changed. public uint SwapColors(RGBQUAD color_a, RGBQUAD color_b, bool ignore_alpha) { EnsureNotDisposed(); return FreeImage.SwapColors(dib, ref color_a, ref color_b, ignore_alpha); } /// /// Applies palette index mapping for one or several indices /// on a 1-, 4- or 8-bit palletized image. /// /// Array of palette indices to be used as the mapping source. /// Array of palette indices to be used as the mapping destination. /// The number of palette indices to be mapped. This is the size of both /// srcindices and dstindices /// If true, source and destination palette indices are swapped, that is, /// each destination index is also mapped to the corresponding source index. /// The total number of pixels changed. /// /// or is a null reference. /// /// /// has a different length than . /// public uint ApplyPaletteIndexMapping(byte[] srcindices, byte[] dstindices, uint count, bool swap) { EnsureNotDisposed(); if (srcindices == null) { throw new ArgumentNullException("srcindices"); } if (dstindices == null) { throw new ArgumentNullException("dstindices"); } if (srcindices.Length != dstindices.Length) { throw new ArgumentException("srcindices and dstindices must have the same length."); } return FreeImage.ApplyPaletteIndexMapping(dib, srcindices, dstindices, (uint)srcindices.Length, swap); } /// /// Swaps two specified palette indices on a 1-, 4- or 8-bit palletized image. /// /// One of the two palette indices to be swapped. /// The other of the two palette indices to be swapped. /// The total number of pixels changed. public uint SwapPaletteIndices(byte index_a, byte index_b) { EnsureNotDisposed(); return FreeImage.SwapPaletteIndices(dib, ref index_a, ref index_b); } /// /// Sets all pixels of this to the specified color. /// See for further details. /// /// The type of the specified color. /// The color to fill this with. /// true on success, false on failure. public bool FillBackground(T color) where T : struct { return FillBackground(color, FREE_IMAGE_COLOR_OPTIONS.FICO_DEFAULT); } /// /// Sets all pixels of this to the specified color. /// See for further details. /// /// The type of the specified color. /// The color to fill this with. /// Options that affect the color search process for palletized images. /// true on success, false on failure. public bool FillBackground(T color, FREE_IMAGE_COLOR_OPTIONS options) where T : struct { EnsureNotDisposed(); return FreeImage.FillBackground(dib, color, options); } /// /// Creates a new ICC-Profile. /// /// The data of the new ICC-Profile. /// The new ICC-Profile of the bitmap. /// is a null reference. public FIICCPROFILE CreateICCProfile(byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } return CreateICCProfile(data, data.Length); } /// /// Creates a new ICC-Profile. /// /// The data of the new ICC-Profile. /// The number of bytes of to use. /// The new ICC-Profile of the bitmap. /// is null. public FIICCPROFILE CreateICCProfile(byte[] data, int size) { EnsureNotDisposed(); if (data == null) { throw new ArgumentNullException("data"); } return FreeImage.CreateICCProfileEx(dib, data, size); } /// /// Determines whether this and the specified instances are the same. /// /// The object to test. /// true if this instance is the same /// or if both are null references; otherwise, false. public override bool Equals(object obj) { return ReferenceEquals(this, obj); } /// /// Returns a hash code for this structure. /// /// An integer value that specifies the hash code for this . public override int GetHashCode() { return dib.GetHashCode(); } #endregion #region Static functions /// /// Returns a value that indicates whether the pixel format for this contains alpha information. /// /// The to test. /// true if pixfmt contains alpha information; otherwise, false. public static bool IsAlphaPixelFormat(PixelFormat pixfmt) { return Bitmap.IsAlphaPixelFormat(pixfmt); } /// /// Returns a value that indicates whether the pixel format is 32 bits per pixel. /// /// The to test. /// true if pixfmt is canonical; otherwise, false. public static bool IsCanonicalPixelFormat(PixelFormat pixfmt) { return Bitmap.IsCanonicalPixelFormat(pixfmt); } /// /// Returns a value that indicates whether the pixel format is 64 bits per pixel. /// /// The enumeration to test. /// true if pixfmt is extended; otherwise, false. public static bool IsExtendedPixelFormat(PixelFormat pixfmt) { return Bitmap.IsExtendedPixelFormat(pixfmt); } /// /// Creates a from a Windows handle to an icon. /// /// A handle to an icon. /// The that this method creates. public static FreeImageBitmap FromHicon(IntPtr hicon) { using (Bitmap bitmap = Bitmap.FromHicon(hicon)) { return new FreeImageBitmap(bitmap); } } /// /// Creates a from the specified Windows resource. /// /// A handle to an instance of the executable /// file that contains the resource. /// A string containing the name of the resource bitmap. /// The that this method creates. public static FreeImageBitmap FromResource(IntPtr hinstance, string bitmapName) { using (Bitmap bitmap = Bitmap.FromResource(hinstance, bitmapName)) { return new FreeImageBitmap(bitmap); } } /// /// Creates a from the specified file. /// /// A string that contains the name of the file /// from which to create the . /// The this method creates. public static FreeImageBitmap FromFile(string filename) { return new FreeImageBitmap(filename); } /// /// Creates a from the specified file /// using embedded color management information in that file. /// /// A string that contains the /// name of the file from which to create the . /// Ignored. /// The this method creates. public static FreeImageBitmap FromFile(string filename, bool useEmbeddedColorManagement) { return new FreeImageBitmap(filename); } /// /// Creates a from a handle to a GDI bitmap. /// /// The GDI bitmap handle from which to create the . /// The this method creates. public static FreeImageBitmap FromHbitmap(IntPtr hbitmap) { FreeImageBitmap result = null; FIBITMAP newDib = FreeImage.CreateFromHbitmap(hbitmap, IntPtr.Zero); if (!newDib.IsNull) { result = new FreeImageBitmap(newDib); } return result; } /// /// Creates a from a handle to a GDI bitmap and a handle to a GDI palette. /// /// The GDI bitmap handle from which to create the . /// Ignored. /// The this method creates. public static FreeImageBitmap FromHbitmap(IntPtr hbitmap, IntPtr hpalette) { return FromHbitmap(hbitmap); } /// /// Frees a bitmap handle. /// /// Handle to a bitmap. /// true on success, false on failure. public static bool FreeHbitmap(IntPtr hbitmap) { return FreeImage.FreeHbitmap(hbitmap); } /// /// Creates a from the specified data stream. /// /// A that contains the data for this . /// The this method creates. public static FreeImageBitmap FromStream(Stream stream) { return new FreeImageBitmap(stream); } /// /// Creates a from the specified data stream. /// /// A that contains the data for this . /// Ignored. /// The this method creates. public static FreeImageBitmap FromStream(Stream stream, bool useEmbeddedColorManagement) { return new FreeImageBitmap(stream); } /// /// Creates a from the specified data stream. /// /// A that contains the data for this . /// Ignored. /// Ignored. /// The this method creates. public static FreeImageBitmap FromStream(Stream stream, bool useEmbeddedColorManagement, bool validateImageData) { return new FreeImageBitmap(stream); } /// /// Returns the color depth, in number of bits per pixel, /// of the specified pixel format. /// /// The member that specifies /// the format for which to find the size. /// The color depth of the specified pixel format. public static int GetPixelFormatSize(PixelFormat pixfmt) { return Bitmap.GetPixelFormatSize(pixfmt); } /// /// Performs a lossless rotation or flipping on a JPEG file. /// /// Source file. /// Destination file; can be the source file; will be overwritten. /// The operation to apply. /// To avoid lossy transformation, you can set the perfect parameter to true. /// Returns true on success, false on failure. public static bool JPEGTransform(string source, string destination, FREE_IMAGE_JPEG_OPERATION operation, bool perfect) { return FreeImage.JPEGTransform(source, destination, operation, perfect); } /// /// Performs a lossless crop on a JPEG file. /// /// Source filename. /// Destination filename. /// Specifies the cropped rectangle. /// Returns true on success, false on failure. /// /// or is null. /// /// /// does not exist. /// public static bool JPEGCrop(string source, string destination, Rectangle rect) { if (source == null) { throw new ArgumentNullException("source"); } if (!File.Exists(source)) { throw new FileNotFoundException("source"); } if (destination == null) { throw new ArgumentNullException("destination"); } return JPEGCrop(source, destination, rect.Left, rect.Top, rect.Right, rect.Bottom); } /// /// Performs a lossless crop on a JPEG file. /// /// Source filename. /// Destination filename. /// Specifies the left position of the cropped rectangle. /// Specifies the top position of the cropped rectangle. /// Specifies the right position of the cropped rectangle. /// Specifies the bottom position of the cropped rectangle. /// Returns true on success, false on failure. /// /// or is null. /// /// /// does not exist. /// public static bool JPEGCrop(string source, string destination, int left, int top, int right, int bottom) { if (source == null) { throw new ArgumentNullException("source"); } if (!File.Exists(source)) { throw new FileNotFoundException("source"); } if (destination == null) { throw new ArgumentNullException("destination"); } return FreeImage.JPEGCrop(source, destination, left, top, right, bottom); } /// /// Converts a X11 color name into a corresponding RGB value. /// /// Name of the color to convert. /// Red component. /// Green component. /// Blue component. /// Returns true on success, false on failure. /// is null. public static bool LookupX11Color(string color, out byte red, out byte green, out byte blue) { if (color == null) { throw new ArgumentNullException("color"); } return FreeImage.LookupX11Color(color, out red, out green, out blue); } /// /// Converts a SVG color name into a corresponding RGB value. /// /// Name of the color to convert. /// Red component. /// Green component. /// Blue component. /// Returns true on success, false on failure. /// is null. public static bool LookupSVGColor(string color, out byte red, out byte green, out byte blue) { if (color == null) { throw new ArgumentNullException("color"); } return FreeImage.LookupSVGColor(color, out red, out green, out blue); } /// /// Creates a lookup table to be used with AdjustCurve() which /// may adjusts brightness and contrast, correct gamma and invert the image with a /// single call to AdjustCurve(). /// /// Output lookup table to be used with AdjustCurve(). /// The size of is assumed to be 256. /// Percentage brightness value where -100 <= brightness <= 100. /// A value of 0 means no change, less than 0 will make the image darker and greater /// than 0 will make the image brighter. /// Percentage contrast value where -100 <= contrast <= 100. /// A value of 0 means no change, less than 0 will decrease the contrast /// and greater than 0 will increase the contrast of the image. /// Gamma value to be used for gamma correction. /// A value of 1.0 leaves the image alone, less than one darkens it, /// and greater than one lightens it. /// If set to true, the image will be inverted. /// The number of adjustments applied to the resulting lookup table /// compared to a blind lookup table. /// is null. /// is not 256. public static int GetAdjustColorsLookupTable(byte[] lookUpTable, double brightness, double contrast, double gamma, bool invert) { if (lookUpTable == null) { throw new ArgumentNullException("lookUpTable"); } if (lookUpTable.Length != 256) { throw new ArgumentException("lookUpTable"); } return FreeImage.GetAdjustColorsLookupTable(lookUpTable, brightness, contrast, gamma, invert); } /// /// Adds a specified frame to the file specified using the specified parameters. /// Use this method to save selected frames from an to a multiple-frame image. /// /// File to add this frame to. /// A that contains the frame to add. /// Format of the image. /// Flags to enable or disable plugin-features. /// Flags to enable or disable plugin-features. /// /// or is null. /// /// does not exist. /// Saving the image failed. public static void SaveAdd( string filename, FreeImageBitmap bitmap, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS loadFlags, FREE_IMAGE_SAVE_FLAGS saveFlags) { if (filename == null) { throw new ArgumentNullException("filename"); } if (!File.Exists(filename)) { throw new FileNotFoundException("filename"); } if (bitmap == null) { throw new ArgumentNullException("bitmap"); } bitmap.EnsureNotDisposed(); FIBITMAP dib = bitmap.dib; if (dib.IsNull) throw new ArgumentNullException("bitmap"); FIMULTIBITMAP mpBitmap = FreeImage.OpenMultiBitmapEx(filename, ref format, loadFlags, false, false, true); if (mpBitmap.IsNull) throw new Exception(ErrorLoadingBitmap); FreeImage.AppendPage(mpBitmap, bitmap.dib); if (!FreeImage.CloseMultiBitmap(mpBitmap, saveFlags)) throw new Exception(ErrorUnloadBitmap); } /// /// Adds a specified frame to the file specified using the specified parameters. /// Use this method to save selected frames from an image to a multiple-frame image. /// /// File to add this frame to. /// A that contains the frame to add. /// The position of the inserted frame. /// Format of the image. /// Flags to enable or disable plugin-features. /// Flags to enable or disable plugin-features. /// /// or is null. /// /// does not exist. /// Saving the image failed. /// is out of range. public static void SaveAdd( string filename, FreeImageBitmap bitmap, int insertPosition, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS loadFlags, FREE_IMAGE_SAVE_FLAGS saveFlags) { if (filename == null) { throw new ArgumentNullException("filename"); } if (!File.Exists(filename)) { throw new FileNotFoundException("filename"); } if (bitmap == null) { throw new ArgumentNullException("bitmap"); } if (insertPosition < 0) { throw new ArgumentOutOfRangeException("insertPosition"); } bitmap.EnsureNotDisposed(); FIBITMAP dib = bitmap.dib; if (dib.IsNull) throw new ArgumentNullException("bitmap"); FIMULTIBITMAP mpBitmap = FreeImage.OpenMultiBitmapEx(filename, ref format, loadFlags, false, false, true); if (mpBitmap.IsNull) throw new Exception(ErrorLoadingBitmap); int pageCount = FreeImage.GetPageCount(mpBitmap); if (insertPosition > pageCount) throw new ArgumentOutOfRangeException("insertPosition"); if (insertPosition == pageCount) FreeImage.AppendPage(mpBitmap, bitmap.dib); else FreeImage.InsertPage(mpBitmap, insertPosition, bitmap.dib); if (!FreeImage.CloseMultiBitmap(mpBitmap, saveFlags)) throw new Exception(ErrorUnloadBitmap); } /// /// Returns a new instance of the class which /// has no public accessible constructor. /// /// A new instace of . public static PropertyItem CreateNewPropertyItem() { return FreeImage.CreatePropertyItem(); } #endregion #region Helper functions /// /// Throws an exception in case the instance has already been disposed. /// private void EnsureNotDisposed() { lock (lockObject) { if (!this.disposed) { return; } } throw new ObjectDisposedException(ToString()); } /// /// Tries to replace the wrapped with a new one. /// In case the new dib is null or the same as the already /// wrapped one, nothing will be changed and the result will /// be false. /// Otherwise the wrapped will be unloaded and replaced. /// /// The new dib. /// Returns true on success, false on failure. private bool ReplaceDib(FIBITMAP newDib) { bool result = false; if ((dib != newDib) && (!newDib.IsNull)) { UnloadDib(); dib = newDib; AddMemoryPressure(); result = true; } return result; } /// /// Unloads currently wrapped or unlocks the locked page /// in case it came from a multipaged bitmap. /// private void UnloadDib() { if (!dib.IsNull) { long size = FreeImage.GetDIBSize(dib); FreeImage.UnloadEx(ref dib); if (size > 0L) GC.RemoveMemoryPressure(size); } } /// /// Informs the runtime about unmanaged allocoted memory. /// private void AddMemoryPressure() { long dataSize; if ((dataSize = DataSize) > 0L) GC.AddMemoryPressure(dataSize); } /// /// Opens the stream and reads the number of available pages. /// Then loads the first page to this instance. /// private void LoadFromStream(Stream stream, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS flags) { FIMULTIBITMAP mdib = FreeImage.OpenMultiBitmapFromStream(stream, ref format, flags); if (mdib.IsNull) { throw new Exception(ErrorLoadingBitmap); } try { frameCount = FreeImage.GetPageCount(mdib); } finally { if (!FreeImage.CloseMultiBitmapEx(ref mdib)) { throw new Exception(ErrorUnloadBitmap); } } dib = FreeImage.LoadFromStream(stream, flags, ref format); if (dib.IsNull) { throw new Exception(ErrorLoadingBitmap); } saveInformation.loadFlags = flags; originalFormat = format; AddMemoryPressure(); } #endregion #region Interfaces /// /// Helper class to store informations for . /// private sealed class SaveInformation : ICloneable { public string filename; public FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN; public FREE_IMAGE_LOAD_FLAGS loadFlags = FREE_IMAGE_LOAD_FLAGS.DEFAULT; public FREE_IMAGE_SAVE_FLAGS saveFlags = FREE_IMAGE_SAVE_FLAGS.DEFAULT; public object Clone() { return base.MemberwiseClone(); } } /// /// Creates a deep copy of this . /// /// A deep copy of this . public object Clone() { EnsureNotDisposed(); FreeImageBitmap result = null; FIBITMAP newDib = FreeImage.Clone(dib); if (!dib.IsNull) { result = new FreeImageBitmap(newDib); result.saveInformation = (SaveInformation)saveInformation.Clone(); result.tag = tag; result.originalFormat = originalFormat; } return result; } /// /// Performs application-defined tasks associated with freeing, /// releasing, or resetting unmanaged resources. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Performs application-defined tasks associated with freeing, /// releasing, or resetting unmanaged resources. /// /// If true managed ressources are released. protected virtual void Dispose(bool disposing) { // Only clean up once lock (lockObject) { if (disposed) { return; } disposed = true; } // Clean up managed resources if (disposing) { if (stream != null) { if (disposeStream) { stream.Dispose(); } stream = null; } } tag = null; saveInformation = null; // Clean up unmanaged resources UnloadDib(); } /// /// Retrieves an object that can iterate through the individual scanlines in this . /// /// An for the . /// The bitmaps's type is not supported. IEnumerator IEnumerable.GetEnumerator() { return GetScanlines().GetEnumerator(); } void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { EnsureNotDisposed(); using (MemoryStream memory = new MemoryStream(DataSize)) { if (!FreeImage.SaveToStream(dib, memory, FREE_IMAGE_FORMAT.FIF_TIFF, FREE_IMAGE_SAVE_FLAGS.TIFF_LZW)) { throw new SerializationException(); } memory.Capacity = (int)memory.Length; info.AddValue("Bitmap Data", memory.GetBuffer()); } } #endregion } }