Skip to content

Instantly share code, notes, and snippets.

@GeirGrusom
Created September 18, 2014 12:23
Show Gist options
  • Save GeirGrusom/90e99545b3817e46b4fa to your computer and use it in GitHub Desktop.
Save GeirGrusom/90e99545b3817e46b4fa to your computer and use it in GitHub Desktop.
Example code for manipulating bits in a Bitmap using C# and unsafe
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
namespace BitBlastBitmap
{
static class Program
{
private static void Swap<T>(ref T a, ref T b)
{
T tmp = a;
a = b;
b = tmp;
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
const int width = 800;
const int height = 600;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
bool appRunning = true;
PictureBox box;
var form = new Form
{
ClientSize = new Size(width, height),
Text = "Bitmap BitBashing",
FormBorderStyle = FormBorderStyle.FixedDialog,
MaximizeBox = false,
};
form.Controls.Add(box = new PictureBox { Dock = DockStyle.Fill});
var buffer1 = new Bitmap(form.ClientSize.Width, form.ClientSize.Height, PixelFormat.Format32bppPArgb);
using(var bg = Graphics.FromImage(buffer1))
bg.Clear(Color.Black);
var buffer2 = new Bitmap(buffer1);
box.Paint += (sender, e) => e.Graphics.DrawImageUnscaled(buffer1, 0, 0);
var font = new Font("Arial", 24);
form.Show();
form.Closing += (sender, args) => appRunning = false;
float angle = 0f;
float angleIncrease = (float)Math.PI/180;
try
{
var sf = new StringFormat(StringFormatFlags.NoWrap)
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
while (appRunning)
{
angle += angleIncrease;
ProcessBitmap(buffer1, buffer2, width, height);
using(var g = Graphics.FromImage(buffer2))
g.DrawString("Hello World!", font, Brushes.White, new PointF(width / 2 + (float)Math.Cos(angle) * 60, height / 2 + (float)Math.Sin(angle) * 60), sf);
Swap(ref buffer1, ref buffer2);
box.Invalidate();
Application.DoEvents();
}
}
finally
{
buffer1.Dispose();
buffer2.Dispose();
}
}
private static readonly Random rnd = new Random();
private static unsafe void ProcessBitmap(Bitmap buffer1, Bitmap buffer2, int width, int height)
{
var bmp1 = buffer1.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
var bmp2 = buffer2.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
try
{
var destination = (uint*)bmp2.Scan0.ToPointer();
var source = ((uint*)bmp1.Scan0.ToPointer()) + width;
int screenSize = width * height;
int screenWidth = width;
destination += screenWidth ;
for(int i = screenWidth * 2; i < screenSize - screenWidth; i++, source++)
{
*destination++ = unchecked
((source[screenWidth << 1] >> 2) & 0x3F3F3F) +
((source[1] >> 2) & 0x3F3F3F) +
((source[-1] >> 2) & 0x3F3F3F) +
((source[screenWidth] >> 2) & 0x3F3F3F) | 0xff000000;
}
var bottomPointer = ((uint*) bmp2.Scan0.ToPointer()) + width * height - width;
for (int i = 0; i < width; i++)
{
var c = (uint)rnd.Next(255);
*bottomPointer++ = ((c) | (c << 8) | (c << 16) | unchecked (0xff000000));
}
}
finally
{
buffer1.UnlockBits(bmp1);
buffer2.UnlockBits(bmp2);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment