Qt 2D繪圖(6):QPixmap類及蒙版原理

Qt 2D繪圖(6):QPixmap類及蒙版原理

若對C++語法不熟悉,建議參閱《C++語法詳解》一書,電子工業出版社出版,該書語法示例短小精悍,對查閱C++知識點相當方便,並對語法原理進行了透徹、深入詳細的講解,可確保讀者徹底弄懂C++的原理,徹底解惑C++,使其知其然更知其所以然。此書是一本全面瞭解C++不可多得的案頭必備圖書。

12.13.4 QPixmap類中的成員函數

QPixmap默認支持的文件格式如表12-23
在這裏插入圖片描述

1、構造函數

1)、QPixmap();		QPixmap(int width, int height);		QPixmap(const QSize &size);
2)、QPixmap(const QString &fileName, const char *format = Q_NULLPTR,Qt::ImageConversionFlags flags = Qt::AutoColor);
	使用格式format加載文件fileName,若文件不存在或格式未知,則創建一個空像素圖,若加載圖像時未指定格式,則加載程序會嘗試猜測文件格式。參數flags用於指示圖像怎樣從高分辨率轉換爲低分辨率。枚舉Qt::ImageConversionFlag見表12-21。
3)、QPixmap(const char * const[] xpm);
	使用xpm數據構造一個像素圖,注:XPM是一種X11上使用的圖像格式,是一種基於ASCII編碼的圖像格式。

2、像素圖的加載和存儲

4)、bool load(const QString &fileName, const char *format = Q_NULLPTR,Qt::ImageConversionFlags flags = Qt::AutoColor);
	使用格式format加載文件fileName,若加載成功則返回true,否則返回false。
	若加載圖像時未指定格式,則加載程序會嘗試猜測文件格式。
	參數flags用於指示圖像怎樣從高分辨率轉換爲低分辨率。枚舉Qt::ImageConversionFlag見表12-21。
	加載文件後對像素圖的修改並不會改變原始文件fileName的內容。
5)、bool loadFromData(const uchar *data, uint len, const char *format = Q_NULLPTR, Qt::ImageConversionFlags flags = Qt::AutoColor);
bool loadFromData(const QByteArray &data, const char *format = Q_NULLPTR, Qt::ImageConversionFlags flags = Qt::AutoColor);
	使用格式format從二進制數據data加載一個像素圖,若加載成功則返回true。
6)、static QPixmap fromImageReader(QImageReader *imageReader,Qt::ImageConversionFlags flags = Qt::AutoColor);   //靜態的
	直接從imageReader讀取的圖像創建一個像素圖。在某些系統上,把圖像讀入到QPixmap比讀取QImage再將其轉換爲QPixmap使用更少的內存。枚舉Qt::ImageConversionFlag見表12-21。
7)、bool save(const QString &fileName, const char *format = Q_NULLPTR, int quality = -1) const;
	使用給定的質量quality和文件格式format把像素圖保存到文件fileName中。
	若成功,則返回true,否則返回false,
	質量因子quality必須在0~100範圍內,值0表示小型壓縮文件,100表示未壓縮文件,-1表示使用默認值。
	若format爲0,則從fileName的後綴中選擇圖像格式。
8)、bool save(QIODevice *device, const char *format = Q_NULLPTR, int quality = -1) const;
	此函數表示把文件寫入設備device中,比如可把文件寫入QByteArray中。
9)、qint64 cacheKey() const;
	返回標識此QPixmap的編號,當改變像素圖時cacheKey()將發生改變。
10)、void detach();
	從共享像素圖中分離像素圖。當像素圖的內容即將發生改變時(比如調用fill()、fromImage()、load()等),Qt就會自動分離它。

示例12.29:把像素圖保存到文件與繪製到QWidget部件的區別

