作者:海水和火焰
转自:
http://lh2078.blog.163.com/blog/static/5681137220131311492631/
在OpenCV1.1版本之前,包含了一个CvvImage类可以用于将IplImage显示在MFC界面上,但是在OpenCV2.0后,这个类没有了。所以有很多朋友问及如何在MFC界面上显示Mat,如果简单的使用
StretchDibBit的方法,会出现图像显示错行。这是由于Mat中的数据和传统的IplImage数据数据对齐方式不同。下面
给出解决方法:
void ShowImg(CDC *pDC, Mat &img, RECT* pRect)
{
if( pDC && pRect && !img.empty() )
{
uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];
BITMAPINFO* bmi = (BITMAPINFO*)buffer;
int bmp_w = img.cols, bmp_h = img.rows;
BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
memset( bmih, 0, sizeof(*bmih));
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biWidth = bmp_w;
bmih->biHeight = -bmp_h;// : -abs(height);
bmih->biPlanes = 1;
bmih->biBitCount = IPL_DEPTH_8U*img.channels();
bmih->biCompression = BI_RGB;
if( IPL_DEPTH_8U*img.channels() == 8 )
{
RGBQUAD* palette = bmi->bmiColors;
int i;
for( i = 0; i < 256; i++ )
{
palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
palette[i].rgbReserved = 0;
}
}
if(pRect->right – pRect->left +1 < bmp_w )
{
SetStretchBltMode(
pDC->m_hDC, // handle to device context
HALFTONE );
}
else
{
SetStretchBltMode(
pDC->m_hDC, // handle to device context
COLORONCOLOR );
}
if(img.cols % 4 != 0 && img.isContinuous())
{
IplImage *tempimg = cvCreateImage(img.size(), 8, img.channels());
img.copyTo(Mat(tempimg));
::StretchDIBits(
pDC->m_hDC,
pRect->left, pRect->top, pRect->right – pRect->left+1, pRect->bottom – pRect->top+1,
0, 0, bmp_w, bmp_h,
tempimg->imageData, bmi, DIB_RGB_COLORS, SRCCOPY );
cvReleaseImage(&tempimg);
}
else
{
::StretchDIBits(
pDC->m_hDC,
pRect->left, pRect->top, pRect->right – pRect->left+1, pRect->bottom – pRect->top+1,
0, 0, bmp_w, bmp_h,
img.data, bmi, DIB_RGB_COLORS, SRCCOPY );
}
}
return;
}
其中,CDC *pDC不用说了,熟悉MFC的码农都知道, Mat &img即OpenCV2.0后的图像了,如果仍然采用IplImage可以强制转换为Mat类型, RECT* pRect是在窗口中显示的位置。