I had a need to directly manipulate the bytes in a bitmap for my VB.Net app for Windows Phone. I found quite a few articles with The Google on how to do this in C#, using the unsafe keyword. That's a perfectly fine way of doing it for C# users. However, VB.Net does not have anything like the unsafe keyword, so there is no way to run unsafe (unmanaged) code blocks. Philosophically, this might be a "good" thing to Managed Code purists. I'm actually neutral on the issue. Still, just because you can't do arbitrary pointer and memory manipulation in VB.Net does not mean you can't do this very simple thing (dimming the color brightness of each byte of a bitmap). It's pretty easy and I can't believe nobody out there has posted how to do it this way VB.Net or C#. I came up with this code for the Compact Framework for Windows Phone specifically, but it will also work in the big Framework for big Windows. It will work in both VB.Net and C# just fine.
The key to this method is using the Marshal.Copy method. This copies a block of memory from an IntPtr to various types of arrays and then back again. Whereas the unsafe method directly manipulates the bytes in the bitmap, this code block copies the unmanaged bytes to an array, manipulates them, then copies them back to the unmanaged buffer. Using the 'unsafe' method is likely a hair faster, but in real world performance metrics, even on Windows Phone you would be hard pressed to see any noticeable difference between the two. Copying blocks of memory is a very fast operation.
This code adjusts the brightness of a bitmap, dimming it by half (a bit shift of >>1 for each color component of each pixel). Windows Phone natively uses 16bit bitmaps ('565' format, as in RRRRRGGGGGGBBBBB). The below code block can be adjusted to work with 24 and 32 bit bitmaps as needed. It's actually easier to use 24 and 32 bit bitmaps as you just manipulate the brightness of individual Byte primitives without needing to break apart the Int16 (short) using bit masks, as below. However, the act of converting the 16 bit bitmap to a 32 bit bitmap on Windows Phone seems to cause a significant a performance hit! So don't do that on Windows Phone. Stay with the 16-bit bitmap and use bit masks, as I did below. For big Windows, you will want to use 32 bit bitmaps, not 16 bit bitmaps.
Private Sub DimBitmapByHalf(ByRef bmp As Bitmap)
Dim bmd As Imaging.BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format16bppRgb565)
Try
Dim bufLen As Integer = (bmd.Stride * bmd.Height) / 2 ' Because bmd.Stride and bmd.Height are in units of 8-bit bytes
Dim buf(bufLen - 1) As Short
Dim r As Short
Dim g As Short
Dim b As Short
System.Runtime.InteropServices.Marshal.Copy(bmd.Scan0, buf, 0, bufLen)
For i = 0 To bufLen - 1
' RRRRR GGGGGG BBBBB
r = (buf(i) >> 1) And &H7800 ' 01111 000000 00000
g = (buf(i) >> 1) And &H3E0 ' 00000 011111 00000
b = (buf(i) >> 1) And &HF ' 00000 000000 01111
buf(i) = r Or g Or b
Next
System.Runtime.InteropServices.Marshal.Copy(buf, 0, bmd.Scan0, bufLen)
Finally
bmp.UnlockBits(bmd)
End Try
End Sub