GetDIBits
От: Antony Россия  
Дата: 09.02.02 16:31
Оценка:
У меня есть DIB в памяти (я его получаю извлекая кадр из входящего видеопотока, используя функции видеозахвата). Причём я его сжимаю по выбору одним из кодеков установленных в системе.
Мне нужно делать одно из нижеперечисленного:
1) Вырезать из неё некторый квадрат изображения меньший теукщего. ИЛИ
2) Масштабировать. ИЛИ
3) Или сделав первое или второе сделать её GRAYSCALE.


Я попытался сделать так, как описано ниже но не получилось:


HDC MainDC = GetDC(AfxGetApp()->m_pMainWnd->m_hWnd);
HDC FirstDC = CreateCompatibleDC(MainDC);



// LPBYTE pData; - указывает на начало в памяти DIB'а с BITMAPINFO и массивом данных
// LPBITMAPINFOHEADER pTBIH = (LPBITMAPINFOHEADER)pData;
// Data.X1,Data.X2,Data.Y1,Data.Y2 - желаемый квадрат из DIB


StretchDIBits(FirstDC, 0, 0, Data.X2 - Data.X1, Data.Y2 - Data.Y1, 
        0, 0, Data.X2 - Data.X1, Data.Y2 - Data.Y1, 
        pData + pTBIH->biSize + pTBIH->biClrUsed * sizeof(RGBQUAD),
        (LPBITMAPINFO)pData, DIB_RGB_COLORS, SRCCOPY);

Я так понимаю эта функция копирует квадрат из памяти в FirstDC

Затем пытаюсь извлечь получившуюся картинку:

pTBIH->biWidth = Data.X2 - Data.X1;
pTBIH->biHeight    = Data.Y2 - Data.Y1;
HBITMAP    hBitmap = CreateCompatibleBitmap(MainDC, pTBIH->biWidth, pTBIH->biHeight);
GetDIBits(    FirstDC, hBitmap, 0, (DWORD)pTBIH->biHeight, 
        pData + pTBIH->biSize + pTBIH->biClrUsed * sizeof(RGBQUAD),
        (LPBITMAPINFO)pData, DIB_RGB_COLORS);

Возвращает код ошибки: Параметр задан неверно. (87)
Скорее всего из-за второй переменной.

Но я пробовал и по-другому.
Создал HBITMAP как возврат CreateBitmap;
Выбрал его SelectObject в первый контекст.
StretchBlt во второй.
И оттуда GetDIBits уже от законной HBITMAP, но опять таже ошибка.
Nihil humany a me alienum puto!
Re: GetDIBits
От: Alex Fedotov США  
Дата: 09.02.02 19:48
Оценка:
Здравствуйте Antony, Вы писали:

A>У меня есть DIB в памяти (я его получаю извлекая кадр из входящего видеопотока, используя функции видеозахвата). Причём я его сжимаю по выбору одним из кодеков установленных в системе.

A>Мне нужно делать одно из нижеперечисленного:
A> 1) Вырезать из неё некторый квадрат изображения меньший теукщего. ИЛИ
A> 2) Масштабировать. ИЛИ
A> 3) Или сделав первое или второе сделать её GRAYSCALE.


A>Я попытался сделать так, как описано ниже но не получилось:


A>HDC MainDC = GetDC(AfxGetApp()->m_pMainWnd->m_hWnd);
A>HDC FirstDC = CreateCompatibleDC(MainDC);


A>// LPBYTE pData; - указывает на начало в памяти DIB'а с BITMAPINFO и массивом данных
A>// LPBITMAPINFOHEADER pTBIH = (LPBITMAPINFOHEADER)pData;
A>// Data.X1,Data.X2,Data.Y1,Data.Y2 - желаемый квадрат из DIB


Вот здесь, прежде чем что-то рисовать в FirstDC, нужно выбрать в него какую-нибудь bitmap. В твоем случае имеет смысл выбрать DIB section, чтобы автоматически получить доступ к битам картинки.

// заполняем BITMAPINFO на основе оригинальной картинки; изменяются только
// размеры, все остальные атрибуты, включая таблицу цветов, копируются без
// изменений

DWORD cbInfo = pTBIH->biSize + pTBIH->biClrUsed * sizeof(RGBQUAD);

BITMAPINFO * pbmi = (BITMAPINFO *)malloc(cbInfo);
if (pbmi == NULL)
    ...;

memcpy(pbmi, pTBIH, cbInfo);
pbmi->bmiHeader.biWidth  = Data.X2 - Data.X1;
pbmi->bmiHeader.biHeight = Data.Y2 - Data.Y1;
pbmi->bmiHeader.biSizeImage = 0;

PVOID pBits;
HBITMAP hBitmap = CreateDIBSection(MainDC, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0);
if (hBitmap == NULL)
    ...;

HGDIOBJ hOldBitmap = SelectObejct(FirstDC, hBitmap);

A>StretchDIBits(FirstDC, 0, 0, Data.X2 - Data.X1, Data.Y2 - Data.Y1, 
A>        0, 0, Data.X2 - Data.X1, Data.Y2 - Data.Y1, 
A>        pData + pTBIH->biSize + pTBIH->biClrUsed * sizeof(RGBQUAD),
A>        (LPBITMAPINFO)pData, DIB_RGB_COLORS, SRCCOPY);

SelectObject(FirstDC, hOldBitmap);

// теперь можно анализировать вырезанный кусок через указатель pBits
-- Alex Fedotov
Re[2]: GetDIBits
От: Аноним  
Дата: 10.02.02 12:58
Оценка:
Ага, идея понятна, но тут возникла проблема с нижеприведённой функцией:


AF>PVOID pBits;
AF>HBITMAP hBitmap = CreateDIBSection(MainDC, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0);
AF>if (hBitmap == NULL)
AF>    ...;



Как раз дело в том, что она возвращает NULL.
С ошибкой: Неправильно задан параметр.
Возможно нельзя эту функцию использовать для сжатой BMP.
Re[3]: GetDIBits
От: Alex Fedotov США  
Дата: 10.02.02 20:02
Оценка:
Здравствуйте Аноним, Вы писали:

А>Ага, идея понятна, но тут возникла проблема с нижеприведённой функцией:


AF>>PVOID pBits;
AF>>HBITMAP hBitmap = CreateDIBSection(MainDC, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0);
AF>>if (hBitmap == NULL)
AF>>    ...;


А>Как раз дело в том, что она возвращает NULL.

А>С ошибкой: Неправильно задан параметр.

А>Возможно нельзя эту функцию использовать для сжатой BMP.


Нельзя. Тогда надо переопределить параметр сжатия в структуре BITMAPINFO, передаваемой на вход этой функции:

pbmi->bmiHeader.biWidth  = Data.X2 - Data.X1;
pbmi->bmiHeader.biHeight = Data.Y2 - Data.Y1;
pbmi->bmiCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = 0;


Если в итоге надо получить опять же сжатое изображение, то нужно будет вызвать GetDIBits, она умеет генерировать RLE.
-- Alex Fedotov
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.