最近项目中要做一个图像显示的模块,需要支持OpenCV中的图像格式。虽然OpenCV中的highgui模块提供了简单易用的图像显示函数cvShowImage,可以直接将图像显示到一个弹出窗口中,但是貌似仅支持用cvNamedWindow创建出来的窗口(尽管文档中指出该函数在Win32环境中返回的是标准windows窗口句柄HWND,但是在调用cvShowImage时需要传入通过cvWindowName获得的窗口名称,windows中创建的窗口貌似名称都是空,所以目前我还没有成功),不能很方便的集成到其他系统中。所以不得不到源码中去探个究竟,看看cvShowImage是怎么实现的。 看了源码后才发现,cvShowImage写得非常简洁,是直接通过GDI来实现在窗口中绘制位图的,其中主要有三个步骤 1. 获得指定窗口的信息 OpenCV中,窗口都是通过窗口名称来调用的。这样做的好处是方便了快速调用(这也是highgui的定位),将句柄隐藏在了名称背后,但窗口其实还是标准的windows窗口。 2. 获得窗口关联的位图对象 众所周知,在GDI中设备上下文(Device Context)是一个非常核心的概念,它近乎完美的将系统中的“设备本身”和“设备所显示的内容”分离开来(所谓的松耦合)。尽管GDI很复杂,但作为Windows的图形界面引擎,无非是在解决两个问题: What:需要绘制什么内容。能够被绘制的东西在GDI中成为GDI对象,其中包括位图(BITMAP)、画笔(PEN)、画刷(BRUSH)等对象。 Where:在什么地方绘制。GDI中所有图形内容最终都展现在“设备”上,这里的“设备”可以是显示器、打印机、绘图仪等硬件图形输出设备,也可以是窗口、对话框等Windows对象,此外还可以是内存区域。 而上文提到的“设备上下文”其实就负责完成“GDI对象”和“设备”之间的工作。我想,到这里GDI基本的实现思想应该就比较清晰了。具体的实现过程中涉及到了几个关键的Windows API:
其中GDI对象类型可以是OBJ_BITMAP、OBJ_BRUSH等(详见http://msdn.microsoft.com/en-us/library/dd144869(VS.85).aspx)。用该函数获得窗口当前关联的位图对象后,便可以通过该位图对象实现在窗口中绘制想要的内容了。
3. 将用户图像数据绘制到窗口上 BITMAP结构体中,LPVOID类型的bmBits成员变量为指向位图数据区域的指针,使用OpenCV中的cvInitMatHeader将该指针初始化为一个CvMat对象的数据区域指针,然后再将图像数据填充到CvMat对象中去,这样最终窗口对应的位图对象中的数据就是用户指定的图像数据了。
由于之前对GDI了解甚少,只是在数年前的MFC中接触过一些,所以为了搞清楚这其中的过程,花了不少时间。在查阅了很多资料后终于大致弄清楚了GDI一些最基本的东西。不得不说,GDI概念很简单,但是实现实在是太复杂了。
posted on 2011-06-16 15:51 HienChu 阅读(2076) 评论(0) 编辑 收藏 引用
Powered by: C++博客 Copyright © HienChu