GetDIBits и цикл через пиксели с помощью X, Y

Я хватаю часть экрана и просматриваю пиксели для определенного цветового диапазона.

Я посмотрел на MSDN захватывает изображение пример и знать, как использовать функции.

Я могу получить биты в массив, но я не уверен, как это сделать таким образом, чтобы я мог пройти через него, как я бы изображение. Псевдо-пример (который, я уверен, далеко):

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 ответов


помимо хороших ответов, уже данных, вот пример как чтобы получить простую структуру массива ходить. (Вы можете использовать, например,ГОЗ' код для итерации.)

GetDIBits ссылка @ MSDN

выберите пункт DIB_RGB_COLORS как флаг для uUsage и создал BITMAPINFO структура и BITMAPINFOHEADER структура в нем содержится. Когда вы установите biClrUsed и biClrImportant к нулю, есть таблица цветов "нет", поэтому вы можете прочитать пиксели растрового изображения, которое вы получаете от GetDIBits как последовательность значений RGB. Используя 32 как разрядность (biBitCount) устанавливает структуру данных в соответствии с MSDN:

растровое изображение имеет максимум 2^32 цветов. Если biCompression член BITMAPINFOHEADER is BI_RGB, the bmiColors член BITMAPINFO is NULL. Каждый DWORD в массиве растровых изображений представлены относительные интенсивности синего, зеленого и красного соответственно для пикселя. Этот высокий байт в каждом DWORD не используется.

С MS LONG ровно 32 бит (размер DWORD), вам не нужно обращать внимание на заполнение (как описано в Примечания).

код:

HDC hdcSource = NULL; // the source device context
HBITMAP hSource = NULL; // the bitmap selected into the device context

BITMAPINFO MyBMInfo = {0};
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);

// Get the BITMAPINFO structure from the bitmap
if(0 == GetDIBits(hdcSource, hSource, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS))
{
    // error handling
}

// create the pixel buffer
BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];

// We'll change the received BITMAPINFOHEADER to request the data in a
// 32 bit RGB format (and not upside-down) so that we can iterate over
// the pixels easily. 

// requesting a 32 bit image means that no stride/padding will be necessary,
// although it always contains an (possibly unused) alpha channel
MyBMInfo.bmiHeader.biBitCount = 32;
MyBMInfo.bmiHeader.biCompression = BI_RGB;  // no compression -> easier to use
// correct the bottom-up ordering of lines (abs is in cstdblib and stdlib.h)
MyBMInfo.bmiHeader.biHeight = abs(MyBMInfo.bmiHeader.biHeight);

// Call GetDIBits a second time, this time to (format and) store the actual
// bitmap data (the "pixels") in the buffer lpPixels
if(0 == GetDIBits(hdcSource, hSource, 0, MyBMInfo.bmiHeader.biHeight,
                  lpPixels, &MyBMInfo, DIB_RGB_COLORS))
{
    // error handling
}
// clean up: deselect bitmap from device context, close handles, delete buffer

GetDIBits возвращает одномерный массив значений. Для растрового изображения шириной M пикселей и высотой N пикселей, использующего 24-битный цвет, первый (M*3) байт будет первой строкой пикселей. Это может сопровождаться некоторыми байтами заполнения. Это зависит от BITMAPINFOHEADER. Обычно обивка, чтобы ширина кратна 4 байтам. Поэтому, если ваше растровое изображение имеет ширину 33 пикселя, на каждой строке будет (36*3) байта.

этот "пиксели" плюс "прокладка" называется "Шаг". Для Растровые изображения RGB, вы можете рассчитать шаг с:stride = (biWidth * (biBitCount / 8) + 3) & ~3, где biWidth и biBitCount взяты из BITMAPINFOHEADER.

Я не уверен, как вы хотите траверс массива. Если вы хотите перейти пиксель за пикселем сверху слева направо (предполагая, что это растровое изображение сверху вниз):

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

Это не так просто. Ваш алгоритм будет зависеть от глубины цвета изображения. Если это 256 или меньше, у вас не будет цветов пикселей, но они будут в палитре цветов. 16-битные пиксели могут быть RGB555 или RGB565, 24-битные изображения будут RGB888, а 32-битные изображения будут RGBA или ARGB. Вам понадобится BITMAPINFOHEADER, чтобы узнать.

Как только вы узнаете, пиксельные данные будут просто массивом ширины размера * высота * (BitsPerPixel / 8)


в ссылке, которую вы публикуете, вы создаете 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.Массивы 0 основаны на C/C++
2. Вы шагали 3 пикселя по горизонтали и вертикали каждый раз. Что означало, что вы посещаете не каждый пиксель.
3. Растровое изображение-это, как правило, организованы таким образом, что есть" высота "пядей" ширина " пикселей. Поэтому вы должны пройти через каждый пиксель в промежутке, а затем перейти к следующему промежутку.
4. Как уже отмечалось, убедитесь,что вы правильно читаете пиксели. в 16-битном режиме его сложнее


некоторый сюрприз от MSDN:

таблица состоит из массива структур данных RGBQUAD. (Таблица для формата BITMAPCOREINFO строится с данными RGBTRIPLE структура.) Красный, зеленый и синий байты в обратном порядке (красный меняет позицию на синюю) из соглашения Windows.

Итак, цвета находятся в порядке BGR в памяти после GetDIBits ()