QPainter类的CompositionMode各值含义

本文详细解读了QPainter::CompositionMode枚举在Qt中的图像混合原理,通过实例演示了SourceOver、DestinationOver、Source、Destination等模式下的源目标图像交互,以及它们在透明度和重叠区域的混合效果。
摘要由CSDN通过智能技术生成

QPainter类的QPainter::CompositionMode枚举用于说明源图像和目标图像怎样合成显示,一般用于图像的混合,其实在OPenGL中也有混合的技术,和QPainter类的QPainter::CompositionMode大同小异,思想类似。
Qt官方手册Assistant对QPainter::CompositionMode枚举的解释,没有真正在项目中实战用过QPainter::CompositionMode的童鞋来说,理解起来很费劲,网上的资料也是你抄我,我抄你的,真正弄懂、有价值的很少。今天我以示例和OPenGL中有关的阐述来讲解这几个枚举。
目标图像
目标图像是划定的绘制设备像素所在区域(如:窗体、图片或窗体图片的一部分区域)或上次绘制的图像。前者是初次绘制时,如:初次想在窗体区域上绘制,此时窗体区域什么都没有,则目标图像是指窗体、图片中程序划定的要绘制区域所在像素。后者指在窗体或图像上已经绘制过图像。
源图像
源图像是指最新、最近绘制的图像。如:起始绘制了a图像到窗体上(此时窗体所在像素形成的区域是目标图像,a图像是源图像),当a绘制完后,又在a的上面绘制了b图像,则b成为源图像,a成为目标图像。
总结:把将要画上去的图像称为“源图像”,把原来的图像称为“目标图像”。

  1. QPainter::CompositionMode_SourceOver
    该模式是默认模式,使用该模式时,源图像如果和目标图像有重叠,绘制时,则重叠部分是源图像在目标图像上面(源遮挡住目标),重叠部分源的RGBA值和重叠部分目标的RGBA值进行混合,没有重叠部分各自保留即都绘制出来。假定源和目标的混合因子为:
    Sr、Sg、Sb、Sa
    Dr、Dg、Db、Da
    其中Sr表示源的R分量的混合因子,Dr表示目标的R分量的混合因子,Sa表示源的alpha混合因子,Da表示目标的alpha混合因子,其它依次类似,相应地表示四元组RGBA的缩放因子。
    一般地,源图像和目标图像重叠部分按照下述公式进行颜色的混合:
    ( Rs* Sr + Rd*Dr , Gs*Sg + Gd*Dg, Bs*Sb + Bd*Db, As*Sa + Ad*Da ) ----公式1
    其中RGBA的下标s和d分别表示源的RGBA值和目标的RGBA值。将上述结果相乘相加后进行截取,以保证值在[0, 255]闭区间。如下代码:
#include <QtWidgets/QWidget>
#include "ui_compositionModeDemo.h"
#include<QPainter>
#include <QImage>
class compositionModeDemo : public QWidget
{
    Q_OBJECT

public:
    compositionModeDemo(QWidget *parent = Q_NULLPTR);

private :

    void paintEvent(QPaintEvent *event)override;
private slots:

	void srcAlphaValueChanged(int newAlphaValue);

	void destAlphaValueChanged(int newAlphaValue);
private:
    Ui::compositionModeDemoClass ui;
	QImage* firstImage = nullptr;
	QImage* secondImage = nullptr;
	int m_srcAlpha{255};
	int m_destAlpha{ 255 };
};

#include "compositionModeDemo.h"

compositionModeDemo::compositionModeDemo(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);

	connect(ui.srcAlphaSlider, SIGNAL(valueChanged(int)), this, SLOT(srcAlphaValueChanged(int)));
	connect(ui.destAlphaSlider, SIGNAL(valueChanged(int)), this, SLOT(destAlphaValueChanged(int)));
	firstImage = new QImage(500, 500, QImage::Format_ARGB32_Premultiplied);
	secondImage = new QImage(500, 500, QImage::Format_ARGB32_Premultiplied);
 
}

void compositionModeDemo::destAlphaValueChanged(int newAlphaValue)
{
	m_destAlpha = newAlphaValue;
	update();
}

