from: http://peng-jun.blog.163.com/blog/static/215628142009325104710656/
下载示例程序地址:http://download.csdn.net/source/1247134
以前就想过如何让OpenCV的图片不是显示在一个由cvNamedWindow生成的窗体,而是显示在MFC的窗体上。可是,没有在OpenCV的函数库中找到相应的函数,也就没有在往下多想。今天,又有一个同学问起来这件事,于是想到了不如自己写一个函数来实现这样的功能不就OK了。结果,就出现了下面的函数:
void ShowMFC(IplImage *img, CDC *pDC)
{
DWORD height=img->height;
DWORD width=img->width;
DWORD lineBytes=(width*8+31)/32*4;
DWORD lineBytes24=(width*24+31)/32*4;
BYTE *temp=new BYTE[img->height*lineBytes24];
if(!temp) return;
memset(temp,0,height*lineBytes24);
WORD bitCount;
if(img->nChannels==1)
{
bitCount=8;
}
else if(img->nChannels==3)
{
bitCount=24;
}
else
{
delete[] temp;
temp=NULL;
return;
}
if(bitCount==8)
{
for(int i=0;i
{
for(int j=0,n=0;j
{
*(temp+lineBytes24*(height-1-i)+j)=(BYTE)((uchar*)(img->imageData+img->widthStep*i))[n];
j++;
*(temp+lineBytes24*(height-1-i)+j)=(BYTE)((uchar*)(img->imageData+img->widthStep*i))[n];
j++;
*(temp+lineBytes24*(height-1-i)+j)=(BYTE)((uchar*)(img->imageData+img->widthStep*i))[n];
}
}
}
else
{
for(int i=0;i
{
for(int j=0,n=0;j
{
*(temp+lineBytes24*(height-1-i)+j)=(BYTE)((uchar*)(img->imageData+img->widthStep*i))[3*n];
j++;
*(temp+lineBytes24*(height-1-i)+j)=(BYTE)((uchar*)(img->imageData+img->widthStep*i))[3*n+1];
j++;
*(temp+lineBytes24*(height-1-i)+j)=(BYTE)((uchar*)(img->imageData+img->widthStep*i))[3*n+2];
}
}
}
BITMAPINFO bi;
// for(int n=0;n<256;n++)
// {
// bi.bmiColors[n].rgbBlue=(BYTE)n;
// bi.bmiColors[n].rgbGreen=(BYTE)n;
// bi.bmiColors[n].rgbRed=(BYTE)n;
// bi.bmiColors[n].rgbReserved=(BYTE)0;
// }
bi.bmiHeader.biBitCount=24;
bi.bmiHeader.biClrImportant=0;
bi.bmiHeader.biClrUsed=0;
bi.bmiHeader.biCompression=0L;
bi.bmiHeader.biHeight=height;
bi.bmiHeader.biPlanes=1;
bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biSizeImage=height*lineBytes;
bi.bmiHeader.biWidth=width;
bi.bmiHeader.biXPelsPerMeter=0;
bi.bmiHeader.biYPelsPerMeter=0;
StretchDIBits(pDC->m_hDC,0,0,width,height,0,0,width,height,temp,(BITMAPINFO*)&bi,DIB_RGB_COLORS,SRCCOPY);
delete[] temp;
temp=NULL;
}
值得注意的是,上面注释的代码部分不知道为什么一旦运行就会改变IplImage结构体的值,所以只能不运行那段程序。也就是要把OpenCV读入的图片全部的转换为24位位图的格式,这样就不需要去改变BITMAPINFO结构体中bmiColors的内容。这点从程序中也能看出来。
可以把上面的函数作为一个全局函数,然后,下面是调用上面函数的程序:
void CTestShowInMFCWindowDlg::OnBtnOpen()
{
// TODO: Add your control notification handler code here
char szFilter[]="BMP files(*.bmp)|*.bmp|JPG files(*.jpg)|*.jpg|All files(*.*)|*.*||";
CFileDialog ofd(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter);
if(ofd.DoModal()!=IDOK) return;
IplImage *src=cvLoadImage(ofd.GetPathName(),CV_LOAD_IMAGE_ANYCOLOR);
if(!src) return;
RedrawWindow();
ShowMFC(src,GetDC());
}
因为ShowMFC函数只要传入要显示的OpenCV的结构体IplImage*和一个要显示的CDC指针就可以了。