Created
April 8, 2020 09:12
-
-
Save mjs3339/7478496fde2dee7db60cd32dfac5e88c to your computer and use it in GitHub Desktop.
Direct Access Pixel Data, GetPixel, SetPixel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Drawing; | |
using System.Drawing.Imaging; | |
public unsafe class MemoryBitmap : IDisposable | |
{ | |
private readonly BitmapData _bmpData; | |
private readonly int _depth; | |
private readonly Bitmap _memoryBitmap; | |
private readonly byte* _pfp; | |
private readonly int _stride; | |
public MemoryBitmap(Bitmap bitmap) | |
{ | |
_memoryBitmap = bitmap ?? throw new Exception("Bitmap cannot be null"); | |
if (_memoryBitmap.PixelFormat != PixelFormat.Format32bppArgb && _memoryBitmap.PixelFormat != PixelFormat.Format24bppRgb && _memoryBitmap.PixelFormat != PixelFormat.Format8bppIndexed) | |
{ | |
var clone = new Bitmap(_memoryBitmap.Width, _memoryBitmap.Height, PixelFormat.Format32bppArgb); | |
using (var gr = Graphics.FromImage(clone)) | |
{ | |
gr.DrawImage(_memoryBitmap, new Rectangle(0, 0, clone.Width, clone.Height)); | |
_memoryBitmap = clone; | |
} | |
} | |
Width = _memoryBitmap.Width; | |
Height = _memoryBitmap.Height; | |
var rect = new Rectangle(0, 0, _memoryBitmap.Width, _memoryBitmap.Height); | |
try | |
{ | |
_bmpData = _memoryBitmap.LockBits(rect, ImageLockMode.ReadWrite, _memoryBitmap.PixelFormat); | |
} | |
catch (Exception ex) | |
{ | |
throw new Exception("Could not lock bitmap", ex.InnerException); | |
} | |
_depth = Image.GetPixelFormatSize(_bmpData.PixelFormat) / 8; | |
_pfp = (byte*) _bmpData.Scan0.ToPointer(); | |
_stride = _bmpData.Stride; | |
} | |
public int Width | |
{ | |
get; | |
} | |
public int Height | |
{ | |
get; | |
} | |
public void Dispose() | |
{ | |
Dispose(true); | |
GC.SuppressFinalize(this); | |
} | |
protected virtual void Dispose(bool disposing) | |
{ | |
if (!disposing) | |
return; | |
if (_memoryBitmap != null) | |
_memoryBitmap.UnlockBits(_bmpData); | |
} | |
private byte* PixelPointer(int x, int y) | |
{ | |
return _pfp + y * _stride + x * _depth; | |
} | |
public Color GetPixel(int x, int y) | |
{ | |
if (x < 0 || y < 0 || x >= Width || y >= Width) | |
throw new Exception("Coordinates out of range"); | |
int a, r, g, b; | |
var p = PixelPointer(x, y); | |
if (_memoryBitmap.PixelFormat == PixelFormat.Format32bppArgb) | |
{ | |
b = *p++; | |
g = *p++; | |
r = *p++; | |
a = *p; | |
return Color.FromArgb(a,r, g, b); | |
} | |
if (_memoryBitmap.PixelFormat == PixelFormat.Format24bppRgb) | |
{ | |
b = *p++; | |
g = *p++; | |
r = *p; | |
return Color.FromArgb(r, g, b); | |
} | |
if (_memoryBitmap.PixelFormat == PixelFormat.Format8bppIndexed) | |
{ | |
a = *p; | |
return Color.FromArgb(a, a, a); | |
} | |
return default; | |
} | |
public void SetPixel(int x, int y, Color col) | |
{ | |
if (x < 0 || y < 0 || x >= Width || y >= Width) | |
throw new Exception("Coordinates out of range"); | |
var p = PixelPointer(x, y); | |
if (_memoryBitmap.PixelFormat == PixelFormat.Format32bppArgb) | |
{ | |
*p++ = col.B; | |
*p++ = col.G; | |
*p++ = col.R; | |
*p = col.A; | |
return; | |
} | |
if (_memoryBitmap.PixelFormat == PixelFormat.Format24bppRgb) | |
{ | |
*p++ = col.B; | |
*p++ = col.G; | |
*p = col.R; | |
return; | |
} | |
if (_memoryBitmap.PixelFormat == PixelFormat.Format8bppIndexed) | |
*p = col.B; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment