Search code examples
c#bitmapbitmapdata

How to do Bitmap processing using BitmapData?


I've built a small test example where the goal is to change all pixels in my .png to white. I'm doing it using BitmapData, because as I understand it, the performance is better. If I can get it working; then I can change which pixels I'm changing and add different conditions to altering a pixel color. But I'm stuck on just this simple test.

Here's my C# :

public static void TestConvertAllBlackBitmapToAllWhite()
{
    string allBlackPNGFullFilePath = @"C:\Users\{Username}\Desktop\50x50AllBlack.png";
    Bitmap allBlackBitmap = new Bitmap(allBlackPNGFullFilePath);

    Bitmap newBitmap = (Bitmap)allBlackBitmap.Clone();

    Size size = newBitmap.Size;
    PixelFormat pixelFormat = newBitmap.PixelFormat;
    byte bitDepth = (byte)(pixelFormat == PixelFormat.Format32bppArgb ? 4 : 3);
    Rectangle rectangle = new Rectangle(Point.Empty, size);
    BitmapData bitmapData = newBitmap.LockBits(rectangle, ImageLockMode.ReadOnly, pixelFormat);
    int dataSize = bitmapData.Stride * bitmapData.Height;
    byte[] data = new byte[dataSize];
    Marshal.Copy(bitmapData.Scan0, data, 0, dataSize);

    Color white = Color.White;

    for (int y = 0; y < size.Height; y++)
    {
        for (int x = 0; x < size.Width; x++)
        {
            // Get Index
            int index = y * bitmapData.Stride + x * bitDepth;

            // Set Pixel Color
            data[index] = white.B;
            data[index + 1] = white.G;
            data[index + 2] = white.R;
        }
    }

    Marshal.Copy(data, 0, bitmapData.Scan0, data.Length);
    newBitmap.UnlockBits(bitmapData);

    // Save New Converted Bitmap
    string originalFileName = Path.GetFileNameWithoutExtension(allBlackPNGFullFilePath);
    string directory = Path.GetDirectoryName(allBlackPNGFullFilePath);
    string newBitmapFileName = originalFileName + "_Converted";
    string newBitmapFullFileName = directory + Path.DirectorySeparatorChar.ToString() + newBitmapFileName + ".png";

    newBitmap.Save(newBitmapFullFileName, ImageFormat.Png);
}

My input is an all black 50x50 .png : All Black 50 x 50 PNG

The problem is the output I'm getting is another all black .png instead of an all white one.

How can I fix up my simple example code to produce an all white .png as a result?

Any help / guidance will be really appreciated.


Solution

  • As pointed out by @Taw

    It's a little thing on this line :

    BitmapData bitmapData = newBitmap.LockBits(rectangle, ImageLockMode.ReadOnly, pixelFormat);
    

    The ImageLockMode is set to ReadOnly. Since I'm making changes to the BitmapData while looping; the ImageLockMode should be ReadWrite