Created
September 18, 2014 12:23
-
-
Save GeirGrusom/90e99545b3817e46b4fa to your computer and use it in GitHub Desktop.
Example code for manipulating bits in a Bitmap using C# and unsafe
This file contains 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; | |
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