要实现图像的ROI显示,即选择图像中的某一区域,显示该区域的原图像。其核心的问题归纳有如下三个:
①.得到缩略图像
②.实现鼠标事件,获取鼠标的坐标
③.将坐标转换为原图像中的坐标,从而就找到了需要的原图像数据区,将它读出来
1,缩略图
显示出原图缩略图的关键是找到缩小倍数,缩小倍数根据显示控件和原图像的大小决定。假设显示区的宽和高相同
原则:原图像宽>高时,缩略图的宽为显示区的宽,缩略图的高通过计算得出(小于显示区的宽);反之,源图像宽<高时,则缩略图的高为显示区的高,缩略图的宽通过计算得出(小于显示区的宽)
通过缩略图的大小就可以得出缩小倍数
然后通过缩小倍数读出缩略图所需数据,以下是RasterIO接口详解
原图像大小:sizeX*sizeY 缩略图大小:width*height 缩小倍数zoom
1 unsigned char *data=new unsigned char[width*height]; 2 poBand->RasterIO(GF_Read, 3 0,0, 4 sizeX,sizeY, 5 data, 6 width,height, 7 GDT_Byte, 8 0,0);
这样需要的数据就读到data中了,RasterIO最后两个参数为0为什么这样至今任未明白,按照参考文档应该是具体的字节值才是,但是经过很多次的测试,只有都为0时才能正确显示图像。
注:显示图像使用的是QImage,图像中波段组织形式为RGB888,即三个波段,每个波段8位。上面data只是8位的灰度数据,要显示出来还需复制两个波段,使每个波段像素值都相等,这样形成灰度图像。不知道使用qt有没有其他的方法显示图像,VC可以显示1个波段的图像,QT好像不可以(有待验证),至少目前没有找到方法,要是可以的话在上图像数据量比较大时可以节约内存。
2.鼠标事件
鼠标事件在基类中是虚函数,没有实现的(见帮助文档),要捕获鼠标事件,必须重写函数,如下几个与鼠标事件有关:
这里只需要处理mousePressEvent(鼠标按下)和mouseReleaseEvent(鼠标释放)事件。
因为显示缩略图的控件QLabel只是主界面的子部件,因此重写主界面类(派生自QMainWindow)的鼠标事件,而不是在QLabel派生类中实现。在QLabel派生类中实现的话,很难将信息传递给主界面类,程序的功能是在主界面类中实现的。缩略图中的鼠标事件要实时获取,而在QLabel中点击鼠标,QMainWindow派生类中的鼠标事件可以获取到。而有些部件(比如QGraphicsView)就不能获取,在这些部件上处理鼠标事件在后面图像拖拽时讲解。
需要的坐标信息如下:菜单栏和工具栏的高度,缩略图显示区大小,缩略图大小,缩略图显示区左上角坐标(其值时相对于主窗口区的),鼠标按下和释放时的坐标(其值时相对于整个界面的)。根据如上几个数据信息就可以计算出鼠标按下和释放所包含的范围,即起始点(鼠标按下时)在缩略图中的坐标位置和终止点(鼠标释放时)在缩略图中的坐标位置。
3.原图区域显示
得到了鼠标在缩略图中的坐标位置,根据缩小倍数zoom,既可以得到在源图像中的坐标位置(×zoom),然后用RasterIO读取区域中的数据。如何读区域数据就不多说了,请参照RasterIO的使用http://www.cnblogs.com/Romi/archive/2012/03/29/2424073.html
读取出数据后显示出来,这里使用了QGraphicsView框架,使用其显示内存中图像数据的方法如下:
1 QImage *img=new QImage(.......);//将内存中data数据组织为可显示的QImage对象 2 QPixmap pixmap=QPixmap::fromImage(*img); 3 QGraphicsScene *scene=new QGraphicsScene; 4 QGraphicsPixmapItem *pixmapItem=new QGraphicsPixmapItem; 5 pixmapItem=scene->addPixmap(pixmap); 6 ui.graphicsView->setScene(scene); 7 ui.graphicsView->show();