要實現圖像的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();