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