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 = [2551, 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]。
本文作者:黃邦勇帥(原名:黃勇)