Click here to Skip to main content
15,886,074 members
Articles / Programming Languages / C#

Managed Bitmaps 2

Rate me:
Please Sign up or sign in to vote.
4.77/5 (17 votes)
19 Mar 2010CPOL5 min read 51.5K   991   36  
This article presents classes that represent bitmaps in full managed code.
using System;
using System.Drawing;
using System.Drawing.Imaging;
using Pfz.Drawing.Extensions.BitmapExtensions;
using Pfz.Threading;

namespace Pfz.Drawing
{
	/// <summary>
	/// Represents a "map" of values as a two-dimensional array. Ideal to convert to and
	/// from unmanaged bitmaps.
	/// </summary>
	/// <typeparam name="T">The type of the data this map supports.</typeparam>
	[Serializable]
	public class ManagedBitmap<T>:
		IBitmap
	{
		#region Constructors
			/// <summary>
			/// Creates a new ManagedBitmap with the given width (first dimension) and
			/// height (second dimension).
			/// </summary>
			/// <param name="width">The size of the first dimension.</param>
			/// <param name="height">The size of the second dimension.</param>
			public ManagedBitmap(int width, int height)
			{
				if (width < 1)
					throw new ArgumentOutOfRangeException("width");
				
				if (height < 1)
					throw new ArgumentOutOfRangeException("height");
					
				fPixelArray = new T[width * height];
				fWidth = width;
			}
			
			/// <summary>
			/// Creates a new ManagedBitmap using the given single-dimension array and
			/// the given width. The array must have a length that is a multiplier of width.
			/// </summary>
			/// <param name="baseArray">The base array. Must be different than null.</param>
			/// <param name="width">The width of the array.</param>
			public ManagedBitmap(T[] baseArray, int width)
			{
				if (baseArray == null)
					throw new ArgumentNullException("array");
				
				if (width < 1)
					throw new ArgumentOutOfRangeException("width");
				
				if (baseArray.Length % width != 0)
					throw new ArgumentException("The array length must be a multiple of width.");
				
				fPixelArray = baseArray;
				fWidth = width;
			}
			
			/// <summary>
			/// Creates a new ManagedBitmap that is a copy of a given 32-bit argb 
			/// System.Drawing.Bitmap.
			/// </summary>
			public ManagedBitmap(Bitmap bitmap, Func<int, T> convertFromArgbDelegate)
			{
				if (bitmap == null)
					throw new ArgumentNullException("bitmap");
				
				if (convertFromArgbDelegate == null)
					throw new ArgumentNullException("convertFromArgbDelegate");
				
				int width = bitmap.Width;
				int height = bitmap.Height;
				T[] array = new T[width * height];
				int arrayIndex = -1;
				
				Bitmap bitmapToUse = null;
				BitmapData data = null;
				AbortSafe.Run
				(
					() =>
					{
						if (bitmap.PixelFormat == PixelFormat.Format32bppArgb)
							bitmapToUse = bitmap;
						else
							bitmapToUse = bitmap.CloneAsFormat32bppArgb();
						
						data = bitmapToUse.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
					},
					() =>
					{
						unsafe
						{
							byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
							for (int y=0; y<height; y++)
							{
								int *scanLine = (int *)scanLineBytes;
								
								for (int x=0; x<width; x++)
								{
									arrayIndex++;
									int argb = scanLine[x];
									array[arrayIndex] = convertFromArgbDelegate(argb);
								}
								
								scanLineBytes += data.Stride;
							}
						}
					},
					() =>
					{
						if (data != null)
							bitmapToUse.UnlockBits(data);
						
						if (bitmapToUse != bitmap && bitmapToUse != null)
							bitmapToUse.Dispose();
					}
				);
				
				fPixelArray = array;
				fWidth = width;
			}

			/// <summary>
			/// Creates a new ManagedBitmap that is a copy of a given 24-bit rgb 
			/// System.Drawing.Bitmap.
			/// </summary>
			public ManagedBitmap(Bitmap bitmap, Func<Rgb24, T> convertFromRgbDelegate)
			{
				if (bitmap == null)
					throw new ArgumentNullException("bitmap");
				
				if (convertFromRgbDelegate == null)
					throw new ArgumentNullException("convertFromRgbDelegate");
				
				int width = bitmap.Width;
				int height = bitmap.Height;
				T[] array = new T[width * height];
				int arrayIndex = -1;
				
				BitmapData data = null;
				AbortSafe.Run
				(
					() => data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb),
					() =>
					{
						unsafe
						{
							byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
							for (int y=0; y<height; y++)
							{
								Rgb24 *scanLine = (Rgb24 *)scanLineBytes;
								
								for (int x=0; x<width; x++)
								{
									arrayIndex++;
									Rgb24 rgb = scanLine[x];
									array[arrayIndex] = convertFromRgbDelegate(rgb);
								}
								
								scanLineBytes += data.Stride;
							}
						}
					},
					() =>
					{
						if (data != null)
							bitmap.UnlockBits(data);
					}
				);
				
				fPixelArray = array;
				fWidth = width;
			}

