using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace gfoidl.Visualization
{
public sealed class FastBitmap
{
#region Felder
private bool _isLocked = false;
private BitmapData _bmpData;
private byte[] _rgbValues;
private IntPtr _bmpPtr;
#endregion
//---------------------------------------------------------------------
#region Eigenschaften
private int _width;
///
/// Die Breite der Bitmap.
///
public int Width { get { return _width; } }
//---------------------------------------------------------------------
private int _height;
///
/// Die Höhe der Bitmap.
///
public int Height { get { return _height; } }
//---------------------------------------------------------------------
private bool _isAlphaBitmap;
///
/// Gibt an ob die Bitmap einen Alpha-Kanal hat.
///
public bool IsAlphaBitmpa { get { return _isAlphaBitmap; } }
//---------------------------------------------------------------------
private Bitmap _bitmap;
///
/// Das Bitmap.
///
public Bitmap Bitmap { get { return _bitmap; } }
#endregion
//---------------------------------------------------------------------
#region Konstruktor
///
/// Erstellt eine neues Instanz von .
///
/// Das Bitmap.
///
/// ist null.
///
///
/// Es kann kein indiziertes Bild gesperrt werden.
///
public FastBitmap(Bitmap bitmap)
{
if (bitmap == null)
throw new ArgumentNullException();
if (bitmap.PixelFormat == (bitmap.PixelFormat | PixelFormat.Indexed))
throw new ArgumentException();
//-----------------------------------------------------------------
_bitmap = bitmap;
_isAlphaBitmap =
bitmap.PixelFormat == (bitmap.PixelFormat | PixelFormat.Alpha);
_width = bitmap.Width;
_height = bitmap.Height;
}
#endregion
//---------------------------------------------------------------------
#region Methoden
///
/// Sperrt die Bitmap.
///
///
/// Das Bild ist bereits gesperrt.
///
public void Lock()
{
if (_isLocked)
throw new Exception("Already locked.");
_bmpData = _bitmap.LockBits(
new Rectangle(0, 0, _width, _height),
ImageLockMode.ReadWrite,
_bitmap.PixelFormat);
_bmpPtr = _bmpData.Scan0;
int bytes = _width * _height;
bytes = _isAlphaBitmap ? bytes * 4 : bytes * 3;
_rgbValues = new byte[bytes];
// Kopieren der RGB-Werte von der Bitmap:
Marshal.Copy(_bmpPtr, _rgbValues, 0, _rgbValues.Length);
_isLocked = true;
}
//---------------------------------------------------------------------
///
/// Entsperrt die Bitmap.
///
///
/// Das Bild ist nicht gesperrt.
///
public void Unlock()
{
if (!_isLocked)
throw new Exception("Not locked.");
// Zurückkopieren der RGB-Werte in die Bitmap:
Marshal.Copy(_rgbValues, 0, _bmpPtr, _rgbValues.Length);
// Entsperren:
_bitmap.UnlockBits(_bmpData);
_isLocked = false;
}
//---------------------------------------------------------------------
///
/// Setzt den Hintergrund des Bitmaps.
///
/// Die Hintergrundfarbe.
///
/// Das Bild ist nicht gesperrt.
///
public void Clear(Color color)
{
if (!_isLocked)
throw new Exception("Not locked.");
int step = _isAlphaBitmap ? 4 : 3;
for (int i = 0; i < _rgbValues.Length; i += step)
{
_rgbValues[i] = color.B;
_rgbValues[i + 1] = color.G;
_rgbValues[i + 2] = color.R;
if (_isAlphaBitmap)
_rgbValues[i + 3] = color.A;
}
}
//---------------------------------------------------------------------
///
/// Setzt das Pixel auf die angegebene Farbe.
///
/// x-Koordinate des Pixel.
/// y-Koordinate des Pixel.
/// Die Farbe des Pixel.
///
/// Das Bild ist nicht gesperrt.
///
public void SetPixel(int x, int y, Color color)
{
if (!_isLocked)
throw new Exception("Not locked.");
int index = _isAlphaBitmap ?
(y * _width + x) * 4 :
(y * _width + x) * 3;
_rgbValues[index] = color.B;
_rgbValues[index + 1] = color.G;
_rgbValues[index + 2] = color.R;
if (_isAlphaBitmap)
_rgbValues[index + 3] = color.A;
}
//---------------------------------------------------------------------
///
/// Liest die Farbe des Pixels aus.
///
/// x-Koordinate des Pixel.
/// y-Koordinate des Pixel.
/// Die Farbe des Pixel.
///
/// Das Bild ist nicht gesperrt.
///
public Color GetPixel(int x, int y)
{
if (!_isLocked)
throw new Exception("Not locked");
int index = _isAlphaBitmap ?
(y * _width + x) * 4 :
(y * _width + x) * 3;
int b = _rgbValues[index];
int g = _rgbValues[index + 1];
int r = _rgbValues[index + 2];
if (!_isAlphaBitmap)
return Color.FromArgb(r, g, b);
else
return Color.FromArgb(_rgbValues[index + 3], r, g, b);
}
#endregion
}
}