// ==========================================================
// 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
}
}