			/// <summary>
			/// Creates a new ManagedBitmap that is a copy of a given indexed 8-bit
			/// System.Drawing.Bitmap.
			/// </summary>
			public ManagedBitmap(Bitmap bitmap, Func<byte, T> convertFromIndexDelegate)
			{
				if (bitmap == null)
					throw new ArgumentNullException("bitmap");
					
				if (bitmap.PixelFormat != PixelFormat.Format8bppIndexed)
					throw new ArgumentException("bitmap.PixelFormat must be Format8bppIndexed.");
				
				if (convertFromIndexDelegate == null)
					throw new ArgumentNullException("convertFromIndexDelegate");
				
				int width = bitmap.Width;
				int height = bitmap.Height;
				T[] array = new T[width * height];
				int arrayIndex = -1;
				
				BitmapData data = null;
				AbortSafe.Run
				(
					() =>
					{
						data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
					},
					() =>
					{
						unsafe
						{
							byte *scanLine = (byte *)data.Scan0.ToPointer();
							for (int y=0; y<height; y++)
							{
								for (int x=0; x<width; x++)
								{
									arrayIndex++;
									byte index = scanLine[x];
									array[arrayIndex] = convertFromIndexDelegate(index);
								}
								
								scanLine += data.Stride;
							}
						}
					},
					() =>
					{
						if (data != null)
							bitmap.UnlockBits(data);
					}
				);
				
				fPixelArray = array;
				fWidth = width;
			}
		#endregion
		
		#region Properties
			private T[] fPixelArray;
			/// <summary>
			/// Gets the base array used by this bitmap.
			/// </summary>
			public T[] PixelArray
			{
				get
				{
					return fPixelArray;
				}
			}
			
			private int fWidth;
			/// <summary>
			/// Gets the width of this bitmap.
			/// </summary>
			public int Width
			{
				get
				{
					return fWidth;
				}
			}
			
			/// <summary>
			/// Gets the height of this bitmap.
			/// </summary>
			public int Height
			{
				get
				{
					return fPixelArray.Length / fWidth;
				}
			}

			/// <summary>
			/// Gets or sets a value into the bitmap.
			/// </summary>
			/// <param name="x">The first-dimension index in the array.</param>
			/// <param name="y">The second-dimension index in the array.</param>
			/// <returns>The value at the given index.</returns>
			public T this[int x, int y]
			{
				get
				{
					return PixelArray[y * Width + x];
				}
				set
				{
					PixelArray[y * Width + x] = value;
				}
			}
		#endregion
		#region Methods
			#region CopyTo - full managed
				#region Same type
					/// <summary>
					/// Copies a part of this bitmap to another bitmap of the same type.
					/// </summary>
					public void CopyTo(ManagedBitmap<T> other, Point sourceLocation, Point destLocation, Size size)
					{
						if (PixelArray == null)
							return;
					
						if (other.PixelArray == null)
							throw new ArgumentException("other array must not be empty.", "other");
					
						if (sourceLocation.X < 0 || sourceLocation.Y < 0)
							throw new ArgumentOutOfRangeException("sourceLocation");
						
						if (destLocation.X < 0 || destLocation.Y < 0)
							throw new ArgumentOutOfRangeException("destLocation");
						
						if 
						(
							sourceLocation.X + size.Width > fWidth || sourceLocation.Y + size.Height > Height ||
							destLocation.X + size.Width > other.fWidth || destLocation.Y + size.Height > other.Height
						)
						{
							throw new ArgumentOutOfRangeException("size");
						}
						
						int sourceIndex = sourceLocation.Y * Width + sourceLocation.X;
						int destIndex = destLocation.Y * other.Width + destLocation.X;
						T[] sourceArray = PixelArray;
						T[] destArray = other.PixelArray;
						for (int y=0; y<size.Height; y++)
						{
							for (int x=0; x<size.Width; x++)
								destArray[destIndex+x] = sourceArray[sourceIndex+x];
							
							sourceIndex += Width;
							destIndex += other.Width;
						}
					}
				#endregion
				#region Other type
					/// <summary>
					/// Copies a part of this bitmap to a bitmap of a different type.
					/// </summary>
					public void CopyTo<T2>(ManagedBitmap<T2> other, Point sourceLocation, Point destLocation, Size size, Func<T, T2> convertToDelegate)
					{
						if (PixelArray == null)
							return;
					
						if (other.PixelArray == null)
							throw new ArgumentException("other array must not be empty.", "other");
					
						if (sourceLocation.X < 0 || sourceLocation.Y < 0)
							throw new ArgumentOutOfRangeException("sourceLocation");
						
						if (destLocation.X < 0 || destLocation.Y < 0)
							throw new ArgumentOutOfRangeException("destLocation");
						
						if (convertToDelegate == null)
							throw new ArgumentNullException("convertToDelegate");
						
						if 
						(
							sourceLocation.X + size.Width > fWidth || sourceLocation.Y + size.Height > Height ||
							destLocation.X + size.Width > other.fWidth || destLocation.Y + size.Height > other.Height
						)
						{
							throw new ArgumentOutOfRangeException("size");
						}
						
						int sourceIndex = sourceLocation.Y * Width + sourceLocation.X;
						int destIndex = destLocation.Y * other.Width + destLocation.X;
						T[] sourceArray = PixelArray;
						T2[] destArray = other.PixelArray;
						for (int y=0; y<size.Height; y++)
						{
							for (int x=0; x<size.Width; x++)
								destArray[destIndex+x] = convertToDelegate(sourceArray[sourceIndex+x]);
							
							sourceIndex += Width;
							destIndex += other.Width;
						}
					}
				#endregion
			#endregion