void paintEvent(QPaintEvent *e){
    		QPainter pr;
    		QPixmap pm;
		pm.load("F:/1i.png");
    		qDebug()<<pm.cacheKey();   			//1、驗證改變像素圖時cacheKey()的值會被改變。
	//在pm繪製一直線
    		pr.begin(&pm);		pr.drawLine(11,11,44,111);		pr.end();
    		qDebug()<<pm.cacheKey();   			 //此處輸出的值與在1處輸出的值不相同。
pr.begin(this);		
pr.drawPixmap(11,11,333,222,pm); 	//把pm繪製到QWidget部件的矩形(11,11,444,333)上。
    		pm.save("F:/zzz.png");	   			//保存圖像
pr.end();}   

運行結果及說明見圖12-68
在這裏插入圖片描述

3、像素圖的基本信息

11)、int depth() const;      			//返回像素圖的深度,空像素圖深度爲0。
static int defaultDepth(); 		//返回該程序使用的默認像素圖深度,通常返回主屏幕的深度。靜態的
12)、int height() const;   			//返回像素圖的高度。
int width() const;  			//返回像素圖的寬度
QSize size() const;   			//返回像素圖的大小。
QRect rect() const;   			//返回像素圖的包圍矩形。
13)、bool isNull() const;   			//若像素圖是空的,則返回true。空像素具有零寬度、零高度和零內容。 
bool isQBitmap() const;   		//若像素圖是一個QBitmap則返回true。
14)、bool hasAlpha() const;   		//若像素圖具有alpha通道或蒙版,則返回true。該函數是遺留函數。
bool hasAlphaChannel() const;   			//若像素圖具有alpha通道格式,則返回true。
void setAlphaChannel(const QPixmap &p);	//不推薦使用。可使用QPainter::CompositionMode()代替
QPixmap alphaChannel() const;   			//不推薦使用該函數,可使用QPainter::CompositionMode()代替
15)、qreal devicePixelRatio() const; 			//返回設備像素比,默認爲0。
void setDevicePixelRatio(qreal scaleFactor);  
	設置設備像素比。默認爲1。
	在顯示圖片時,若把設備像素比設置爲其他值,將使圖片被縮放。比如若設置設備像素比爲2(這時相當於提高了當前繪製設備的分辨率),若圖片的大小爲200*200,由於圖片的大小始終是固定不變的,因此在顯示時將被縮小爲100*100(高分變率設備將顯示得更小)。
void paintEvent(QPaintEvent *e){
   			QPainter pr;
            	QPixmap pm;
        		pm.load("F:/2.jpg");		//假設圖片大小爲300*300(這個大小是不會變的)
    			pm.setDevicePixelRatio(2);	//設置設備像素比爲2。
   			pr.begin(&pm);			//在pm上繪製圖形
    			pr.drawLine(0,100,100,100);	//此直線繪製到pm上時,將變爲(0,200,200,200)
    			pr.end();
pr.begin(this);			//在當前設備上繪製圖形
pr.drawPixmap(11,11,pm); 	//把pm顯示到當前設備上,圖片2.jpg將被顯示爲
//150*150的大小,且繪製的直線顯示爲(0,100,100,100)
pr.end();
pm.save("F:/2222.jpg");	}	//保存圖像,圖像222.jpg的大小仍爲300*300,但在該圖像上
//繪製的直線爲(0,200,200,200),可在F盤找到該文件進行查看

4、像素圖的複製、填充、替換

16)、void fill(const QColor &color = Qt::white);   		//使用顏色color填充像素圖。
17)、QPixmap copy(const QRect &rectangle = QRect()) const;
QPixmap copy(int x, int y, int width, int height) const;
	返回矩形範圍內的像素圖的深層副本,若rectangle爲空,則複製整個圖像,深層副本詳見隱式數據共享。
18)、void swap(QPixmap &other);   	//把該像素圖與other交換。

5、像素圖的縮放與滾動

19)、QPixmap scaled(const QSize &size, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation) const;
QPixmap scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation) const;
	把像素圖縮放到給定的大小,並返回縮放後的副本(注意:不會修改原始像素圖)。若size爲空或width、height爲0 或負,則函數返回空像素圖。其中參數aspectRatioMode用於指定縮放時是否保持高寬比,transformMode用於指定縮放時是否平滑圖像。Qt::AspectRatioMode和Qt::TransformationMode枚舉分別見表12-24和表12-25及示例12.30

