Search code examples
c#.netbitmapsystem.drawing

Manipulating BitmapData, only 1/3rd gets altered


My goal is to load my 256x256 pixel sized bitmap and assign for each pixel either a white or black color value, depending on whether the actual value falls below a certain threshold.

Problem is, only 1/3 of the width the bitmap has the new pixel data, even though the inner for-statement iterates over the whole width.

unsafe
{
    BitmapData bitmapData = bitmap.LockBits(new Rectangle(0,0, 256, 256), ImageLockMode.ReadWrite, bitmap.PixelFormat);

    for (int j = 0; j < bitmapData.Height; j++)
    {
        byte* row = (byte*)bitmapData.Scan0 + (j * bitmapData.Stride);
        for (int k = 0; k < bitmapData.Width; k++)
        {
            if (row[k] <= TresholdFilter)
                row[k] = 0;
            if (row[k] > 0)
                row[k] = 255;
        }
    }
    bitmap.UnlockBits(bitmapData);
}

Example Picture


Solution

  • Your problem is that you treat a 24bpp image as 8bpp. Each Pixel is described by 3 Bytes, not one. The code could be modified in the following way:

    unsafe
    {
        BitmapData bitmapData = bitmap.LockBits(new Rectangle(0,0, 256, 256),ImageLockMode.ReadWrite, bitmap.PixelFormat);
    
        for (int j = 0; j < bitmapData.Height; j++)
        {
            byte* row = (byte*)bitmapData.Scan0 + (j * bitmapData.Stride);
            for (int k = 0; k < bitmapData.Width * 3; k += 3)
            {
                if (row[k] <= TresholdFilter)
                {
                   row[k] = 0;
                   row[k + 1] = 0;
                   row[k + 2] = 0;
                }
                if (row[k] > 0)
                {
                   row[k] = 255;
                   row[k + 1] = 255;
                   row[k + 2] = 255;
                }
            }
        }
        bitmap.UnlockBits(bitmapData);
    }
    

    Just to be sure you could check if row[k], k + 1 and k + 2 are all below/above the ThresholdFilter, but you only need that if it could happen that the image isn't grayscaled.

    Additionally you should probably check at the beginning if the image is in fact in 24bppRgb format to avoid crashing the application if it actually isn't.