void compositionModeDemo::srcAlphaValueChanged(int newAlphaValue)
{
	m_srcAlpha = newAlphaValue;
	update();
}

void compositionModeDemo::paintEvent(QPaintEvent *event)
{
	//绘制第一张图片
	QPainter painterFirst(firstImage);
	firstImage->fill(Qt::transparent);//设置透明
	painterFirst.setBrush(QColor(255, 0, 0, m_destAlpha));
	painterFirst.drawRect(50, 50, 100, 100);

	//绘制第二张图片
	QPainter painterSecond(secondImage);
	secondImage->fill(Qt::transparent);
	painterSecond.setBrush(QColor(0, 0, 255, m_srcAlpha));
	painterSecond.drawRect(100, 100, 100, 100);

	//设置图片的重叠模式
	painterFirst.setCompositionMode(QPainter::CompositionMode_SourceOver);
	//重叠图片
	painterFirst.drawImage(0, 0, *secondImage);

	//展示图片
	QPainter painter2(this);
	painter2.drawImage(0, 0, *firstImage);
 
}

第一次绘制的红色矩形为目标,第二次绘制的蓝色矩形为源,采用的模式为QPainter::CompositionMode_SourceOver,则效果如下:
SourceOver效果图

通过调节源alpha的滑块,改变其值,如下为源alpha为111时的效果:
在这里插入图片描述
如下为源apha为0即源完全透明的效果,即能透过源看到后面的目标:
在这里插入图片描述
当源的alpha为0时,公式1源和目标合成后的图像的alpha只有目标 Ad*Da 值了。然后保持源的alpha滑块在最大值255处不变,调节目标的alpha到中间,如下为目标的alpha为92的情况:
在这里插入图片描述
如下为目标的alpha为0的情况:
在这里插入图片描述
将上述cpp中第39行代码改为如下:

painterSecond.drawRect(200, 200, 100, 100);

以便目标和源不重叠,则输出如下,即源和目标都显示:
在这里插入图片描述
调节源和目标各自的alpha,都只对自己的透明度有影响。

可以看到:

  • 源图像如果和目标图像有重叠,绘制时,则重叠部分是源图像在目标图像上面(源遮挡住目标),当源的alpha为255时,目标被源完全遮挡。

  • 重叠部分RGBA值按公式1进行进行混合,混合之后得出的RGBA值为重叠部分的RGBA值。

  • 没有重叠部分各自保留即都绘制出来。
    2. QPainter::CompositionMode_DestinationOver
    将上述cpp代码中的第42行改为QPainter::CompositionMode_DestinationOver,则:

  • 源图像如果和目标图像有重叠,绘制时,则重叠部分是目标图像在源图像上面(目标遮挡住源),当目标的alpha为255时,源被目标完全遮挡。。

  • 重叠部分的源和重叠部分的目标按公式1进行进行混合,混合之后得出的RGBA值为重叠部分的RGBA值。

  • 没有重叠部分各自保留即都绘制出来。
    注意:和QPainter::CompositionMode_SourceOver的区别,唯一的区别是当源和目标有重叠时,目标盖住源,该模式是QPainter::CompositionMode_SourceOver的的逆操作。如下为源和目标的alpha都为255时的效果:
    在这里插入图片描述
    如下为源alpha为255,目标alpha为168效果:
    在这里插入图片描述
    如下为源alpha为255,目标alpha为0效果,即目标完全透明,能透过目标看到后面的源:
    在这里插入图片描述
    将上述cpp中第39行代码改为如下:

painterSecond.drawRect(200, 200, 100, 100);

以便目标和源不重叠,则输出如下,即源和目标都显示:
在这里插入图片描述
调节源和目标各自的alpha,都只对自己的透明度有影响。

3.
QPainter::CompositionMode_Source

将上面cpp代码的第42行改为QPainter::CompositionMode_Source,则:

  • 无论什么情况,都只显示源,不显示目标,目标就像不存在、没绘制一样。如下为源和目标的alpha都为255的效果:
    在这里插入图片描述
    如下为源的alpha为0,目标alpha为255的效果:
    在这里插入图片描述可以看到,即使源完全透明,依然看不到目标。

