Qt的4個圖像類QImage/QPixmap/QBitmap/QPicture 轉


(一)QPixmap和QImage的區別

http://www.thisisqt.com/forum/viewthread.php?tid=267

 

QPixmap是專門為繪圖而生,當需要繪制圖片時你需要使用QPixmap。QImage則是為I/O,為圖片像素訪問以及修改而設計的。如果你 想訪問圖片的像素或是修改圖片像素,則需要使用QImage,或者借助於QPainter來操作像素。另外跟QImage不同是,QPixmap跟硬件是 相關的,如X11, Mac 以及 Symbian平台上,QPixmap 是存儲在服務器端,而QImage則是存儲在客戶端,在Windows平台上,QPixmap和QImage都是存儲在客戶端,並不使用任何的GDI資 源。

相信大家更關心的是誰比較快,哈哈,現在來總結一下:
在X11, Mac 以及 Symbian平台上,QImage: 因為它是存儲在客戶端,往QImage上繪圖比較快,但顯示它則比較慢。QPixmap: 因為它是存儲在服務器端,往QPixmap上繪圖比較慢,但顯示它則比較快。但在Windows平台上則是是一樣的,因為它們都存儲在客戶端。


Qt上圖片處理使用QPixmap和QImage時最多了,不過既然談到圖片了,我們把其他幾個圖片處理類也說一下:
QBitmap只是一個繼承於QPixmap的簡單類,它可以確保圖片深度為1。
QBitmap是QPixmap的子類,提供單色圖像,可以用來制作游標(QCursor)或者筆刷(QBrush)。

 

QPicture是一個繪畫設備類,它記錄了並可以重演QPainter的命令。你可以使用QPainter的begin()方法,指定在 QPicture上繪圖,使用end()方法結束繪圖,使用QPicture的save()方法將QPainter所使用過的繪圖指令存至檔案。要重播繪 圖指令的話,建立一個QPicture,使用load()方法載入繪圖指令的檔案,然后在指定的繪圖裝置上繪制QPicture:

 

(二)QImage與QPixmap完全解析

http://www.civilnet.cn/bbs/browse.php?topicno=4691

用Qt程序在手機上顯示一幅圖片對編程人員來說是再基礎不過的一件事情了。那么先讓大家看兩段代碼:

//dangerous should not be used, cannot display earth.png,  
//but if we change earth.png to a smaller image e.g. apple.png, apple.png can be displayed
QPixmap pixmap;
pixmap.load( ":/pics/earth.png" );
label->setPixmap( pixmap );


//dangerous should not be used, cannot display earth.png,  
//but if we change earth.png to a smaller image e.g. apple.png, apple.png can be displayed
QPixmap pixmap;
pixmap.load( ":/pics/earth.png" );
QPainter painter(this);
painter.drawPixmap(0,0, pixmap);
大 家認為這兩段代碼有什么問題嗎? 看起來好像沒什么問題啊。是的,在Windows操作系統上是沒有問題的。問題是我們做的是Qt for Symbian! 手機上的資源本來就是比較緊缺的,所以我們使用的時候就需要更加注意。 Qt 為我們提供了四個處理圖像的類:QImage,QPixmap,QBitmap 和QPicture。其中前兩個是最常使用的。

本文就通過一個例子,一步一步為大家講解QImage與QPixmap的使用奧秘,在此過程中為大家揭示以上代碼存在的缺陷。
QPixmap依賴於硬件

首先需要知道的是QPixmap的具體實現是依賴於系統的。在Symbian系統上QPixmap是被存放在Server端的。
目前的Qt會把QPixmap都存儲在graphics memory中,這明顯是依賴硬件的。因此我們對QPixmap的使用需要格外注意。這也正是以上兩段代碼存在問題的根源。
那么Qt為什么要這么做呢?很簡單,設計之初QPixmap就是用來加速顯示的,例如我們在paint的時候用QPixmap就會比用其他類的效果好許多。

現在回到我們最初的問題,以上代碼到底有什么問題呢?我們可以先用本文提供的例子程序做個試驗。當使用上述代碼顯示較小圖片的時候(比如例子程序中的background.png 和apple.png)是沒有問題的,圖片都能在手機上正確顯示。
但是當我們把圖片換成一副較大圖片287KB,1058 x 1058的“earth.png”的時候就出現問題了,圖片無法顯示,程序的界面是一片空白。

據測算,“earth.png”被完全解碼后存儲在graphics memory中會占用大約4.3MB的空間。如果此時還有其他加載的窗口和QPixmap,很可能就沒有空間了。
使用QImage加載后轉換成QPixmap 顯示

那么安全和正確的方法應該是什么呢?答案是我們需要用QImage做一下預處理:

//correct and recommended way
QImage image;
image.load( ":/pics/earth.png" );

QPainter painter(this);
QPixmap pixmapToShow = QPixmap::fromImage( image.scaled(size(), Qt::KeepAspectRatio) );
painter.drawPixmap(0,0, pixmapToShow);
和QPixmap 不同,QImage是獨立於硬件的,它可以同時被另一個線程訪問。QImage是存儲在客戶端的,對QImage的使用是非常方便和安全的。 又由於 QImage 也是一種QPaintDevice,因此我們可以在另一個線程中對其進行繪制,而不需要在GUI 線程中處理,使用這一方式可以很大幅度提高UI響應速度。 因此當圖片較大時,我們可以先通過QImage將圖片加載進來,然后把圖片縮放成需要的尺寸,最后轉換成QPixmap 進行顯示。 下圖是顯示效果(圖片是按照earth.png的原始尺寸比例縮放后顯示的):




其中需要注意的是Qt::KeepAspectRatio的使用,默認參數是Qt::IgnoreAspectRatio,如果我們在程序中這么寫:

QPixmap pixmapToShow = QPixmap::fromImage( image.scaled(size(), Qt::IgnoreAspectRatio) );
效果就是下面這個樣子,earth.png被拉伸以充滿整個屏幕:


直接使用QImage 顯示

我們也可以直接使用QImage做顯示,而不轉換成QPixmap ,這要根據我們應用的具體需求來決定,如果需要的話我們可以這么寫:

//correct, some times may be needed
QImage image;
image.load( ":/pics/earth.png" );

QPainter painter(this);
painter.drawImage(0,0, image);
下面是顯示效果(當然我們也可以對其進行縮放之后再顯示) 從圖片可以看出來它是按照原始尺寸顯示earth.png的:




測試設備

本代碼已通過在N97和N8上的測試。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM