Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Created April 8, 2020 09:12
Show Gist options
  • Save mjs3339/7478496fde2dee7db60cd32dfac5e88c to your computer and use it in GitHub Desktop.
Save mjs3339/7478496fde2dee7db60cd32dfac5e88c to your computer and use it in GitHub Desktop.
Direct Access Pixel Data, GetPixel, SetPixel
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