在這裏插入圖片描述

示例12.30:像素圖的縮放(結果見圖12-69)
void paintEvent(QPaintEvent *e){
QPainter pr;    QPixmap pm(120,55);    QFont f;    f.setPointSize(33);
//在pm上繪製文字
    pr.begin(&pm);    pr.setFont(f);    pr.drawText(0,33,"ABCDF");    pr.end();
pr.begin(this);    pr.drawPixmap(11,11,pm);   //繪製原始文字
//不保留縱橫比
QPixmap pm1=pm.scaled(100,100,Qt::IgnoreAspectRatio);    pr.drawPixmap(133,11,pm1);
//在給定矩形(100,100)內,圖像尺寸在保持縱橫比的情形下,圖像保持最大矩形。
QPixmap pm2=pm.scaled(100,100,Qt::KeepAspectRatio);    pr.drawPixmap(255,11,pm2);
//在給定矩形外,圖像尺寸在保持縱橫比的情形下,圖像外部尺寸保持儘可能小的矩形。
    QPixmap pm3=pm.scaled(100,100,Qt::KeepAspectRatioByExpanding);	pr.drawPixmap(377,11,pm3);
pr.end();}

在這裏插入圖片描述

20)、QPixmap scaledToHeight(int height, Qt::TransformationMode mode = Qt::FastTransformation) const;
QPixmap scaledToWidth(int width, Qt::TransformationMode mode = Qt::FastTransformation) const;
	返回縮放後的像素圖的副本,像素圖被保持縱橫比縮放到給定的高度height或寬度width,未指定的寬度或高度由縱橫比自動計算。若width、height爲0或負,則返回空像素圖。
21)、void scroll(int dx, int dy, int x, int y, int width, int height, QRegion *exposed = Q_NULLPTR);
void scroll(int dx, int dy, const QRect &rect, QRegion *exposed = Q_NULLPTR);
	把像素圖的矩形部分rect滾動(dx, dy)距離,區域exposed可用於保存未被改變的區域部分,當像素圖上有一個活動的QPainter時,無法進行滾動。原理見示例12.31

示例12.31:圖像滾動原理

void paintEvent(QPaintEvent *e){
    		QPainter pr(this);    		QPixmap pm("F:/111.png");	QRegion g;  
QRect r(33,33,111,111);		pm.scroll(33,33,r,&g);		pr.drawPixmap(11,11,pm);
//輸出:QRegion(size=2,bounds=(33,33 111x111)-[(33,33 111x33),(33,66 33x78)])
qDebug()<<g;} 

在這裏插入圖片描述

6、像素圖變換

22)、QPixmap transformed(const QTransform &transform, Qt::TransformationMode mode = Qt::FastTransformation) const;
QPixmap transformed(const QMatrix &matrix,Qt::TransformationMode mode = Qt::FastTransformation) const;
	返回使用transform變換後的像素圖的副本,原始像素圖不會改變。轉換時會在內部調整變換矩陣,以補償不必要的轉換,使用trueMatrix()函數可獲得實際的變換矩陣。注:QMatrix類已過時。Qt::TransformationMode枚舉見表12-25。
23)、static QTransform trueMatrix(const QTransform &matrix, int width, int height);		//靜態的
static QMatrix trueMatrix(const QMatrix &m, int w, int h);					//靜態的
	返回轉換具有寬度width、高度height和變換矩陣matrix的像素圖的實際變換矩陣。注:QMatrix類已過時。

7、QPixmap與QImage之間的轉換

24)、QImage toImage() const;
	把該像素圖轉換爲QImage(圖像),若轉換失敗,則返回空圖像。若像素圖的深度爲1,則返回的QImage也是1的深度。注意:單色圖像上的alpha蒙版將被忽略。
25)、static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor);   	//靜態的
static QPixmap fromImage(QImage &&image,Qt::ImageConversionFlags flags = Qt::AutoColor);  	//qt5.3,靜態的
	把圖像image使用標誌flags轉換爲像素圖。枚舉Qt::ImageConversionFlag見表12-21。
