BitBlt рисование растрового изображения вверх ногами - PullRequest
3 голосов
/ 26 января 2012

У меня есть элемент управления MFC, которому я передаю дескриптор растрового изображения (HBITMAP).В элементе управления OnPaint я использую BitBlt для рендеринга растрового изображения.Но растровое изображение отображается вверх ногами.

В качестве теста я создал объект CBitmap из этого дескриптора и записал его в файл, и он создал растровое изображение, которое было справа вверх.Так что я делаю что-то не так с моим звонком в BitBlt?

Я разместил свой код на OnPaint ниже.Я попытался изменить режим отображения контекста моего устройства на MM_LOENGLISH и смог получить растровое изображение для рендеринга правой стороной вверх, но оно было очень зернистым.Когда я покидаю режим отображения в MM_TEXT, качество изображения идеальное, но, как я уже сказал, оно перевернуто.Я мало работал с растровыми изображениями, блиттингом и т. Д., Поэтому я мог упустить что-то простое.Любые другие предложения будут оценены.Для некоторого фона я беру BYTE * из драйвера видеокамеры и создаю HBITMAP для рендеринга видео.Как я могу заставить это сделать правильно?Большое спасибо

void BitmapControl::OnPaint()
{
EnterCriticalSection (&CriticalSection);

if (_handleBMP)
{

    CPaintDC dc(this);
    //dc.SetMapMode(MM_LOENGLISH);
    CDC dcMem;
    dcMem.CreateCompatibleDC(&dc);

    CRect rect;
    GetClientRect(&rect);
    dc.DPtoLP(&rect);


    CBitmap* pBmpOld = dcMem.SelectObject(CBitmap::FromHandle(_handleBMP));
    BitBlt(dc,rect.left,rect.top,rect.Width(),rect.Height(),dcMem,rect.left,rect.top,SRCCOPY); //works with MM_TEXT but upsidedown
    //BitBlt(dc,0,rect.bottom,rect.Width(),-rect.Height(),dcMem,0,0,SRCCOPY); //works with MM_LOENGLISH
    dcMem.SelectObject(pBmpOld);
    DeleteDC(dc);
    DeleteDC(dcMem);
    DeleteObject(_handleBMP);
    DeleteObject(pBmpOld);
    _handleBMP = NULL;

}
LeaveCriticalSection (&CriticalSection);
}

edit * Я предполагал, потому что я мог сохранить растровое изображение на диск в правильной ориентации, что проблема была с bitblt.Вот код, который я использую для генерации HBITMAP.

 HBITMAP BitmapWriter::CreateBitmapFromFrame(BYTE* frame)
{
BITMAPFILEHEADER* bmfh;
bmfh = (BITMAPFILEHEADER*)frame;

BITMAPINFOHEADER* bmih = &_bmi;

BITMAPINFO* bmpInfo = (BITMAPINFO*)bmih;

HBITMAP hbmp = CreateDIBSection(_hdc,bmpInfo,DIB_RGB_COLORS,NULL,NULL,0);
SetBitmapBits(hbmp,_bmi.biSizeImage,frame);


return hbmp;
}

О, и я использовал критическую секцию, потому что я передаю hbitmap элементу управления в свойстве, а затем обращаюсь к нему в OnPaint.Если это потенциальная проблема, мне придется переосмыслить это.Спасибо

Ответы [ 4 ]

5 голосов
/ 26 января 2012

Растровые изображения Windows сохраняются с нижней строки в первую очередь. Большая часть остального мира работает в первую очередь, поэтому я предполагаю, что именно это вы получаете от своей камеры.

Вы можете использовать отрицательную высоту в структуре BITMAPINFOHEADER, чтобы изменить нормальный порядок.

3 голосов
/ 04 января 2013

Просто используйте отрицательное значение в поле biHeight структуры BITMAPINFOHEADER.

bi.biHeight = -height;  //this is the line that makes it draw upside down or not
1 голос
/ 27 января 2012

Хорошо, похоже, это работает. В итоге я изменил режим отображения на MM_LOENGLISH. Как я уже говорил, это дало мне зернистое изображение, но это было исправлено добавлением следующего

dc.SetStretchBltMode (COLORONCOLOR);

Мне нужно немного почитать, чтобы понять, почему ... но вот мой код рендеринга.

void BitmapControl::OnPaint()
{
EnterCriticalSection (&CriticalSection);

if (_handleBMP)
{

    CPaintDC dc(this);
    //dc.SetMapMode(MM_ISOTROPIC);
    dc.SetMapMode(MM_LOENGLISH);
    CDC dcMem;
    dcMem.CreateCompatibleDC(&dc);

    CRect rect;
    GetClientRect(&rect);
    dc.DPtoLP(&rect);

    CBitmap* pBmpOld = dcMem.SelectObject(CBitmap::FromHandle(_handleBMP));

    //tst
    dc.SetStretchBltMode(COLORONCOLOR);

    //BitBlt(dc,rect.left,-0,rect.Width(),rect.Height(),dcMem,rect.left,rect.top,SRCCOPY); //works with MM_TEXT but upsidedown
    BitBlt(dc,0,rect.bottom,rect.Width(),-rect.Height(),dcMem,0,0,SRCCOPY); //works with MM_LOENGLISH
    dcMem.SelectObject(pBmpOld);
    DeleteDC(dc);
    DeleteDC(dcMem);
    DeleteObject(_handleBMP);
    DeleteObject(pBmpOld);
    _handleBMP = NULL;

}
LeaveCriticalSection (&CriticalSection);
}
1 голос
/ 26 января 2012

В MM_TEXT ось Y направлена ​​вниз, а в других режимах отображения - вверх. Попробуйте MM_ISOTROPIC режим отображения. Для более точного управления вам может понадобиться установить смещение окна просмотра и окна и экстенты на CDC .

Растровые изображения можно хранить в перевернутом виде, о чем свидетельствует отрицательная высота в структуре BITMAPINFOHEADER , но это не должно быть проблемой.

...