			#region Create - CopyTo/From - System.Drawing.Bitmap - Argb32
				#region CopyTo
					private void p_CopyToBitmapDirectArgb32(Bitmap bitmap, Func<T, int> convertToArgbDelegate)
					{
						int width = Width;
						int height = Height;
						T[] baseArray = PixelArray;
					
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb),
							() =>
							{
								unsafe
								{
									int arrayIndex = -1;
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<height; y++)
									{
										int *scanLine = (int *)scanLineBytes;
										
										for (int x=0; x<width; x++)
										{
											arrayIndex++;
											T value = baseArray[arrayIndex];
											int argb = convertToArgbDelegate(value);
											scanLine[x] = argb;
										}
										
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies a part of this bitmap to a System.Drawing.Bitmap.
					/// </summary>
					public void CopyToArgb32(Bitmap bitmap, Point sourceLocation, Point destLocation, Size size, Func<T, int> convertToArgbDelegate)
					{
						if (PixelArray == null)
							return;
					
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
							throw new ArgumentException("bitmap.PixelFormat must be Format32bppArgb.", "bitmap");
					
						if (sourceLocation.X < 0 || sourceLocation.Y < 0)
							throw new ArgumentOutOfRangeException("sourceLocation");
						
						if (destLocation.X < 0 || destLocation.Y < 0)
							throw new ArgumentOutOfRangeException("destLocation");
						
						if (convertToArgbDelegate == null)
							throw new ArgumentNullException("convertToArgbDelegate");
						
						if 
						(
							sourceLocation.X + size.Width > fWidth || sourceLocation.Y + size.Height > Height ||
							destLocation.X + size.Width > bitmap.Width || destLocation.Y + size.Height > bitmap.Height
						)
						{
							throw new ArgumentOutOfRangeException("size");
						}
						
						int sourceIndex = sourceLocation.Y * Width + sourceLocation.X;
						T[] sourceArray = PixelArray;
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(destLocation, size), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb),
							() =>
							{
								unsafe
								{
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<size.Height; y++)
									{
										int *scanLine = (int *)scanLineBytes;
										
										for (int x=0; x<size.Width; x++)
											scanLine[x] = convertToArgbDelegate(sourceArray[sourceIndex+x]);
										
										sourceIndex += Width;
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies this bitmap to the given System.Drawing.Bitmap.
					/// It must be a 32-bit argb bitmap for this to work.
					/// </summary>
					public void CopyToArgb32(Bitmap bitmap, Func<T, int> convertToArgbDelegate)
					{
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (convertToArgbDelegate == null)
							throw new ArgumentNullException("convertToArgbDelegate");

						if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
							throw new ArgumentException("bitmap must be in 32-bit argb format.");
						
						int width = bitmap.Width;
						int height = bitmap.Height;
						if (width == Width && height == Height)
						{
							p_CopyToBitmapDirectArgb32(bitmap, convertToArgbDelegate);
							return;
						}
						
						CopyToArgb32(bitmap, new Point(0, 0), new Point(0, 0), new Size(Math.Min(Width, width), Math.Min(Height, height)), convertToArgbDelegate);
					}
				#endregion
				#region CopyFrom
					/// <summary>
					/// Copies the given System.Drawing.Bitmap to this bitmap.
					/// It must be a 32-bit argb bitmap for this to work.
					/// </summary>
					public void CopyFromArgb32(Bitmap bitmap, Func<int, T> convertFromArgbDelegate)
					{
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (convertFromArgbDelegate == null)
							throw new ArgumentNullException("convertFromArgbDelegate");

						if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
							throw new ArgumentException("bitmap must be in 32-bit argb format.");
						
						int width = Width;
						int height = Height;

						if (bitmap.Width != width || bitmap.Height != height)
						{
							CopyFromArgb32(bitmap, new Point(0, 0), new Point(0, 0), new Size(Math.Min(width, bitmap.Width), Math.Min(height, bitmap.Height)), convertFromArgbDelegate);
							return;
						}
						
						T[] baseArray = PixelArray;
					
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb),
							() =>
							{
								unsafe
								{
									int arrayIndex = -1;
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<height; y++)
									{
										int *scanLine = (int *)scanLineBytes;
										
										for (int x=0; x<width; x++)
										{
											int argb = scanLine[x];
											T value = convertFromArgbDelegate(argb);

											arrayIndex++;
											baseArray[arrayIndex] = value;
										}
										
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies the given System.Drawing.Bitmap to this bitmap.
					/// It must be a 32-bit argb bitmap for this to work.
					/// </summary>
					public void CopyFromArgb32(Bitmap bitmap, Func<Point, int, T> convertFromArgbDelegate)
					{
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (convertFromArgbDelegate == null)
							throw new ArgumentNullException("convertFromArgbDelegate");

						if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
							throw new ArgumentException("bitmap must be in 32-bit argb format.");
						
						int width = Width;
						int height = Height;

						if (bitmap.Width != width || bitmap.Height != height)
						{
							CopyFromArgb32(bitmap, new Point(0, 0), new Point(0, 0), new Size(Math.Min(width, bitmap.Width), Math.Min(height, bitmap.Height)), convertFromArgbDelegate);
							return;
						}
						
						T[] baseArray = PixelArray;
					
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb),
							() =>
							{
								unsafe
								{
									int arrayIndex = -1;
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<height; y++)
									{
										int *scanLine = (int *)scanLineBytes;
										
										for (int x=0; x<width; x++)
										{
											int argb = scanLine[x];
											T value = convertFromArgbDelegate(new Point(x, y), argb);

											arrayIndex++;
											baseArray[arrayIndex] = value;
										}
										
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}
					
					/// <summary>
					/// Copies a block from a System.Drawing.Bitmap to this ManagedBitmap using the given conversion
					/// delegate.
					/// </summary>
					public void CopyFromArgb32(Bitmap bitmap, Point sourceLocation, Point destLocation, Size size, Func<int, T> convertFromArgbDelegate)
					{
						if (PixelArray == null)
							return;
					
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
							throw new ArgumentException("bitmap.PixelFormat must be Format32bppArgb.", "bitmap");
					
						if (sourceLocation.X < 0 || sourceLocation.Y < 0)
							throw new ArgumentOutOfRangeException("sourceLocation");
						
						if (destLocation.X < 0 || destLocation.Y < 0)
							throw new ArgumentOutOfRangeException("destLocation");
						
						if (convertFromArgbDelegate == null)
							throw new ArgumentNullException("convertFromArgbDelegate");
						
						if 
						(
							sourceLocation.X + size.Width > fWidth || sourceLocation.Y + size.Height > Height ||
							destLocation.X + size.Width > bitmap.Width || destLocation.Y + size.Height > bitmap.Height
						)
						{
							throw new ArgumentOutOfRangeException("size");
						}
						
						int destIndex = destLocation.Y * Width + destLocation.X;
						T[] destArray = PixelArray;
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(sourceLocation, size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb),
							() =>
							{
								unsafe
								{
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<size.Height; y++)
									{
										int *scanLine = (int *)scanLineBytes;
										
										for (int x=0; x<size.Width; x++)
											destArray[destIndex+x] = convertFromArgbDelegate(scanLine[x]);
										
										destIndex += Width;
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies a block from a System.Drawing.Bitmap to this bitmap using the given conversion
					/// delegate.
					/// </summary>
					public void CopyFromArgb32(Bitmap bitmap, Point sourceLocation, Point destLocation, Size size, Func<Point, int, T> convertFromArgbDelegate)
					{
						if (PixelArray == null)
							return;
					
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
							throw new ArgumentException("bitmap.PixelFormat must be Format32bppArgb.", "bitmap");
					
						if (sourceLocation.X < 0 || sourceLocation.Y < 0)
							throw new ArgumentOutOfRangeException("sourceLocation");
						
						if (destLocation.X < 0 || destLocation.Y < 0)
							throw new ArgumentOutOfRangeException("destLocation");
						
						if (convertFromArgbDelegate == null)
							throw new ArgumentNullException("convertFromArgbDelegate");
						
						if 
						(
							sourceLocation.X + size.Width > fWidth || sourceLocation.Y + size.Height > Height ||
							destLocation.X + size.Width > bitmap.Width || destLocation.Y + size.Height > bitmap.Height
						)
						{
							throw new ArgumentOutOfRangeException("size");
						}
						
						int destIndex = destLocation.Y * Width + destLocation.X;
						T[] destArray = PixelArray;
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(sourceLocation, size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb),
							() =>
							{
								unsafe
								{
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<size.Height; y++)
									{
										int *scanLine = (int *)scanLineBytes;
										
										for (int x=0; x<size.Width; x++)
											destArray[destIndex+x] = convertFromArgbDelegate(new Point(x, y), scanLine[x]);
										
										destIndex += Width;
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}
				#endregion
				#region CreateBitmapArgb32
					/// <summary>
					/// Creates a new 32-bit argb System.Drawing.Bitmap using the given convert method.
					/// </summary>
					public Bitmap CreateBitmapArgb32(Func<T, int> convertToArgbDelegate)
					{
						if (PixelArray == null)
							throw new ArgumentException("This array must not be empty.", "array");
						
						if (convertToArgbDelegate == null)
							throw new ArgumentNullException("convertToArgbDelegate");
						
						Bitmap result = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
						p_CopyToBitmapDirectArgb32(result, convertToArgbDelegate);
						return result;
					}
				#endregion
			#endregion
			#region Create - CopyTo/From - System.Drawing.Bitmap - Rgb24
				#region CopyTo
					private void p_CopyToBitmapDirectRgb24(Bitmap bitmap, Func<T, Rgb24> convertToRgbDelegate)
					{
						int width = Width;
						int height = Height;
						T[] baseArray = PixelArray;
					
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb),
							() =>
							{
								unsafe
								{
									int arrayIndex = -1;
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<height; y++)
									{
										Rgb24 *scanLine = (Rgb24 *)scanLineBytes;
										
										for (int x=0; x<width; x++)
										{
											arrayIndex++;
											T value = baseArray[arrayIndex];
											Rgb24 rgb = convertToRgbDelegate(value);
											scanLine[x] = rgb;
										}
										
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies a part of this bitmap to a System.Drawing.Bitmap.
					/// </summary>
					public void CopyToRgb24(Bitmap bitmap, Point sourceLocation, Point destLocation, Size size, Func<T, Rgb24> convertToRgbDelegate)
					{
						if (PixelArray == null)
							return;
					
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (bitmap.PixelFormat != PixelFormat.Format24bppRgb)
							throw new ArgumentException("bitmap.PixelFormat must be Format24bppRgb.", "bitmap");
					
						if (sourceLocation.X < 0 || sourceLocation.Y < 0)
							throw new ArgumentOutOfRangeException("sourceLocation");
						
						if (destLocation.X < 0 || destLocation.Y < 0)
							throw new ArgumentOutOfRangeException("destLocation");
						
						if (convertToRgbDelegate == null)
							throw new ArgumentNullException("convertToArgbDelegate");
						
						if 
						(
							sourceLocation.X + size.Width > fWidth || sourceLocation.Y + size.Height > Height ||
							destLocation.X + size.Width > bitmap.Width || destLocation.Y + size.Height > bitmap.Height
						)
						{
							throw new ArgumentOutOfRangeException("size");
						}
						
						int sourceIndex = sourceLocation.Y * Width + sourceLocation.X;
						T[] sourceArray = PixelArray;
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(destLocation, size), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb),
							() =>
							{
								unsafe
								{
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<size.Height; y++)
									{
										Rgb24 *scanLine = (Rgb24 *)scanLineBytes;
										
										for (int x=0; x<size.Width; x++)
											scanLine[x] = convertToRgbDelegate(sourceArray[sourceIndex+x]);
										
										sourceIndex += Width;
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies this bitmap to the given System.Drawing.Bitmap.
					/// It must be a 24-bit rgb bitmap for this to work.
					/// </summary>
					public void CopyToRgb24(Bitmap bitmap, Func<T, Rgb24> convertToRgbDelegate)
					{
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (convertToRgbDelegate == null)
							throw new ArgumentNullException("convertToRgbDelegate");

						if (bitmap.PixelFormat != PixelFormat.Format24bppRgb)
							throw new ArgumentException("bitmap must be Format24bppRgb.");
						
						int width = bitmap.Width;
						int height = bitmap.Height;
						if (width == Width && height == Height)
						{
							p_CopyToBitmapDirectRgb24(bitmap, convertToRgbDelegate);
							return;
						}
						
						CopyToRgb24(bitmap, new Point(0, 0), new Point(0, 0), new Size(Math.Min(Width, width), Math.Min(Height, height)), convertToRgbDelegate);
					}
				#endregion
				#region CopyFrom
					/// <summary>
					/// Copies the given System.Drawing.Bitmap to this bitmap.
					/// It must be a 24-bit rgb bitmap for this to work.
					/// </summary>
					public void CopyFromRgb24(Bitmap bitmap, Func<Rgb24, T> convertFromRgbDelegate)
					{
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (convertFromRgbDelegate == null)
							throw new ArgumentNullException("convertFromRgbDelegate");

						if (bitmap.PixelFormat != PixelFormat.Format24bppRgb)
							throw new ArgumentException("bitmap must be in Format24bppRgb format.");
						
						int width = Width;
						int height = Height;

						if (bitmap.Width != width || bitmap.Height != height)
						{
							CopyFromRgb24(bitmap, new Point(0, 0), new Point(0, 0), new Size(Math.Min(width, bitmap.Width), Math.Min(height, bitmap.Height)), convertFromRgbDelegate);
							return;
						}
						
						T[] baseArray = PixelArray;
					
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb),
							() =>
							{
								unsafe
								{
									int arrayIndex = -1;
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<height; y++)
									{
										Rgb24 *scanLine = (Rgb24 *)scanLineBytes;
										
										for (int x=0; x<width; x++)
										{
											Rgb24 rgb = scanLine[x];
											T value = convertFromRgbDelegate(rgb);

											arrayIndex++;
											baseArray[arrayIndex] = value;
										}
										
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies the given System.Drawing.Bitmap to this bitmap.
					/// It must be a 24-bit rgb bitmap for this to work.
					/// </summary>
					public void CopyFromRgb24(Bitmap bitmap, Func<Point, Rgb24, T> convertFromRgbDelegate)
					{
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (convertFromRgbDelegate == null)
							throw new ArgumentNullException("convertFromRgbDelegate");

						if (bitmap.PixelFormat != PixelFormat.Format24bppRgb)
							throw new ArgumentException("bitmap must be in Format24bppRgb format.");
						
						int width = Width;
						int height = Height;

						if (bitmap.Width != width || bitmap.Height != height)
						{
							CopyFromRgb24(bitmap, new Point(0, 0), new Point(0, 0), new Size(Math.Min(width, bitmap.Width), Math.Min(height, bitmap.Height)), convertFromRgbDelegate);
							return;
						}
						
						T[] baseArray = PixelArray;
					
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb),
							() =>
							{
								unsafe
								{
									int arrayIndex = -1;
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<height; y++)
									{
										Rgb24 *scanLine = (Rgb24 *)scanLineBytes;
										
										for (int x=0; x<width; x++)
										{
											Rgb24 rgb = scanLine[x];
											T value = convertFromRgbDelegate(new Point(x, y), rgb);

											arrayIndex++;
											baseArray[arrayIndex] = value;
										}
										
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}
					
					/// <summary>
					/// Copies a block from a System.Drawing.Bitmap to this ManagedBitmap using the given conversion
					/// delegate.
					/// </summary>
					public void CopyFromRgb24(Bitmap bitmap, Point sourceLocation, Point destLocation, Size size, Func<Rgb24, T> convertFromRgbDelegate)
					{
						if (PixelArray == null)
							return;
					
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (bitmap.PixelFormat != PixelFormat.Format24bppRgb)
							throw new ArgumentException("bitmap.PixelFormat must be Format24bppRgb.", "bitmap");
					
						if (sourceLocation.X < 0 || sourceLocation.Y < 0)
							throw new ArgumentOutOfRangeException("sourceLocation");
						
						if (destLocation.X < 0 || destLocation.Y < 0)
							throw new ArgumentOutOfRangeException("destLocation");
						
						if (convertFromRgbDelegate == null)
							throw new ArgumentNullException("convertFromRgbDelegate");
						
						if 
						(
							sourceLocation.X + size.Width > fWidth || sourceLocation.Y + size.Height > Height ||
							destLocation.X + size.Width > bitmap.Width || destLocation.Y + size.Height > bitmap.Height
						)
						{
							throw new ArgumentOutOfRangeException("size");
						}
						
						int destIndex = destLocation.Y * Width + destLocation.X;
						T[] destArray = PixelArray;
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(sourceLocation, size), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb),
							() =>
							{
								unsafe
								{
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<size.Height; y++)
									{
										Rgb24 *scanLine = (Rgb24 *)scanLineBytes;
										
										for (int x=0; x<size.Width; x++)
											destArray[destIndex+x] = convertFromRgbDelegate(scanLine[x]);
										
										destIndex += Width;
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies a block from a System.Drawing.Bitmap to this bitmap using the given conversion
					/// delegate.
					/// </summary>
					public void CopyFromRgb24(Bitmap bitmap, Point sourceLocation, Point destLocation, Size size, Func<Point, Rgb24, T> convertFromRgbDelegate)
					{
						if (PixelArray == null)
							return;
					
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (bitmap.PixelFormat != PixelFormat.Format24bppRgb)
							throw new ArgumentException("bitmap.PixelFormat must be Format24bppRgb.", "bitmap");
					
						if (sourceLocation.X < 0 || sourceLocation.Y < 0)
							throw new ArgumentOutOfRangeException("sourceLocation");
						
						if (destLocation.X < 0 || destLocation.Y < 0)
							throw new ArgumentOutOfRangeException("destLocation");
						
						if (convertFromRgbDelegate == null)
							throw new ArgumentNullException("convertFromRgbDelegate");
						
						if 
						(
							sourceLocation.X + size.Width > fWidth || sourceLocation.Y + size.Height > Height ||
							destLocation.X + size.Width > bitmap.Width || destLocation.Y + size.Height > bitmap.Height
						)
						{
							throw new ArgumentOutOfRangeException("size");
						}
						
						int destIndex = destLocation.Y * Width + destLocation.X;
						T[] destArray = PixelArray;
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(sourceLocation, size), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb),
							() =>
							{
								unsafe
								{
									byte *scanLineBytes = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<size.Height; y++)
									{
										Rgb24 *scanLine = (Rgb24 *)scanLineBytes;
										
										for (int x=0; x<size.Width; x++)
											destArray[destIndex+x] = convertFromRgbDelegate(new Point(x, y), scanLine[x]);
										
										destIndex += Width;
										scanLineBytes += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}
				#endregion
				#region CreateBitmapRgb24
					/// <summary>
					/// Creates a new 24-bit rgb System.Drawing.Bitmap using the given convert method.
					/// </summary>
					public Bitmap CreateBitmapRgb24(Func<T, Rgb24> convertToRgbDelegate)
					{
						if (PixelArray == null)
							throw new ArgumentException("This array must not be empty.", "array");
						
						if (convertToRgbDelegate == null)
							throw new ArgumentNullException("convertToRgbDelegate");
						
						Bitmap result = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
						p_CopyToBitmapDirectRgb24(result, convertToRgbDelegate);
						return result;
					}
				#endregion
			#endregion
			#region Create - CopyTo/From - System.Drawing.Bitmap - Indexed8/Grayscale
				#region CopyTo
					private void p_CopyToBitmapDirectIndexed8(Bitmap bitmap, Func<T, byte> convertToIndexDelegate)
					{
						int width = Width;
						int height = Height;
						T[] baseArray = PixelArray;
					
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed),
							() =>
							{
								unsafe
								{
									int arrayIndex = -1;
									byte *scanLine = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<height; y++)
									{
										for (int x=0; x<width; x++)
										{
											arrayIndex++;
											T value = baseArray[arrayIndex];
											byte index = convertToIndexDelegate(value);
											scanLine[x] = index;
										}
										
										scanLine += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies a part of this bitmap to a System.Drawing.Bitmap.
					/// </summary>
					public void CopyToIndexed8(Bitmap bitmap, Point sourceLocation, Point destLocation, Size size, Func<T, byte> convertToIndexDelegate)
					{
						if (PixelArray == null)
							return;
					
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (bitmap.PixelFormat != PixelFormat.Format8bppIndexed)
							throw new ArgumentException("bitmap.PixelFormat must be Format8bppIndexed.", "bitmap");
					
						if (sourceLocation.X < 0 || sourceLocation.Y < 0)
							throw new ArgumentOutOfRangeException("sourceLocation");
						
						if (destLocation.X < 0 || destLocation.Y < 0)
							throw new ArgumentOutOfRangeException("destLocation");
						
						if (convertToIndexDelegate == null)
							throw new ArgumentNullException("convertToIndexDelegate");
						
						if 
						(
							sourceLocation.X + size.Width > fWidth || sourceLocation.Y + size.Height > Height ||
							destLocation.X + size.Width > bitmap.Width || destLocation.Y + size.Height > bitmap.Height
						)
						{
							throw new ArgumentOutOfRangeException("size");
						}
						
						int sourceIndex = sourceLocation.Y * Width + sourceLocation.X;
						T[] sourceArray = PixelArray;
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(destLocation, size), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed),
							() =>
							{
								unsafe
								{
									byte *scanLine = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<size.Height; y++)
									{
										for (int x=0; x<size.Width; x++)
											scanLine[x] = convertToIndexDelegate(sourceArray[sourceIndex+x]);
										
										sourceIndex += Width;
										scanLine += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies this bitmap to the given System.Drawing.Bitmap.
					/// It must be a 8-bit indexed bitmap for this to work.
					/// </summary>
					public void CopyToIndexed8(Bitmap bitmap, Func<T, byte> convertToIndexDelegate)
					{
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (convertToIndexDelegate == null)
							throw new ArgumentNullException("convertToIndexDelegate");

						if (bitmap.PixelFormat != PixelFormat.Format8bppIndexed)
							throw new ArgumentException("bitmap must be in 8-bit indexed format.");
						
						int width = bitmap.Width;
						int height = bitmap.Height;
						if (width == Width && height == Height)
						{
							p_CopyToBitmapDirectIndexed8(bitmap, convertToIndexDelegate);
							return;
						}
						
						CopyToIndexed8(bitmap, new Point(0, 0), new Point(0, 0), new Size(Math.Min(Width, width), Math.Min(Height, height)), convertToIndexDelegate);
					}
				#endregion
				#region CopyFrom
					/// <summary>
					/// Copies the given System.Drawing.Bitmap to this bitmap.
					/// It must be a 8-bit indexed bitmap for this to work.
					/// </summary>
					public void CopyFromIndexed8(Bitmap bitmap, Func<byte, T> convertFromIndexDelegate)
					{
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (convertFromIndexDelegate == null)
							throw new ArgumentNullException("convertFromIndexDelegate");

						if (bitmap.PixelFormat != PixelFormat.Format8bppIndexed)
							throw new ArgumentException("bitmap must be in 8-bit indexed format.");
						
						int width = Width;
						int height = Height;

						if (bitmap.Width != width || bitmap.Height != height)
						{
							CopyFromIndexed8(bitmap, new Point(0, 0), new Point(0, 0), new Size(Math.Min(width, bitmap.Width), Math.Min(height, bitmap.Height)), convertFromIndexDelegate);
							return;
						}
						
						T[] baseArray = PixelArray;
					
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed),
							() =>
							{
								unsafe
								{
									int arrayIndex = -1;
									byte *scanLine = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<height; y++)
									{
										for (int x=0; x<width; x++)
										{
											byte index = scanLine[x];
											T value = convertFromIndexDelegate(index);

											arrayIndex++;
											baseArray[arrayIndex] = value;
										}
										
										scanLine += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies the given System.Drawing.Bitmap to this bitmap.
					/// It must be a 8-bit indexed bitmap for this to work.
					/// </summary>
					public void CopyFromIndexed8(Bitmap bitmap, Func<Point, byte, T> convertFromIndexDelegate)
					{
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (convertFromIndexDelegate == null)
							throw new ArgumentNullException("convertFromIndexDelegate");

						if (bitmap.PixelFormat != PixelFormat.Format8bppIndexed)
							throw new ArgumentException("bitmap must be in 8-bit indexed format.");
						
						int width = Width;
						int height = Height;

						if (bitmap.Width != width || bitmap.Height != height)
						{
							CopyFromIndexed8(bitmap, new Point(0, 0), new Point(0, 0), new Size(Math.Min(width, bitmap.Width), Math.Min(height, bitmap.Height)), convertFromIndexDelegate);
							return;
						}
						
						T[] baseArray = PixelArray;
					
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed),
							() =>
							{
								unsafe
								{
									int arrayIndex = -1;
									byte *scanLine = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<height; y++)
									{
										for (int x=0; x<width; x++)
										{
											byte index = scanLine[x];
											T value = convertFromIndexDelegate(new Point(x, y), index);

											arrayIndex++;
											baseArray[arrayIndex] = value;
										}
										
										scanLine += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}
					
					/// <summary>
					/// Copies a block from a System.Drawing.Bitmap to this ManagedBitmap using the given conversion
					/// delegate.
					/// </summary>
					public void CopyFromIndexed8(Bitmap bitmap, Point sourceLocation, Point destLocation, Size size, Func<byte, T> convertFromIndexDelegate)
					{
						if (PixelArray == null)
							return;
					
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (bitmap.PixelFormat != PixelFormat.Format8bppIndexed)
							throw new ArgumentException("bitmap.PixelFormat must be Format8bppIndexed.", "bitmap");
					
						if (sourceLocation.X < 0 || sourceLocation.Y < 0)
							throw new ArgumentOutOfRangeException("sourceLocation");
						
						if (destLocation.X < 0 || destLocation.Y < 0)
							throw new ArgumentOutOfRangeException("destLocation");
						
						if (convertFromIndexDelegate == null)
							throw new ArgumentNullException("convertFromIndexDelegate");
						
						if 
						(
							sourceLocation.X + size.Width > fWidth || sourceLocation.Y + size.Height > Height ||
							destLocation.X + size.Width > bitmap.Width || destLocation.Y + size.Height > bitmap.Height
						)
						{
							throw new ArgumentOutOfRangeException("size");
						}
						
						int destIndex = destLocation.Y * Width + destLocation.X;
						T[] destArray = PixelArray;
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(sourceLocation, size), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed),
							() =>
							{
								unsafe
								{
									byte *scanLine = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<size.Height; y++)
									{
										for (int x=0; x<size.Width; x++)
											destArray[destIndex+x] = convertFromIndexDelegate(scanLine[x]);
										
										destIndex += Width;
										scanLine += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}

					/// <summary>
					/// Copies a block from a System.Drawing.Bitmap to this bitmap using the given conversion
					/// delegate.
					/// </summary>
					public void CopyFromIndexed8(Bitmap bitmap, Point sourceLocation, Point destLocation, Size size, Func<Point, byte, T> convertFromIndexDelegate)
					{
						if (PixelArray == null)
							return;
					
						if (bitmap == null)
							throw new ArgumentNullException("bitmap");
						
						if (bitmap.PixelFormat != PixelFormat.Format8bppIndexed)
							throw new ArgumentException("bitmap.PixelFormat must be Format8bppIndexed.", "bitmap");
					
						if (sourceLocation.X < 0 || sourceLocation.Y < 0)
							throw new ArgumentOutOfRangeException("sourceLocation");
						
						if (destLocation.X < 0 || destLocation.Y < 0)
							throw new ArgumentOutOfRangeException("destLocation");
						
						if (convertFromIndexDelegate == null)
							throw new ArgumentNullException("convertFromIndexDelegate");
						
						if 
						(
							sourceLocation.X + size.Width > fWidth || sourceLocation.Y + size.Height > Height ||
							destLocation.X + size.Width > bitmap.Width || destLocation.Y + size.Height > bitmap.Height
						)
						{
							throw new ArgumentOutOfRangeException("size");
						}
						
						int destIndex = destLocation.Y * Width + destLocation.X;
						T[] destArray = PixelArray;
						BitmapData data = null;
						AbortSafe.Run
						(
							() => data = bitmap.LockBits(new Rectangle(sourceLocation, size), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed),
							() =>
							{
								unsafe
								{
									byte *scanLine = (byte *)data.Scan0.ToPointer();
									for (int y=0; y<size.Height; y++)
									{
										for (int x=0; x<size.Width; x++)
											destArray[destIndex+x] = convertFromIndexDelegate(new Point(x, y), scanLine[x]);
										
										destIndex += Width;
										scanLine += data.Stride;
									}
								}
							},
							() =>
							{
								if (data != null)
									bitmap.UnlockBits(data);
							}
						);
					}
				#endregion
				#region CreateBitmapIndexed8
					/// <summary>
					/// Creates a new 8-bit indexed System.Drawing.Bitmap using the given convert method.
					/// </summary>
					public Bitmap CreateBitmapIndexed8(Func<T, byte> convertToIndexDelegate)
					{
						if (PixelArray == null)
							throw new ArgumentException("This array must not be empty.", "array");
						
						if (convertToIndexDelegate == null)
							throw new ArgumentNullException("convertToIndexDelegate");
						
						Bitmap result = new Bitmap(Width, Height, PixelFormat.Format8bppIndexed);
						p_CopyToBitmapDirectIndexed8(result, convertToIndexDelegate);
						result.Palette = GrayscalePalette.Value;
						return result;
					}
				#endregion
			#endregion
		#endregion

		#region IBitmap Members
			Array IBitmap.PixelArray
			{
				get
				{
					return PixelArray;
				}
			}
			object IBitmap.this[int x, int y]
			{
				get
				{
					return this[x, y];
				}
				set
				{
					this[x, y] = (T)value;
				}
			}
		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Microsoft
United States United States
I started to program computers when I was 11 years old, as a hobbyist, programming in AMOS Basic and Blitz Basic for Amiga.
At 12 I had my first try with assembler, but it was too difficult at the time. Then, in the same year, I learned C and, after learning C, I was finally able to learn assembler (for Motorola 680x0).
Not sure, but probably between 12 and 13, I started to learn C++. I always programmed "in an object oriented way", but using function pointers instead of virtual methods.

At 15 I started to learn Pascal at school and to use Delphi. At 16 I started my first internship (using Delphi). At 18 I started to work professionally using C++ and since then I've developed my programming skills as a professional developer in C++ and C#, generally creating libraries that help other developers do their work easier, faster and with less errors.

Want more info or simply want to contact me?
Take a look at: http://paulozemek.azurewebsites.net/
Or e-mail me at: paulozemek@outlook.com

Codeproject MVP 2012, 2015 & 2016
Microsoft MVP 2013-2014 (in October 2014 I started working at Microsoft, so I can't be a Microsoft MVP anymore).

Comments and Discussions