为什么这个黑白位图到Bool数组创建了正确的图像,但设置了错误的Bool数量(C#)

为什么这个黑白位图到Bool数组创建了正确的图像,但设置了错误的Bool数量(C#),c#,bitmap,bytearray,unsafe-pointers,C#,Bitmap,Bytearray,Unsafe Pointers,这是一个函数,它获取一个透明的白色图像,并尝试将其转换为布尔数组 我的单元测试代码给出了我期望的两个图像(见下文),但是“numberOfMasked”总是比我期望的高。例如,如果“maskBuffer”标记了一个像素(请参见下面的mask_image_test.bmp),则尽管“mask_bool_test70.bmp”)创建了一个标记了一个像素的图像。出于某种原因,标记为true的bool的实际数量要高得多,而且似乎是随机的。我看到它的范围从25到70 public static bool[

这是一个函数,它获取一个透明的白色图像,并尝试将其转换为布尔数组

我的单元测试代码给出了我期望的两个图像(见下文),但是“numberOfMasked”总是比我期望的高。例如,如果“maskBuffer”标记了一个像素(请参见下面的mask_image_test.bmp),则尽管“mask_bool_test70.bmp”)创建了一个标记了一个像素的图像。出于某种原因,标记为true的bool的实际数量要高得多,而且似乎是随机的。我看到它的范围从25到70

public static bool[] ConvertImageToBoolAray(Bitmap maskbuffer)
    {
        bool[] mask = null;
        int w = maskbuffer.Width;
        int h = maskbuffer.Height;

        #region unit_test
            maskbuffer.Save("mask_image_test.bmp");
        #endregion

        lock (maskbuffer)
        {
            BitmapData bmpData = maskbuffer.LockBits(new Rectangle(0, 0, w, h),
                ImageLockMode.ReadOnly,
                PixelFormat.Format8bppIndexed);

            const int numBmpChannel = 1;
            int maskIndex = 0;
            int bmpIndex = 0;

            unsafe
            {

                byte* pixels = (byte*) bmpData.Scan0;
                int numPixels = w*h;

                mask = new bool[numPixels];

                for (;
                    maskIndex < numPixels;
                    bmpIndex += numBmpChannel, maskIndex++)
                {
                    byte red = pixels[bmpIndex];
                    bool masked = red != 0;
                    mask[maskIndex] = masked;
                }

            }
            maskbuffer.UnlockBits(bmpData);
        }

        #region unit_test
            byte[] boolAsByte = Array.ConvertAll(mask, b => b ? (byte)1 : (byte)0);
            Bitmap maskBitmap = GLImageConvertor.ConvertByteBufferToBitmap(boolAsByte, w, h, PixelFormat.Format8bppIndexed);
            int numberOfMasked = mask.Count(b => b);
            maskBitmap.Save("mask_bool_test" + numberOfMasked + ".bmp");
        #endregion


        return mask;
    }
public static bool[]ConvertImageToBoolAray(位图maskbuffer)
{
bool[]掩码=null;
int w=掩码缓冲宽度;
int h=遮罩缓冲高度;
#区域单位检验
Save(“mask_image_test.bmp”);
#端区
锁(maskbuffer)
{
BitmapData bmpData=maskbuffer.LockBits(新矩形(0,0,w,h),
ImageLockMode.ReadOnly,
像素格式;
常数int numBmpChannel=1;
int-maskIndex=0;
int bmpIndex=0;
不安全的
{
字节*像素=(字节*)bmpData.Scan0;
int numPixels=w*h;
掩码=新布尔值[numPixels];
对于(;
maskIndexb?(字节)1:(字节)0);
位图maskBitmap=GLImageConvertor.ConvertByteBufferToBitmap(boolAsByte,w,h,PixelFormat.format8bppinged);
int numberOfMasked=mask.Count(b=>b);
保存(“mask\u bool\u test”+numberOfMasked+”.bmp);
#端区
返回掩码;
}
有人对这种奇怪的行为有什么想法吗

调试表明,在“像素”内存中,有一些我不希望看到的字节,我希望看到一个字节设置为“FF”,但我有随机的数据部分

mask\u image\u test.bmp:

mask\u bool\u test70.bmp:


你在算法中需要考虑的差异。

跨距是一行像素(扫描线)的宽度,四舍五入到四字节边界

因为70不能被4整除,所以有一些空闲像素,可能被随机数据填充

你需要像这样的东西

int count = 0;
int stride = bmpData.Stride;

for (int column = 0; column < bmpData.Height; column++)
{
    for (int row = 0; row < bmpData.Width; row++)
    {
        red = pixels[(column * stride) + (row * 3) + 2]);
    }
}
int count=0;
int stride=bmpData.stride;
for(int column=0;column
正如Thomas指出的,我没有考虑stride!我一秒钟也没想到C会把位图中多余的字节打包掉。但在这种情况下肯定是宽度!=步幅(宽度为111,但步幅为112)。我决定编写一个更简单的版本,完全避免使用原始缓冲区,以避免棘手的问题(而且我再也不用担心原始缓冲区了)

public static bool[]ConvertImageToBoolAray(位图maskbuffer)
{
bool[]掩码=null;
int w=掩码缓冲宽度;
int h=遮罩缓冲高度;
#区域单位检验
//Save(“mask_image_test.bmp”);
#端区
锁(maskbuffer)
{
int numPixels=w*h;
掩码=新布尔值[numPixels];
对于(int y=0;yb?(字节)1:(字节)0);
//位图maskBitmap=GLImageConvertor.ConvertByteBufferToBitmap(boolAsByte,w,h,PixelFormat.format8bppinged);
//int numberOfMasked=mask.Count(b=>b);
//保存(“mask\u bool\u test”+numberOfMasked+”.bmp);
#端区
返回掩码;
}
如果有人想发布正确的原始缓冲区版本,请继续,我会将您的标记为最佳答案

---更新-- 添加了返工版本以直接使用缓冲区

   private static bool[] ConvertImageToBoolArayUnsafe(Bitmap maskbuffer)
    {
        bool[] mask = null;
        int w = maskbuffer.Width;
        int h = maskbuffer.Height;

        #region unit_test
            //maskbuffer.Save("mask_image_test.bmp");
        #endregion

        lock (maskbuffer)
        {
            BitmapData bmpData = maskbuffer.LockBits(new Rectangle(0, 0, w, h),
                ImageLockMode.ReadOnly,
                PixelFormat.Format8bppIndexed);


            int stride = bmpData.Stride;
            unsafe
            {

                byte* pixels = (byte*) bmpData.Scan0;


                mask = new bool[w * h];

                for (int y = 0; y < h; ++y)
                {
                    for (int x = 0; x < w; ++x)
                    {
                        int imageIndex = x + (y * stride);
                        byte color = pixels[imageIndex];
                        int maskIndex = x + (y * w);
                        mask[maskIndex] = color != 0;
                    }
                }

            }
            maskbuffer.UnlockBits(bmpData);
        }

        #region unit_test
           // byte[] boolAsByte = Array.ConvertAll(mask, b => b ? (byte)1 : (byte)0);
          //  Bitmap maskBitmap = GLImageConvertor.ConvertByteBufferToBitmap(boolAsByte, w, h, PixelFormat.Format8bppIndexed);
          //  int numberOfMasked = mask.Count(b => b);
          //  maskBitmap.Save("mask_bool_test" + numberOfMasked + ".bmp");
        //check equality to safe version (as that is correct)
        #endregion


        return mask;
    }
private static bool[]ConvertImageToBoolArayUnsafe(位图掩码缓冲)
{
bool[]掩码=null;
int w=掩码缓冲宽度;
int h=遮罩缓冲高度;
#区域单位检验
//Save(“mask_image_test.bmp”);
#端区
锁(maskbuffer)
{
BitmapData bmpData=maskbuffer.LockBits(新矩形(0,0,w,h),
ImageLockMode.ReadOnly,
像素格式;
int stride=bmpData.stride;
不安全的
{
字节*像素=(字节*)bmpData.Scan0;
掩码=新布尔值[w*h];
对于(int y=0;y   private static bool[] ConvertImageToBoolArayUnsafe(Bitmap maskbuffer)
    {
        bool[] mask = null;
        int w = maskbuffer.Width;
        int h = maskbuffer.Height;

        #region unit_test
            //maskbuffer.Save("mask_image_test.bmp");
        #endregion

        lock (maskbuffer)
        {
            BitmapData bmpData = maskbuffer.LockBits(new Rectangle(0, 0, w, h),
                ImageLockMode.ReadOnly,
                PixelFormat.Format8bppIndexed);


            int stride = bmpData.Stride;
            unsafe
            {

                byte* pixels = (byte*) bmpData.Scan0;


                mask = new bool[w * h];

                for (int y = 0; y < h; ++y)
                {
                    for (int x = 0; x < w; ++x)
                    {
                        int imageIndex = x + (y * stride);
                        byte color = pixels[imageIndex];
                        int maskIndex = x + (y * w);
                        mask[maskIndex] = color != 0;
                    }
                }

            }
            maskbuffer.UnlockBits(bmpData);
        }

        #region unit_test
           // byte[] boolAsByte = Array.ConvertAll(mask, b => b ? (byte)1 : (byte)0);
          //  Bitmap maskBitmap = GLImageConvertor.ConvertByteBufferToBitmap(boolAsByte, w, h, PixelFormat.Format8bppIndexed);
          //  int numberOfMasked = mask.Count(b => b);
          //  maskBitmap.Save("mask_bool_test" + numberOfMasked + ".bmp");
        //check equality to safe version (as that is correct)
        #endregion


        return mask;
    }