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]。

本文作者:黄邦勇帅(原名:黄勇)

猜你喜欢

转载自blog.csdn.net/hyongilfmmm/article/details/83141582
今日推荐