4.QPainter::CompositionMode_Destination
将上面cpp代码第42行换为:QPainter::CompositionMode_Destination,则:

  • 无论什么情况,都只显示目标,不显示源,源就像不存在、没绘制一样,该模式是QPainter::CompositionMode_Source逆操作。如下为源和目标的alpha都为255的效果:
    在这里插入图片描述
    如下为目标的alpha为0,源alpha为255的效果:
    在这里插入图片描述
    可以看到,即使目标完全透明,依然看不到源。

5.QPainter::CompositionMode_SourceIn
将上面cpp代码第42行换为:QPainter::CompositionMode_SourceIn,则:

  • 如果目标和源有重叠,则只显示重叠部分中的源区域,不显示重叠部分的目标区域。目标和源不重叠部分都剔除、都不显示,
  • 如果目标和源不重叠,则什么都不显示,不绘制,就像源和目标不存在一样。
  • 目标和源重叠部分图像的alpha受到目标alpha的影响而削减(具体计算公式暂不清楚,知道的可以留言给我)。

如下为源和目标的alpha值都为255的结果:
在这里插入图片描述
如下为源的alpha值为255, 目标alpha值为0的结果:

在这里插入图片描述
如下为源的alpha值为0, 目标alpha值为255的结果:

在这里插入图片描述
如下为源的alpha值为0, 目标alpha值为0的结果:
在这里插入图片描述

如下为源的alpha值为128, 目标alpha值为133的结果:
在这里插入图片描述
将上述cpp中第39行代码改为如下:

painterSecond.drawRect(200, 200, 100, 100);

以便目标和源不重叠,则输出如下,即什么都不显示:
在这里插入图片描述

6.QPainter::CompositionMode_DestinationIn
将上面cpp代码第42行换为:QPainter::CompositionMode_DestinationIn,则:

  • 只显示目标和源重叠部分中的目标部分,不显示重叠部分的源部分。目标和源不重叠部分都剔除、都不显示,
  • 如果目标和源不重叠,则什么都不显示,不绘制,就像源和目标不存在一样。
  • 目标和源重叠部分图像的alpha受到源的alpha的影响而削减(具体计算公式暂不清楚,知道的可以留言给我)。
  • 该模式是QPainter::CompositionMode_SourceIn的逆操作。
    如下为源和目标的alpha值都为255的结果:
    在这里插入图片描述
    如下为源的alpha值为255, 目标alpha值为0的结果:
    在这里插入图片描述
    如下为源的alpha值为0, 目标alpha值为255的结果:
    在这里插入图片描述
    如下为源的alpha值为0, 目标alpha值为0的结果:
    在这里插入图片描述
    如下为源的alpha值为128, 目标alpha值为116的结果:
    在这里插入图片描述
    将上述cpp中第39行代码改为如下:
painterSecond.drawRect(200, 200, 100, 100);

以便目标和源不重叠,则输出如下,即什么都不显示:
在这里插入图片描述

7.QPainter::CompositionMode_SourceOut
将上面cpp代码第42行换为:QPainter::CompositionMode_SourceOut,则:

  • 如果源和目标有重叠,则输出全部的源,但源和目标重叠部分默认完全透明,属于目标但不属于目标和源重叠的部分不输出。此时目标alpha对重叠部分的alpha有影响即目标透明度影响重叠区域透明度;当目标alpha值为255即完全不透明时,源alpha对重叠区域alpha无影响,即此时源的透明度不影响重叠区域的透明度;当目标alpha值不为255即部分透明时,源alpha对重叠区域的alpha有影响,即此时源的透明度影响重叠区域透明度。
  • 如果源和目标没有重叠,则输出全部源,不输出目标。此时目标透明度对源没有影响,这种情况下和QPainter::CompositionMode_Source相同。
    如下为源和目标有重叠,且源alpha值为255, 目标alpha值为255的结果,可以看到重叠区域完全透明,
    在这里插入图片描述
    保持源alpha为255不变,分别调小目标的alpha为154、0,可以看到重叠区域受到目标透明度的影响:
    在这里插入图片描述
    在这里插入图片描述
    保持目标alpha为255不变,分别调小源的alpha为103、38,可以看到重叠区域不受源透明度影响,此时源透明度只影响属于源自身但不属于重叠部分的源区域:

