Почему этот порог изображения работает в Windows, но не в моно/линукс?

У меня есть относительно простая пороговая функция, использующая небезопасный код. Это работает в Windows, однако в Mono на Linux пороговое значение не используется. Это сложно отлаживать, так как это только для Linux, я проверил, что bitsPerPixel верен, а высота h, ширина w и шаг ws также верны.

Что еще я могу сделать, чтобы сузить его, или здесь есть общая ошибка?

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);
        }

person user3791372    schedule 27.05.2017    source источник


Ответы (1)


Установите ImageLockMode на ReadWrite:

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

Пример:

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);
person SushiHangover    schedule 27.05.2017
comment
Похоже, что GDIPlus.GdipBitmapLockBits соответствует типу ImageLockMode, переданному в Bitmap.LockBits, мне нужно сравнить справочный источник MS в том, как он обрабатывает этот флаг... Вы должны указать ошибку на bugzilla.xamarin.com, чтобы сообщить о несоответствии. - person SushiHangover; 27.05.2017