26)、bool convertFromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor);
	使用圖像image替換此像素圖的數據。枚舉Qt::ImageConversionFlag見表12-21,該函數的原理見示例12.32。

示例12.32:convertFromImage()函數的使用(效果見圖12-71)

void paintEvent(QPaintEvent *e){
   		QPainter pr(this);   QPixmap pm("F:/1i.png");   QImage pi("F:/1m.png");
   		pr.drawPixmap(11,11,pm);   pr.drawImage(77,11,pi);
   		pm.convertFromImage(pi);   pr.drawPixmap(288,11,pm);}

在這裏插入圖片描述

8、蒙版(mask)
蒙版的概念:
在繪圖軟件中,蒙版類似於蒙在原始圖片上的一塊玻璃(即蒙版),然後我們再在這塊玻璃上使用其他工具對圖片進行修改,這樣就不會破壞原始圖片,而又能看到圖片修改後的效果。
蒙版通常是黑白色的,通常通過改變蒙版(玻璃)的灰度可改變蒙版的透明度,從而可使原始圖片變爲可見、不可見、透明三種效果,也就是說蒙版本身只能改變透明度,並不能改變原始圖像的色彩或其他性質(這些性質的改變需藉助其他工具)。
蒙版很少有彩色蒙版,幾乎都是黑白色的(即只能通過灰度改變透明度),雖然可使用蒙版矇住原始圖的某個通道,但蒙版本身仍是黑白色的。比如使用蒙版矇住紅色通道,則通過改變蒙版本身的透明度,可使原始圖的紅色變爲可見、不可見或透明,但蒙版本身並不是彩色的。
Qt通常使用QBitmap類來保存蒙版,QBitmap類是一個只有1位深度的圖像,因此Qt的蒙版只能在可見和不可見之間變換,不能實現透明度的效果。
注意:被蒙板黑色部分遮擋的像素會被顯示,被白色部分遮檔的像素不會被顯示。白色:顯示、不透明。黑色:隱藏、透明。
下面爲QPixmap類中與蒙版有關的函數

27)、void setMask(const QBitmap &mask);
	設置蒙版位圖。此函數把蒙版與像素圖的alpha通道合併,蒙版(即一個QBitmap圖像)上的像素值爲1(黑色),則像素圖的像素不變(即仍被顯示),若蒙版的值爲0,則表示像素圖的像素是透明的(即隱藏而不被顯示)。蒙版必須與此像素圖具有相同的大小。在繪製像素圖時,此函數的效果是未定義的。該函數可能是一項昂貴的操作。
28)、QBitmap mask() const;
	從像素圖的alpha通道創建一個蒙版,該函數是遺留函數(因爲操作可能會很昂貴),不應被使用。
29)、QBitmap createHeuristicMask(bool clipTight = true) const;
	爲此像素圖創建並返回一個啓發式蒙版,該函數的工作原理是從一個角中選擇一種顏色,然後從所有邊緣開始切掉該顏色的像素,若clipTight爲true,則蒙版的大小足以覆蓋像素。該函數可能會很慢。
30)、QBitmap createMaskFromColor(const QColor &maskColor, Qt::MaskMode mode = Qt::MaskInColor) const;
	使用顏色maskColor爲此像素圖創建一個蒙版,若mode是Qt::MaskInColor,則與maskColor匹配的所有像素都是透明的,即隱藏像素,不顯示該像素,若model是Qt::MaskOutColor,則與maskColor匹配的所有像素都是不透明的,即顯示該像素。

示例12.33:createHeuristicMask()函數創建的蒙版(效果見圖12-72)

