Skip to content
Advertisement

Why would this image threshold work in windows but not mono / linux?

I have a relatively simple threshold function that’s using unsafe code. This works a treat in Windows, however, in Mono on linux, no thresholding takes place. It’s difficult to debug as it’s on Linux only, I’ve checked the bitsPerPixel is correct along with the height h, width w and stride ws are all correct as well.

What else can I do to narrow it down, or is there a common gotcha here?

public void threshold(Bitmap bmp, int thresh)
        {
            var bitsPerPixel = Image.GetPixelFormatSize(bmp.PixelFormat) / 8;

            BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
            ImageLockMode.ReadOnly, bmp.PixelFormat);
            unsafe
            {
                byte* p = (byte*)(void*)bmData.Scan0.ToPointer();
                int h = bmp.Height;
                int w = bmp.Width;
                int ws = bmData.Stride;

                for (int i = 0; i < h; i++)
                {
                    byte* row = &p[i * ws];
                    for (int j = 0; j < w * bitsPerPixel; j += bitsPerPixel)
                    {
                        for (var k = 0; k < bitsPerPixel; k++)
                        {
                            row[j + k] = (byte)((row[j + k] > (byte)thresh) ? 255 : 0);
                        }
                    }
                }
            }
            bmp.UnlockBits(bmData);
        }

Advertisement

Answer

Set ImageLockMode to ReadWrite:

BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                                             ImageLockMode.ReadWrite, bmp.PixelFormat);

Example:

public unsafe void Threshold(Bitmap bmp, int thresh)
{
    var bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);
    var bitsPerPixel = Image.GetPixelFormatSize(bmp.PixelFormat);
    var p = (byte*)bmData.Scan0.ToPointer();
    for (int i = 0; i < bmData.Height; ++i)
    {
        for (int j = 0; j < bmData.Width; ++j)
        {
            byte* data = p + i * bmData.Stride + j * bitsPerPixel / 8;
            data[0] = (byte)((data[0] > thresh) ? 255 : 0);
            data[1] = (byte)((data[1] > thresh) ? 255 : 0);
            data[2] = (byte)((data[2] > thresh) ? 255 : 0);
        }
    }
    bmp.UnlockBits(bmData);
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement