GetDIBits并使用X,Y循环遍历像素

时间:2010-09-10 21:17:21

标签: c++ loops pixels getdibits

我抓住屏幕的一部分并扫描像素以获得特定的颜色范围。

我查看了MSDN's Capturing an Image示例并知道如何使用这些函数。

我可以把这些位放到一个数组中,但是我不知道如何以这样的方式进行操作,我可以像处理图像一样遍历它。一个伪示例(我肯定是这样的):

for ( x = 1; x <= Image.Width; x += 3 )
{
    for ( y = 1; y <= Image.Height; y += 3 )
    {
        red = lpPixels[x];
        green = lpPixels[x + 1];
        blue = lpPixels[x + 2];
    }
}

这基本上就是我想做的事情,所以如果红色,蓝色和绿色是某种颜色,我会知道它在图像中的(x,y)坐标是什么。

我只是不知道如何以这种方式使用GetDIBits,以及如何正确设置数组以实现此目的。

5 个答案:

答案 0 :(得分:12)

除了已经给出的好答案之外,这里有一个如何的例子来获得一个简单的数组结构。 (您可以使用例如Goz' code进行迭代。)

GetDIBits reference @ MSDN

您必须选择DIB_RGB_COLORS作为uUsage的标记,然后设置BITMAPINFO structure及其中包含的BITMAPINFOHEADER structure。当您将biClrUsedbiClrImportant设置为零时,会出现“无”颜色表,因此您可以读取从GetDIBits获得的位图像素作为RGB值序列。使用32作为位数(biBitCount)根据MSDN设置数据结构:

  

位图最多有2 ^ 32种颜色。如果biCompression的{​​{1}}成员为BITMAPINFOHEADER,则BI_RGB的{​​{1}}成员为bmiColors。位图数组中的每个BITMAPINFO分别表示像素的蓝色,绿色和红色的相对强度。不使用每个NULL中的高字节。

由于MS DWORD正好是32位长(DWORD的大小),因此您不必注意填充(如Remarks section中所述)。< / p>

代码:

LONG

答案 1 :(得分:9)

GetDIBits返回一维值数组。对于M像素宽,N像素高且使用24位颜色的位图,第一(M * 3)字节将是第一行像素。接下来可以是一些填充字节。这取决于BITMAPINFOHEADER。通常使用填充来使宽度为4个字节的倍数。因此,如果您的位图宽度为33像素,则每行实际上会有(36 * 3)个字节。

这个“像素加填充”被称为“步幅”。对于RGB位图,您可以使用stride = (biWidth * (biBitCount / 8) + 3) & ~3计算步幅,其中biWidthbiBitCount取自BITMAPINFOHEADER。

我不确定你想要如何遍历数组。如果你想从左上角到右下角逐像素(假设这是一个自上而下的位图):

for (row = 0; row < Image.Height; ++row)
{
    int rowBase = row*stride;
    for (col = 0; col < Image.Width; ++col)
    {
        red = lpPixels[rowBase + col];
        // etc.
    }
}

答案 2 :(得分:2)

这并不容易。您的算法将取决于图像的颜色深度。如果它是256或更小,你将没有像素颜色,但是在颜色调色板中有颜色。 16位像素可以是RGB555或RGB565,24位图像是RGB888,32位图像是RGBA或ARGB。你需要BITMAPINFOHEADER才能找到答案。

一旦你发现,像素数据将只是一个大小宽度*高度*(BitsPerPixel / 8)的数组

答案 3 :(得分:2)

在您发布的链接中,您创建了一个32位位图,因此我假设您正在读取32位位图(此假设可能不正确)。

因此,将循环更改为以下内容应该有效:

char* pCurrPixel = (char*)lpPixels;
for ( y = 0; y < Image.Height; y++ )
{
    for ( x = 0; x < Image.Width; x++ )
    {
        red = pCurrPixel[0];
        green = pCurrPixel[1];
        blue = pCurrPixel[2];

        pCurrPixel += 4;
    }
}

要记住的事情:

1.Arrays为0,基于C / C ++
 你每次水平和垂直踩3个像素。这意味着你不会访问每个像素  通常组织位图使得存在“宽度”像素的“高度”跨度。因此,您应该逐步浏览范围中的每个像素,然后移动到下一个范围  4.正如已经指出的那样,确保你正确地读取像素。在16位模式下,它更复杂

答案 4 :(得分:0)

MSDN的一些惊喜:

  

该表由一组RGBQUAD数据结构组成。 (桌子   对于BITMAPCOREINFO格式,使用RGBTRIPLE数据构建   结构。)红色,绿色和蓝色字节的顺序相反(红色   从Windows约定中用蓝色交换位置。

因此,在GetDIBits()

之后,颜色在内存中以BGR顺序排列