OpenCV 2.2版本号以上显示图片到 MFC 的 Picture Control 控件中
OpenCV 2.2 以及后面的版本号取消掉了 CvvImage.h 和CvvImage.cpp 两个文件,直接导致了苦逼的程序猿无法调用里面的显示函数来将图片显示到 MFC 的 Picture Control 控件中。为此,网上非常多人表示仅仅要将那两个文件人为的提取出来然后放到project里面就解决这个问题了,也提供了两个文件的下载,可是这麻烦不说。还会导致一些奇奇怪怪的报错(至少本人是这种,非常崩溃!)。所以在了解了一些gdi画图之后结合网上的代码写了例如以下的函数,仅仅需调用就能够将OpenCV的图片显示在上面了(仅仅支持三通道不支持单通道),初步測试效率跟原来两个文件差点儿相同。假设有大神请帮我完好这份代码!
配置好 OpenCV 后,在文件头部加入例如以下一行代码:
#define WIDTHBYTES(bits) (((bits)+31)/32*4)//用于使图像宽度所占字节数为4byte的倍数
在对话框类中声明函数:
void drawpic(IplImage* img, unsigned int id);//画图到 MFC 的 Picture Control 控件相关函数。參数一为 OpenCV 的图像数据结构类。參数二为 Picture Control 控件的id
定义函数例如以下:
void CMFCDrawDlg::drawpic(IplImage* img, unsigned int id)//CMFCDrawDlg为对话框类名
{
BITMAPINFO *pbmi;//位图信息
BYTE *bmibuf;//位图信息空间
BYTE *g_pBits;
HDC g_hMemDC;
HBITMAP g_hBmp;
CDC *pDC;
CStatic *pic;
int width, height;
CRect rect; //位图信息初始化
bmibuf = new BYTE[sizeof(BITMAPINFO)+256 * sizeof(RGBQUAD)];
memset(bmibuf, 0, sizeof(bmibuf));
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; //获得设备DC和显示宽高
pDC = GetDlgItem(id)->GetDC();
pic = (CStatic*)GetDlgItem(id);
pic->GetClientRect(&rect);
width = rect.Width();
height = rect.Height(); g_hMemDC = CreateCompatibleDC(pDC->m_hDC);//创建兼容设备环境的内存DC
g_hBmp = CreateDIBSection(g_hMemDC, pbmi, DIB_RGB_COLORS, (void**)&g_pBits, 0, 0);//创建应用程序能够直接写入的、与设备无关的位图
//改动图像内容: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); SelectObject(g_hMemDC, g_hBmp);//将位图对象选入g_hMemDC内存DC中
//拉伸画图
TransparentBlt(pDC->m_hDC, 0, 0, width, height, g_hMemDC, 0, 0, img->width, img->height, RGB(1, 0, 0));//RGB值原本设置为(0,0,0),只是似乎在这里画图会有bug,是故改为(1,0,0) //释放内存资源
ReleaseDC(pDC);
DeleteDC(g_hMemDC);
DeleteObject(pic);
DeleteObject(g_hBmp);
}
在须要将图片显示到 Picture Control 控件的地方加入例如以下代码就可以:
char *filename = "pic1.jpg";//图像路径
IplImage* img = cvLoadImage(filename);
drawpic(img, IDC_STATIC_SHOW);//IDC_STATIC_SHOW 为Picture Control 控件的ID
cvReleaseImage(&img);
离最開始写这篇文章已经非常久了,因为近期须要进行画图方面的工作且该工作要求画图效率非常高,是故又回过头来看这份东西。发现了一些错误,也把错误的地方改动掉了。相信有GDI画图基础的人应该早就看出来了,实在羞愧。
对于上面的那份代码,是能够适用于普通情况的画图工作的。然而假设须要进一步优化性能还是大有可为的,比方将程序拆分成“初始化”,“主体部分”,“内存释放”三个部分。便不用每次显示图片都进行初始化和内存释放,会进一步的提高程序的效率。以下将改动版本号的代码也放上来。
声明一个类用以存放位图和设备环境等相关信息:
class drawBitmapobj
{
public:
//位图对象
BITMAPINFO *pbmi;//位图信息
BYTE *bmibuf;//位图信息空间
BYTE *g_pBits;
HBITMAP g_hBmp;
CDC *pDC;
CRect rect;
CStatic *pic;
HDC g_hMemDC;
};
在对话框类中声明函数:
void drawpicinit(IplImage* img, unsigned int id, drawBitmapobj &mybmpobj);//初始化函数。參数一为 OpenCV的图像数据结构类,參数二为控件id,參数三为位图和设备信息对象
void drawpic(IplImage* img, drawBitmapobj &mybmpobj);//画图到MFC的 Picture Control 控件相关函数。參数一为 OpenCV的图像数据结构类,參数二为位图和设备信息对象
void drawrelease(drawBitmapobj &mybmpobj);//释放画图对象
由于涉及到位图,须要四字节对齐。所以将该公式也放在须要用到的文件头部:
#define WIDTHBYTES(bits) (((bits)+31)/32*4)//用于使图像宽度所占字节数为4byte的倍数
分别定义三个函数:
void CMFCDrawDlg::drawpicinit(IplImage* img, unsigned int id, drawBitmapobj &mybmpobj)
{
//位图信息初始化
mybmpobj.bmibuf = new BYTE[sizeof(BITMAPINFO)+256 * sizeof(RGBQUAD)];
memset(mybmpobj.bmibuf, 0, sizeof(mybmpobj.bmibuf));
mybmpobj.pbmi = (BITMAPINFO*)mybmpobj.bmibuf;
mybmpobj.pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
mybmpobj.pbmi->bmiHeader.biWidth = img->width;
mybmpobj.pbmi->bmiHeader.biHeight = img->height;
mybmpobj.pbmi->bmiHeader.biPlanes = 1;
mybmpobj.pbmi->bmiHeader.biBitCount = 24;
mybmpobj.pbmi->bmiHeader.biCompression = BI_RGB; mybmpobj.pDC = GetDlgItem(id)->GetDC();
mybmpobj.pic = (CStatic*)GetDlgItem(id);
mybmpobj.pic->GetClientRect(&mybmpobj.rect); mybmpobj.g_hMemDC = CreateCompatibleDC(mybmpobj.pDC->m_hDC);//创建兼容设备环境的内存DC
mybmpobj.g_hBmp = CreateDIBSection(mybmpobj.g_hMemDC, mybmpobj.pbmi, DIB_RGB_COLORS, (void**)&mybmpobj.g_pBits, 0, 0);//创建应用程序能够直接写入的、与设备无关的位图
} void CMFCDrawDlg::drawpic(IplImage* img, drawBitmapobj &mybmpobj)//CMFCOpenCVShowDlg 为对话框类名
{
//改动图像内容:g_pBits
//这里这么做一则为BMP图像的四字节对齐机制。二则是由于BMP图像是从图像的左下角開始算起的,假设直接拷贝会导致图像上下颠倒
int l_width = WIDTHBYTES(img->width* mybmpobj.pbmi->bmiHeader.biBitCount);
for (int row = 0; row < img->height; row++)
memcpy(&mybmpobj.g_pBits[row*l_width], &img->imageData[(img->height - row - 1)*l_width], l_width); SelectObject(mybmpobj.g_hMemDC, mybmpobj.g_hBmp);//将位图对象选入g_hMemDC内存DC中
//拉伸画图
TransparentBlt(mybmpobj.pDC->m_hDC, 0, 0, mybmpobj.rect.Width(), mybmpobj.rect.Height(), mybmpobj.g_hMemDC, 0, 0, img->width, img->height, RGB(1, 0, 0));//RGB值原本设置为(0,0,0),只是似乎在这里画图会有bug,是故改为(1,0,0)
} void CMFCDrawDlg::drawrelease(drawBitmapobj &mybmpobj)
{
//释放内存资源
delete[]mybmpobj.bmibuf;
DeleteDC(mybmpobj.g_hMemDC);
DeleteObject(mybmpobj.pic);
DeleteObject(mybmpobj.g_hBmp);
ReleaseDC(mybmpobj.pDC);
}
做完上面那些就OK了,调用的方式例如以下:
drawBitmapobj mybmpobj;
char *filename = "1.jpg";//图像路径
IplImage* img = cvLoadImage(filename);
drawpicinit(img, IDC_STATIC_SHOW, mybmpobj);
long begintime = clock();
int i = 8;
while (i--)
{
drawpic(img, mybmpobj);//IDC_STATIC_SHOW 为Picture Control 控件的ID
}
printf("消耗时间:%dms\n", (clock() - begintime)/8);
cvReleaseImage(&img);
drawrelease(mybmpobj);
当然。也能够进一步直接将其封装成一个类
#include "stdafx.h"
#include "afxdialogex.h" /****************************
**名字:绘制图像类
**功能:Opencv输入的IplImage图像对象绘制图像到指定窗口的控件中
**解释:showWnd为指定窗口,id为指定窗口id。img为输入图像对象
**作者:weixinhum
**时间:2015/10/29
****************************/
class PaintImgToScreenControls : public CDialogEx
{
public:
//位图对象
BITMAPINFO *pbmi;//位图信息
BYTE *bmibuf;//位图信息空间
BYTE *g_pBits;
HBITMAP g_hBmp;
CDC *pDC;
CRect rect;
CStatic *pic;
HDC g_hMemDC;
void drawpicinit(IplImage* img, unsigned int id, CWnd* showWnd);//初始化函数。參数一为 OpenCV的图像数据结构类,參数二为控件id
void drawpic(IplImage* img);//画图到MFC的 Picture Control 控件相关函数,參数一为 OpenCV的图像数据结构类
void drawrelease();//释放画图对象
CWnd* mShowWnd;
}; #define WIDTHBYTES(bits) (((bits)+31)/32*4)//用于使图像宽度所占字节数为4byte的倍数 void PaintImgToScreenControls::drawpicinit(IplImage* img, unsigned int id, CWnd* showWnd)
{
//位图信息初始化
bmibuf = new BYTE[sizeof(BITMAPINFO)+256 * sizeof(RGBQUAD)];
memset(bmibuf, 0, sizeof(bmibuf));
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;
mShowWnd = showWnd;
pDC = mShowWnd->GetDlgItem(id)->GetDC();
pic = (CStatic*)mShowWnd->GetDlgItem(id);
pic->GetClientRect(&rect); g_hMemDC = CreateCompatibleDC(pDC->m_hDC);//创建兼容设备环境的内存DC
g_hBmp = CreateDIBSection(g_hMemDC, pbmi, DIB_RGB_COLORS, (void**)&g_pBits, 0, 0);//创建应用程序能够直接写入的、与设备无关的位图
} void PaintImgToScreenControls::drawpic(IplImage* img)//CMFCOpenCVShowDlg 为对话框类名
{
//改动图像内容:g_pBits
//这里这么做一则为BMP图像的四字节对齐机制,二则是由于BMP图像是从图像的左下角開始算起的。假设直接拷贝会导致图像上下颠倒
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); SelectObject(g_hMemDC, g_hBmp);//将位图对象选入g_hMemDC内存DC中
//拉伸画图
TransparentBlt(pDC->m_hDC, 0, 0, rect.Width(), rect.Height(), g_hMemDC, 0, 0, img->width, img->height, RGB(1, 0, 0));//RGB值原本设置为(0,0,0),只是似乎在这里画图会有bug,是故改为(1,0,0)
} void PaintImgToScreenControls::drawrelease()
{
//释放内存资源
delete[]bmibuf;
DeleteDC(g_hMemDC);
DeleteObject(pic);
DeleteObject(g_hBmp);
mShowWnd->ReleaseDC(pDC);
}
然后调用
PaintImgToScreenControls paintObj;
char *filename = "pano.jpg";//图像路径
IplImage* img = cvLoadImage(filename);
paintObj.drawpicinit(img, IDC_STATIC_PANO, this);
int i = 8;
while (i--)
{
paintObj.drawpic(img);//IDC_STATIC_SHOW 为Picture Control 控件的ID
}
cvReleaseImage(&img);
paintObj.drawrelease();
OpenCV 2.2版本号以上显示图片到 MFC 的 Picture Control 控件中的更多相关文章
- OpenCV 通过 MFC 的 Picture Control 控件操作图像
假设希望对显示在MFC Picture Control 控件里的图像进行操作,比方画线画点之类的,能够利用 OpenCV 结合 MFC 本身的鼠标响应函数来实现. 怎样将图像显示到 Picture C ...
- C++MFC之picture control控件铺满图片
UpdateData(true); //更新路径公共变量 CString m_path = m_edit1.GetString(); if(m_path=="") ...
- 对话框上动态控件的创建、在Picture Control控件上显示图片
1 MFC对话框之上的动态控件的创建 对话框上的控件是MFC类的一个具体对象. 当在对话框之上使用静态控件时,可以根据类向导来为每个控件添加消息.响应函数以及变量. 当需要在对话框中动态的创建某个控 ...
- 如何在WindowsPhone Bing Map控件中显示必应中国中文地图、谷歌中国中文地图。
原文:如何在WindowsPhone Bing Map控件中显示必应中国中文地图.谷歌中国中文地图. 最近正好有点业余时间,所以在做做各种地图.Bing Map控件本身就能显示必应地图,但是很遗憾微软 ...
- MFC 对话框Picture Control(图片控件)中静态和动态显示Bmp图片
版权声明:本文为博主原创文章,转载请注明CSDN博客源地址! 共同学习,一起进步~ https://blog.csdn.net/Eastmount/article/details/26404733 ...
- Android实现图片轮显效果——自定义ViewPager控件
一.问题概述 使用ViewPager控件实现可横向翻页.水平切换图片等效果,但ViewPager需要手动滑动才能切换页面,图片轮显效果的效果本质上就是在ViewPager控件的基础上让它能自动的进行切 ...
- [Android] 拍照、截图、保存并显示在ImageView控件中
近期在做Android的项目,当中部分涉及到图像处理的内容.这里先讲述怎样调用Camera应用程序进行拍照,并截图和保存显示在ImageView控件中以及遇到的困难和解决方法. PS:作者购买 ...
- 在RichTextBox控件中插入图片
. 在RichTextBox控件中插入图片 关键点 . 实现过程 . public void ShowInsertImageDlg() { OpenFileDialog OpenFileD ...
- 在RichTextBox控件中添加图片和文字
public void SetText(RichTextBox rtb) { rtb.Text = "在RichTextBox控件中添加图片和文字" + Environment.N ...
随机推荐
- 写的cursor demo仅作记录
declare @objectID int; declare objcur cursor for object_id from m_object open objcur fetch next from ...
- XAMPP for Linux
XAMPP 的 Linux 版图片集锦 安装过程仅 4 个步骤 步骤 1:下载 XAMPP PHP 5.4 XAMPP PHP 5.5 步骤 2:安装 步骤 3:开始运行 步骤 4:测试 使 ...
- 《C++ primer》--第11章
习题11.1 algorithm头文件定义了一个count的函数,其功能类似于find.这个函数使用一对迭代器和一个值做参数,返回这个值出现次数的统计结果.编写程序读取一系列int型数据,并将它们存储 ...
- POJ2976 Dropping tests 01分数规划
裸题 看分析请戳这里:http://blog.csdn.net/hhaile/article/details/8883652 #include<stdio.h> #include<a ...
- Web自动化框架之五一套完整demo的点点滴滴(excel功能案例参数化+业务功能分层设计+mysql数据存储封装+截图+日志+测试报告+对接缺陷管理系统+自动编译部署环境+自动验证false、error案例)
标题很大,想说的很多,不知道从那开始~~直接步入正题吧 个人也是由于公司的人员的现状和项目的特殊情况,今年年中后开始折腾web自动化这块:整这个原因很简单,就是想能让自己偷点懒.也让减轻一点同事的苦力 ...
- html在图片上实现下雨效果
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...
- CSS基础知识——选择器
选择器 元素选择器# 文档元素为最基本的选择器 例子:div{属性:值}; 选择器分组 例子:h2,p{属性:值}; 表示符合这两种规则的元素设置相同的属性值 通配选择器 表示所有元素 类选择器 应用 ...
- bzoj 2594 [Wc2006]水管局长数据加强版(LCT+最小生成树)
[深坑勿入] [给个链接] http://blog.csdn.net/popoqqq/article/details/41348549 #include<cstdio> #include& ...
- 最短路径算法(Dijkstra算法、Floyd-Warshall算法)
最短路径算法具体的形式包括: 确定起点的最短路径问题:即已知起始结点,求最短路径的问题.适合使用Dijkstra算法. 确定终点的最短路径问题:即已知终结结点,求最短路径的问题.在无向图中,该问题与确 ...
- php 正则表达
今天看书,看到代码里面出现了一段正则表达式匹配语句preg_match,感觉水很深的感觉,网上搜了一些资料,暂时没时间学习,但是觉得以后学的话有两个网址比较靠谱,如下: php正则表达式手册:php ...