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