您的位置:首页 > 运维架构

OpenCV2.2版本以上显示图片到MFC 的picture control中

2017-02-28 10:37 791 查看
OpenCV 2.2 以及后面的版本取消掉了 CvvImage.h 和CvvImage.cpp 两个文件,直接导致无法调用里面的显示函数来将图片显示到 MFC 的 Picture Control 控件中。为此,网上很多人表示只要将这两个文件人为的添加到自己的工程里面就解决问题了,网上有这两个文件的源代码,但是这麻烦不说,还会导致一些奇奇怪怪的报错,自己在尝试的过程中遇到了很多问题,所以在了解了一些GDI绘图之后结合网上的代码写了如下的函数,只需调用就可以将OpenCV的图片显示在picture control中了,初步测试效率跟原来两个文件差不多,如果有大神请帮我继续完善这份代码!

本人使用的OpenCV版本为OpenCV2.4.9,在VS2012中配置好之后,在文件头部添加如下一行代码:

#define  WIDTHBYTES(bits) (((bits)+31)/32*4) ; //用于使图像宽度所占字节数为4byte的倍数

首先在对话框类中声明函数:void ShowImage( IplImage * img, unsigned int ID) ,其中参数一为OpenCV的图像数据结构类,参数二为picture control的ID

定义该函数如下:

void CImageRetrievalSystemDlg::ShowImage(IplImage * img, unsigned int ID)   //ImageRetrievalSystemDlg 为对话框类名

{

BYTE *g_pBits;

        HDC g_hMemDC;

        HBITMAP g_hBmp, g_hOldBmp;

        CDC *pDC;

        CStatic *pic;

        int width, height;

        CRect rect;

        pDC = GetDlgItem(ID)->GetDC();

        pic = (CStatic*)GetDlgItem(ID);

        pic->GetClientRect(&rect);

        width = rect.Width();

        height = rect.Height();

        g_hMemDC = ::CreateCompatibleDC(pDC->m_hDC);//创建兼容DC

        BYTE bmibuf[sizeof(BITMAPINFO)+256 * sizeof(RGBQUAD)];

        memset(bmibuf, 0, sizeof(bmibuf));

        BITMAPINFO *pbmi = (BITMAPINFO*)bmibuf;

        pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

        pbmi->bmiHeader.biWidth = img->width;

        pbmi->bmiHeader.biHeight = img->height;

        pbmi->bmiHeader.biPlanes = 1;

        pbmi->bmiHeader.biBitCount = 24;

        pbmi->bmiHeader.biCompression = BI_RGB;

        g_hBmp = ::CreateDIBSection(g_hMemDC, pbmi, DIB_RGB_COLORS, (void**)&g_pBits, 0, 0);//创建应用程序可以直接写入的、与设备无关的位图(DIB)

        g_hOldBmp = (HBITMAP)::SelectObject(g_hMemDC, g_hBmp);//复原兼容DC数据

        BitBlt(g_hMemDC, 0, 0, width, height, pDC->m_hDC, 0, 0, SRCCOPY);

       //修改图像内容:g_pBits

       int l_width = WIDTHBYTES(img->width* pbmi->bmiHeader.biBitCount);

       for (int row = 0; row < img->height; row++)

       memcpy(&g_pBits[row*l_width], &img->imageData[ (img->height - row - 1)*l_width], l_width);

 

        TransparentBlt(pDC->m_hDC, 0, 0, width, height, g_hMemDC, 0, 0, img->width, img->height, RGB(0, 0, 0));

        SelectObject(g_hMemDC, g_hOldBmp);

 

       //释放内存资源

       ReleaseDC(pDC);

       DeleteDC(g_hMemDC);

       DeleteObject(pic);

       DeleteObject(g_hBmp);

       DeleteObject(g_hOldBmp);



然后在按钮的消息响应函数中添加如下代码:

void CImageRetrievalSystemDlg::OnBnClickedButtonQuery()

{
// TODO: 在此添加控件通知处理程序代码
CFileDialog dlg(true,_T("*.jpg"),NULL,OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,_T("image file(*.bmp;*.jpg;*.png)|*.bmp;*.jpg;*.png|All                Files(*.*)|*.*|"),NULL);
dlg.m_ofn.lpstrTitle=_T("open Image");
if(dlg.DoModal()!=IDOK)
     return;
CString query_path=dlg.GetPathName();

        query_path.Replace(_T("//"),_T("////"));
IplImage *qimg =cvLoadImage((CT2CA)query_path,1);
if(qimg!=NULL)
{
ShowImage(qimg,IDC_STATIC_QUERY);// IDC_STATIC_QUERY为picture control ID
}

}

最后运行程序结果如下:



点击按钮“查询图像”,载入任意一张图片:



自己尝试做的一个小demo,记录下来,为初学者提供一个方向,也为自己梳理下思路。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OpenCV MFC