在这里插入图片描述
在这里插入图片描述
将目标alpha为135,源的alpha调为91、209,结果分别如下:
在这里插入图片描述
在这里插入图片描述
将上述cpp中第39行代码改为如下:

painterSecond.drawRect(200, 200, 100, 100);

即让源和目标不重叠,结果如下:
在这里插入图片描述
此时调节目标的alpha对源的透明度没任何影响。
8.QPainter::CompositionMode_DestinationOut
将上面cpp代码第42行换为:QPainter::CompositionMode_DestinationOut,则:

  • 如果源和目标有重叠,则输出全部目标,但源和目标重叠部分默认完全透明,属于源但不属于源和目标重叠的部分不输出。此时源alpha对重叠部分的alpha有影响即源透明度影响重叠区域透明度;当源alpha值为255即完全不透明时,目标alpha对重叠区域alpha无影响,即此时目标的透明度不影响重叠区域的透明度;当源alpha值不为255即部分透明时,目标alpha对重叠区域的alpha有影响,即此时目标透明度影响重叠区域透明度。
  • 如果源和目标没有重叠,则输出全部目标,不输出源。此时源透明度对目标没有影响,这种情况下和QPainter::CompositionMode_Destination相同。该模式是CompositionMode_SourceOut.模式的逆操作。
    结果就是把CompositionMode_SourceOut.蓝色截图换成红色就行。

9.QPainter::CompositionMode_SourceAtop
将上面cpp代码第42行换为:QPainter::CompositionMode_SourceAtop,则:

  • 输出全部目标。
  • 如果源和目标有重叠,则只输出源重叠部分,且源重叠部分在目标的上面即遮挡住目标。源和目标不重叠的部分不输出。
  • 如果源和目标没有重叠,则只输出全部的目标,不输出源。
    如下为目标的alpha为255,源alpha为255时的效果::
    在这里插入图片描述
    重叠部分中,源在目标上面(遮挡住目标),重叠部分像素值由源和目标混合得出,源的alpha受到目标像素的alpha而削减。
    如下为目标的alpha为0,源alpha为255时的效果:
    在这里插入图片描述
    如下为目标的alpha为255,源alpha为0时的效果:
    在这里插入图片描述
    如下为目标的alpha为128,源alpha为128时的效果:
    在这里插入图片描述
    将上述cpp代码中的39行改为如下,即源和目标不重叠
    painterSecond.drawRect(200,200, 100, 100);
    则效果如下:
    在这里插入图片描述
    可以看到只输出目标,没有输出源。

10.QPainter::CompositionMode_DestinationAtop
将上面cpp代码第42行换为:QPainter::CompositionMode_DestinationAtop,则:

  • 输出全部源。
  • 如果目标和源有重叠,则只输出目标重叠部分,且目标重叠部分在源上面即遮挡住源。目标和源不重叠的部分不输出。
  • 如果目标和源没有重叠,则只输出全部的源,不输出目标。
  • 该模式是QPainter::CompositionMode_SourceAtop的逆操作。

截图略。
11 QPainter::CompositionMode_Xor
源(其alpha值与目标alpha值的倒数成反比)与目标合并,该目标的alpha值与源alpha的倒数成反比。
截图略
12.QPainter::CompositionMode_Clear
源和目标无论在什么情况下都不显示,就像源、目标不存在一样。

总结:

  • Qt总共有35种组合模式,但是很多不常用,所以本文就没再描述说明,当用户需要研究时,可以将上面cpp代码42行换成你要的模式,进行研究。
  • 上面很多有关alpha减小、混合的内容,应该都有相应的公式的,但qt官方没有给出,这属于图形图像学的内容,OPengl中有一些,但和Qt的还是有些不同,如果读者知道这些混合方面的,alpha方面的公式,可以和我留言。

参考资料:
【1】:《 OpenGL编程指南(原书第7版)》 6.1节 混合。
【2】:QT多张图片的重叠显示

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值