简体   繁体   中英

MFC - How to draw a color bitmap to the dialog DC

I've got this snippet of code in a camera acquisition loop:

CBitmap* bmp = new CBitmap();
CDC* pDC;
CBitmap* old;
CDC*  memDC = new CDC();

pDC = pLiveImageDlg->GetDC();

bmp->CreateCompatibleBitmap(pDC, 640, 480);

memDC->CreateCompatibleDC(pDC);
old = memDC->SelectObject(bmp);

bmp->SetBitmapBits(640 * 480 * 3, frame.data);

pDC->BitBlt(0, 0, 640, 480, memDC, 0, 0, SRCCOPY);

memDC->SelectObject(old);

My issue is, when viewing the bitmap that gets drawn onto the dialog, it looks completely distorted and monochrome. Normally, an image being distorted means the pixel indexing is off (wrong color format, etc). The "frame" variable is an OpenCV Mat object, which is grabbing the image as a 24-bit RGB format (displays perfectly fine in color using imshow() ). I have the feeling that the monochrome issue is related to the CreateCompatibleDC function call since by default it creates a 1x1 monochrome pixel, according to the MSDN docs ... and this monochrome issue might be causing the "pixel byte array offset" issue.

What's the right way to go about getting a bitmap blitted to the screen as a 24-bit RGB bitmap?

Yes, you are correct - default is monochrome. I think the easiest (and fastest for GDI) would be just to render the 24-bitmap directly:

BITMAPINFO bmi = { 0 };
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = 640;
bmi.bmiHeader.biHeight = -480;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;

CClientDC dc(pLiveImageDlg);
SetDIBitsToDevice(dc, 0, 0, 640, 480, 0, 0, 0, 480, data, frame.data, 0);

Two things to mention here, there should be correct sequence of RGB (ie RGB/BGR) and correct sequence of vertical lines (ie up->down vs down->up), you may adjust this using setting biHeight to positive/negative value.

If you want to display a grayscale bitmap you have to prepare a palette into BITMAPINFO

int bpp = 8 * img.elemSize();
uchar buffer[sizeof(BITMAPINFO) + 256*4];
BITMAPINFO* bmi = (BITMAPINFO*)buffer;
BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);

//Sets the palette only if image is grey scale
if (bpp == 8)
{
    RGBQUAD* palette = bmi->bmiColors;
    for (int i = 0; i < 256; i++)
    {
      palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
      palette[i].rgbReserved = 0;
    }
}

See here for more details: How to display an OpenCV image or video in your own MFC interface

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM