I am using following routines to display OpenCV Mat on MFC View. And it’s working well for uncropped images. But for pre-cropped images, it shows blank or weird images like the ones below:
First one is displayed on usual image software such as MS Paint and the second is on my MFC view. Difficult is that uncropped image files are displaying just fine. I am not sure this is fault of SetDIBitsToDevice or OpenCV. But clearly SetDIBitsToDevice loses constant number of bytes in each row. Anybody has any idea to fix this problem?

cv::Mat m_cvImage;
static int Bpp(cv::Mat img) { return 8 * img.channels(); }
void COpenCVTestView::OnDraw(CDC* pDC)
{
COpenCVTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
if(pDoc->m_cvImage.empty()) return;
// TODO: add draw code for native data here
int height=pDoc->m_cvImage.rows;
int width=pDoc->m_cvImage.cols;
uchar buffer[sizeof( BITMAPINFOHEADER ) + 1024];
BITMAPINFO* bmi = (BITMAPINFO* )buffer;
FillBitmapInfo(bmi,width,height,Bpp(pDoc->m_cvImage),0);
SetDIBitsToDevice(pDC->GetSafeHdc(), 0, 0, width,
height, 0, 0, 0, height, pDoc->m_cvImage.data, bmi,
DIB_RGB_COLORS);
}
void COpenCVTestView::FillBitmapInfo(BITMAPINFO* bmi, int width, int height, int bpp, int origin)
{
assert(bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));
BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
memset(bmih, 0, sizeof(*bmih));
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biWidth = width;
bmih->biHeight = origin ? abs(height) : -abs(height);
bmih->biPlanes = 1;
bmih->biBitCount = (unsigned short)bpp;
bmih->biCompression = BI_RGB;
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;
}
}
}
As Roel says, the bitmap data needs to be DWORD aligned. This is an incomplete description of the problem however; each row of the data needs to start on a DWORD boundary. Typically you insert 0 to 3 bytes of padding at the end of each row to ensure this.
If it is inconvenient or impossible to pad the rows, simply make sure the width of the image is evenly divisible by 4.