1. 程式人生 > >Qt影象合成原理

Qt影象合成原理

Qt影象合成原理

若對C++語法不熟悉,建議參閱《C++語法詳解》一書,電子工業出版社出版,該書語法示例短小精悍,對查閱C++知識點相當方便,並對語法原理進行了透徹、深入詳細的講解。

需要用到的QPainter類中的函式如下

	CompositionMode compositionMode() const;   		  	//返回當前的合成模式
void setCompositionMode(CompositionMode mode);		//設定當前的合成模式
	說明:僅在QImage上使用QPainter才能完全支援合成模式。列舉CompositionMode 見表12-30。
影象合成是基於畫素的運算,即在兩個影象進行合成時,逐畫素進行合成。

1、Proter-Duff合成公式
(1)、講解Proter-Duff合成公式前,先定義以下符號

	Sc:表示源畫素的顏色,即source color
	Dc:表示目標畫素的顏色,即destination color
	Rc:表示結果畫素的顏色,即result color
	Sa:表示源畫素的透明度,即source alpha
	Da:表示目標畫素的透明度,即destination alpha
	Ra:表示結果畫素的透明度,即result alpha
	Fs:表示源畫素的因子,即factor source 
	Fd:表示目標畫素的因子,即factor destination

(2)、注意:
①、alpha值使用的是01之間的小數,也就是說若alpha是使用的0255的值表示的,需把該值除以255,比如對於111的alpha值,其小數值為111/255。
②、顏色是使用的預乘alpha顏色(這樣Proter-Duff公式會更簡單)。
(3)、Proter-Duff公式,如下:

	Rc = Sc*Fs + Dc*Fd;      	//結果顏色(即合成後的顏色)
	Ra = Sa*Fs + Da*Fd;      	//結果alpha(即合成後的alpha)
也可寫為
	[Sa*Fs + Da*Fd, Sc*Fs + Dc*Fd ];  	//第一項為alpha值,第2項為顏色值
根據Fs和Fd的不同取值,共有12種不同的合成公式,比如若Fs = 1,Fd = (1 − Sa);時,得到如下公式
Rc = Sc + Dc*(1 − Sa);    Ra = Sa + Da*(1 − Sa);
   詳細的公式詳見對QPainter::CompositionMode列舉的講解(表12-30)

2、QPainter::CompositionMode列舉,見表12-30,合成的效果見圖12-83
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

示例12.40:影象合成示例
void paintEvent(QPaintEvent *e){
   QPainter pr;
//1、使用預乘alpha格式可提高執行速度
   QImage pi1(150,200,QImage::Format_ARGB32_Premultiplied);	//源,將繪製綠色影象
   QImage pi2(150,200,QImage::Format_ARGB32_Premultiplied);	//目標,將繪製紅色影象
//2、繪製兩個三角形路徑
    QPainterPath ph; ph.moveTo(0,0);  ph.lineTo(150,0); ph.lineTo(150,180); ph.lineTo(0,0);
    QPainterPath ph1; ph1.moveTo(0,0); ph1.lineTo(0,180);ph1.lineTo(150,0); ph1.lineTo(0,0);
//3、用於填充三角形的畫刷
    QBrush bs(QColor(0,255,0,100)); 	//QColor()第4個引數就是alpha通道的值
    QBrush bs1(QColor(255,0,0,255));
//4、建立影象:在pi1和pi2上使用路徑繪製兩個三角形
//注:使用alpha為0的顏色填充整個影象,可保證在繪製的三角形區域之外的alpha通道的值
//不會對合成產生影響。
pr.begin(&pi1);	pi1.fill(QColor(255,255,255,0));     pr.fillPath(ph,bs);   	pr.end();
pr.begin(&pi2);    	pi2.fill(QColor(255,255,255,0));    	pr.fillPath(ph1,bs1);   pr.end();
//在QWidget上繪製pi1(源)和pi2(目標)
pr.begin(this);	pr.drawImage(180,11,pi1);	pr.drawImage(400,11,pi2);	pr.end();
//5、開始合成影象,影象需要繪製在QImage上才能見到效果。
    pr.begin(&pi2);  				//這是目標影象,紅色
    //可在以下語句使用QPainter::CompositionMode的列舉值逐一驗證效果。
    		pr.setCompositionMode(QPainter::CompositionMode_SourceAtop);
    		pr.drawImage(0,0,pi1);  	//源影象,綠色
    pr.end();
//6、在QWidget上繪製合成後的影象pi2。
    pr.begin(this);    pr.drawImage(11,11,pi2);    pr.end();
//7、若使用以下語句把兩個QImage直接在QWidget上合成,可能會得不到想要的結果
  /*    	pr.begin(this);
    		pr.drawImage(11,11,pi2);
   		pr.setCompositionMode(QPainter::CompositionMode_SourceIn);
    		pr.drawImage(11,11,pi1);
    		pr.end();		*/
//8、以下語句可輸出兩影象合成後相交區域的顏色,輸出的顏色為ARGB(1, 0.607843, 0.392157, 0)
QColor c1= pi2.pixelColor(78,30);   qDebug()<<c1;	}

執行結果(見圖12-84)及說明
在這裡插入圖片描述

計算步驟如下:
1、計算源和目標影象的alpha值和預乘alpha顏色。
源影象的alpha值為:Sa = 100/255 ≈ 0.392,
源影象的預乘alpha顏色為:Sc = [0, 2550.392,0] = [0,100,0]
目標影象的alpha值為:Da = 255/255 = 1,
目標影象的預乘alpha顏色為:Dc = [255
1, 0,0] = [255,0,0]
2、本示例合成模式為QPainter::CompositionMode_SourceAtop,其計算公式為
[Da , ScDa + Dc(1 - Sa) ]
3、計算區域①的影象
區域①:Sa = 0.392; Da = 1; Dc = [255,0,0]; Sc = [0,100,0]
a1 = [Da, ScDa +Dc(1 - Sa)]
=[1, (0,100,0)1 + (255,0,0)(1 - 0.392) ] =[1, (0,100,0) + (155,0,0) ] = [1,(155,100,0)]
區域②: Da = 1; Dc = [255,0,0]; 因該區域不含源影象,所以Sa = 0; Sc = [0,0,0]
a2 = [Da, ScDa +Dc(1 - Sa)] = [1, (0,0,0)1 + (255,0,0)(1 - 0) ] =[1, (255,0,0) ]
區域③:Sa = 1; Sc = [0,100,0]; 該區域不含目標影象,所以Da = 0; Dc = [0,0,0];
a3 = [0, ScDa +Dc(1 - Sa)] = [0, XXX ] //因alpha=0,所以無論顏色為何值該區域都是透明的。
區域④的alpha也為0,所以是透明的。
其餘模式讀者可自行計算,需要注意的是,在顯示alpha不為0或1的影象時,顯示的色號並不一定是原色號,比如本示例的ARGB =[100,0,255,0];即alpha為100的純綠色,顯示在QWidget上的顏色為RGB = [146,246,146]。

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