void paintEvent(QPaintEvent *e){
QPainter pr(this);   QPixmap pm("F:/1z.png");   QPixmap pm1("F:/1z.png");
//創建兩個蒙版
   QBitmap pt=pm.createHeuristicMask(true);   QBitmap pt1=pm1.createHeuristicMask(false);
   pr.drawPixmap(11,11,pm);   //繪製原始圖片
//蒙版pt的效果
   pm.setMask(pt);   pr.drawPixmap(222,11,pm);   pr.drawPixmap(222,222,pt);
//蒙版pt1的效果
   pm1.setMask(pt1);   pr.drawPixmap(444,11,pm1);   pr.drawPixmap(444,222,pt1);}

在這裏插入圖片描述

示例12.34:createMaskFromColor()函數創建的蒙版(效果見圖12-73)

void paintEvent(QPaintEvent *e){
   QPainter pr(this);   QPixmap pm("F:/1z.png");   QPixmap pm1("F:/1z.png");
//創建兩個蒙版
   QBitmap pt2=pm.createMaskFromColor(QColor(255,0,0),Qt::MaskInColor);
   QBitmap pt3=pm.createMaskFromColor(QColor(255,0,0),Qt::MaskOutColor);
   pr.drawPixmap(11,11,pm);	//繪製原始圖片
//蒙版pt2的效果
pm.setMask(pt2);   pr.drawPixmap(222,11,pm);   pr.drawPixmap(222,222,pt2);
//蒙版pt3的效果
   pm1.setMask(pt3);   pr.drawPixmap(444,11,pm1);   pr.drawPixmap(444,222,pt3);}

在這裏插入圖片描述

示例12.35:setMask()函數會合並蒙版

void paintEvent(QPaintEvent *e){
   QPainter pr(this);   QPixmap pm("F:/1z.png");
   QBitmap pt=pm.createHeuristicMask(true);
   QBitmap pt2=pm.createMaskFromColor(QColor(0,255,0),Qt::MaskInColor);
   pr.drawPixmap(11,11,pm);   			//繪製原始圖像。
   pm.setMask(pt);   pm.setMask(pt2);   	//同一像素圖上設置兩個蒙板,這兩個蒙版會合並。
   pr.drawPixmap(222,11,pm);   pr.drawPixmap(444,11,pt);   pr.drawPixmap(666,11,pt2);}

運行結果及說明(見圖12-74)
在這裏插入圖片描述

12.13.5 QBitmap類(位圖)中的成員函數

QBitmap類繼承自QPixmap,該類描述的是1位深度(單色)的像素圖,即只有兩種色的像素圖。該類主要用於創建自定義的QCursor(光標)對象、QRegion對象及設置圖像的蒙版等。
若把深度大於1的像素圖分配給QBitmap,則QBitmap將自動抖動。
使用Qt::color0將位圖的位設置爲0,使用Qt::color1把位圖的位設置爲1。其中0表示背景(透明像素),1表示前景(不透明像素)。注意:使用Qt::black(黑色)和Qt::white(白色)沒有意義。位圖的效果見圖12-75。

在這裏插入圖片描述

QBitmap類中的函數如下

1)、QBitmap();		//構造函數
QBitmap(int width, int height);
QBitmap(const QSize &size);
QBitmap(const QPixmap &pixmap);   //使用pixmap構造一個位圖
QBitmap(const QString &fileName, const char *format = Q_NULLPTR);
QBitmap(const QBitmap &other);
2)、void clear();    				//清除位圖,即把所有位設置爲Qt::color0。
3)、void swap(QBitmap &other);   	//把該位圖與other交換。
4)、QBitmap transformed(const QTransform &matrix) const;  
	使用變換矩陣matrix變換位圖,並返回變換後的副本。
5)、static QBitmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor);  //靜態的
	把圖像image轉換爲位圖,並返回其副本。枚舉Qt::ImageConversionFlag見表12-21。
6)、static QBitmap fromData(const QSize &size, const uchar *bits, 
QImage::Format monoFormat = QImage::Format_MonoLSB);  //靜態的
	構造一個大小爲size的位圖,並把內容設置爲bits,位圖數據必須是字節對齊的,並需按monoFormat指定的位順序提供,單色圖格式必須是QImage::Format_Mono或QImage::Format_MonoLSB。

本文作者:黃邦勇帥(原名:黃勇)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章