Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取像素';使用C语言的单色图像的颜色#_C#_Image_Image Processing_Monochrome - Fatal编程技术网

C# 获取像素';使用C语言的单色图像的颜色#

C# 获取像素';使用C语言的单色图像的颜色#,c#,image,image-processing,monochrome,C#,Image,Image Processing,Monochrome,正如主题所说,我有一个.bmp图像,我需要编写一个能够获得图像任何像素颜色的代码。这是一个1bpp(索引)图像,因此颜色将为黑色或白色。以下是我目前拥有的代码: //This method locks the bits of line of pixels private BitmapData LockLine(Bitmap bmp, int y) { Rectangle lineRect = new Rectangle(0, y, bmp.Width, 1

正如主题所说,我有一个
.bmp
图像,我需要编写一个能够获得图像任何像素颜色的代码。这是一个1bpp(索引)图像,因此颜色将为黑色或白色。以下是我目前拥有的代码:

    //This method locks the bits of line of pixels
    private BitmapData LockLine(Bitmap bmp, int y)
    {
        Rectangle lineRect = new Rectangle(0, y, bmp.Width, 1);
        BitmapData line = bmp.LockBits(lineRect,
                                       ImageLockMode.ReadWrite,
                                       bmp.PixelFormat);
        return line;
    }
    //This method takes the BitmapData of a line of pixels
    //and returns the color of one which has the needed x coordinate
    private Color GetPixelColor(BitmapData data, int x)
    {
        //I am not sure if this line is correct
        IntPtr pPixel = data.Scan0 + x; 
        //The following code works for the 24bpp image:
        byte[] rgbValues = new byte[3];
        System.Runtime.InteropServices.Marshal.Copy(pPixel, rgbValues, 0, 3);
        return Color.FromArgb(rgbValues[2], rgbValues[1], rgbValues[0]);
    }
但我如何才能使它适用于1bpp图像?如果我只从指针读取一个字节,它总是有
255
值,因此我认为我做错了什么。
请不要建议使用
System.Drawing.Bitmap.GetPixel
方法,因为它的运行速度太慢,我希望代码尽可能快地运行。 提前谢谢

编辑: 以下是代码,可以很好地工作,以防有人需要:

    private Color GetPixelColor(BitmapData data, int x)
    {
        int byteIndex = x / 8;
        int bitIndex = x % 8;
        IntPtr pFirstPixel = data.Scan0+byteIndex;
        byte[] color = new byte[1];
        System.Runtime.InteropServices.Marshal.Copy(pFirstPixel, color, 0, 1);
        BitArray bits = new BitArray(color);
        return bits.Get(bitIndex) ? Color.Black : Color.White;
    }

首先,如果您需要在一次操作中读取单个像素,那么
GetPixel
在性能上是等效的。昂贵的操作是锁定位,也就是说,您应该保留
BitmapData
,以便执行所有需要的读取操作,并且只在最后关闭它,但请记住关闭它


像素格式似乎有些混乱,但我们假设它是正确的1bpp。然后每个像素将占用一位,一个字节中将有8个像素的数据。因此,您的索引计算是不正确的。字节的位置将位于
x/8
,然后您需要获取位
x%8

好的,明白了!您需要从BitmapData读取位,并对要提取颜色的位应用掩码:

var bm = new Bitmap...

//lock all image bits
var bitmapData = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed);

// this  will return the pixel index in the color pallete
// since is 1bpp it will return 0 or 1
int pixelColorIndex = GetIndexedPixel(50, 30, bitmapData);

// read the color from pallete
Color pixelColor = bm.Pallete.Entries[pixelColorIndex];
方法如下:

// x, y relative to the locked area
private int GetIndexedPixel(int x, int y, BitmapData bitmapData)
{
    var index = y * bitmapData.Stride + (x >> 3);
    var chunk = Marshal.ReadByte(bitmapData.Scan0, index);

    var mask = (byte)(0x80 >> (x & 0x7));
    return (chunk & mask) == mask ? 1 : 0;
}
像素位置分两轮计算:

1) 查找“x”中像素所在的字节(x/8):每个字节包含8个像素,要查找字节除以x/8取整:58>>3=7,像素位于当前行(跨距)的字节7上

2) 查找当前字节上的位(x%8):执行
x&0x7
仅获取最左边的3位(x%8)

例如:

x = 58 
// x / 8 - the pixel is on byte 7
byte = 58 >> 3 = 58 / 8 = 7 

// x % 8 - byte 7, bit 2
bitPosition = 58 & 0x7 = 2 

// the pixels are read from left to right, so we start with 0x80 and then shift right. 
mask = 0x80 >> bitPosition = 1000 0000b >> 2 =  0010 0000b 

即使像素为黑色,值是否为255?当您只需要一个像素操作时,锁定位没有意义。您只需使用bmp的GetPixel方法,而不锁定任何位或任何内容。如果您实际需要多个像素,则应锁定包含所有所需像素的整个区域,并使用Scan0的索引逻辑访问这些像素。但是,对于单个像素的get/set,您应该,使用GetPixel/SetPixel,因为单次使用速度更快。顺便说一下,锁定1x1矩形可能会有问题,因此您可以尝试锁定2x2,即使您只使用该矩形的第一个像素(如果这样做,请记住处理bmp的右下边缘)。您的图像是每像素1比特还是每像素1字节?因为你说的是24bpp,然后是1bpp,但似乎1bpp实际上意味着8bpp,或者不是?谢谢你的回答!我已经提到,图像是1bpp索引的。这有关系吗?我只是被这个事实弄糊涂了,因为如果所有的位都表示像素的颜色,那么索引存储在哪里?或者我理解错了什么?索引只是意味着颜色值是颜色表的索引。但是由于1位只剩下2种可能,所以可以安全地假设这两种颜色是黑色和白色。实际上,托盘上可以有任意两种颜色,不一定是黑色/白色。它可以是蓝色/红色、绿色/黄色等。。。Bitmap.Pallete.Entries保存位图的Pallete颜色。工作正常!谢谢。让我问你,你是如何找到计算面具的方法的?