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_OBJECTpublic: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,则效果如下:

通过调节源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多张图片的重叠显示

QPainter类的CompositionMode各值含义相关推荐

  1. Uml 类图 stereotype的值含义,该怎么解决

    2019独角兽企业重金招聘Python工程师标准>>> Uml 类图 stereotype的值含义 用rose画类图的时候,里面的stereotype 选项的entity和domai ...

  2. WIN32 API GetLastError()返回值含义列表

    转载自:http://blog.csdn.net/ice197983/article/details/614451 返回值 含义 0 操作成功完成. 1 功能错误. 2 系统找不到指定的文件. 3 系 ...

  3. c#图像处理入门(-bitmap类和图像像素值获取方法)

    c#图像处理入门 -bitmap类和图像像素值获取方法 一.Bitmap类 Bitmap对象封装了GDI+中的一个位图,此位图由图形图像及其属性的像素数据组成.因此Bitmap是用于处理由像素数据定义 ...

  4. ShellExecute函数返回值含义

    ShellExecute函数返回值含义 如果函数执行成功,那么返回值就是该运行的程序的实例句柄(例如你打开一个txt文件,如果成功了,返回的是关联到txt文件类型的应用程序的句柄).或者是一个DDE服 ...

  5. DataReader类访问字段的值

    DataReader类访问字段的值 有2种方法.第一种是Item属性,此属性返回字段索引或者字段名字对应的字段的值.第二种是Get方法,此方法返回有字段索引指定的字段的值.有点难以理解,不是吗?不要紧 ...

  6. 在jsp中调用常量类中的属性值

    在jsp中想要调用常量类中的属性值方法: 1.  在jsp中导入此常量类   <%@page import="com.Zyp.constant.FlagConstant"%& ...

  7. 枚举类中获取枚举值的几种方法

    在开发的过程中我们经常会定义枚举类,枚举类中获取枚举值的方式也有很多种,下面我们就探究一下大家常用的几种方式: 枚举类 public enum TestEnum {ONE(1,"one&qu ...

  8. 封装实现电子宠物系统的企鹅类正确输入健康值和亲密度

    作业: 1.需求说明 使用封装实现电子宠物系统的企鹅类正确输入健康值和亲密度 保证健康值的有效性(0-100),否则取默认值60 保证亲密度的有效性(0-100),否则取默认值60 咱们先来一道题 上 ...

  9. lab值意义_色差仪lab值含义是什么?

    在1931年,国际标准照明委员会(CIE)建立了一个系列,可表示可见光谱的颜色空间标准.比较基本的CIE色空间标准是CIE XYZ,它建立在标准观察者的视觉能力基础上,反映了标准人眼可见颜色的范围.基 ...

最新文章

  1. P1014Cantor表(找规律)
  2. dubbo中的Filter顺序是如何确定的
  3. android 高斯模糊 c,c-如何在不使用任何内置高斯函数的情况下对图像进行高斯模糊处理?...
  4. php环形链表,PHP环形链表实现方法示例
  5. php统一处理异常,PHP异常处理
  6. scala 协变和逆变_Scala方差:协变,不变和逆变
  7. lamp一键配置 --转自秋水
  8. 智慧农业:农业物联网实施方案
  9. 百度 php 图片文字识别,使用百度接口实现图片识别文字
  10. 浅谈老妈的QQ号被盗之后
  11. Chinese Std GBT7714-2015.ens EndNote 样式文件
  12. html + js实现马赛克画板
  13. vue-router 报NavigationDuplicated: Navigating to current location问题解决
  14. 关于参加“兆易创新杯”第十三届中国研究生电子设计竞赛,国赛二等奖的总结(fishing_5)
  15. Vue-2-计算属性、侦听器、过滤器、样式绑定
  16. 如何设计一个抢红包系统(商品秒杀同理)
  17. 我们一起学一学渗透测试——黑客应该掌握的Windows基础
  18. (附源码)计算机毕业设计ssm高校智慧党建党务管理系统
  19. python三大_Python之三大器
  20. java毕业生设计校园兼职招聘系统计算机源码+系统+mysql+调试部署+lw

热门文章

  1. c++ opencv添加logo_OpenCV-Python 图像平滑 | 十六
  2. python代理池_用Python搭建一个简单的代理池
  3. 眉骨高者为大贵之相_什么样才算富贵相?曾国藩的识人秘诀(组图)
  4. 刷机android8.1 错误7,[Android]错误: -source 1.7 中不支持 lambda 表达式 (请使用 -source 8 或更高版本以启用 lambda 表达式)...
  5. java request payload_java 模拟 post request payload
  6. 设置电子围栏 高德地图_地理围栏-辅助功能-开发指南-Android 定位SDK | 高德地图API...
  7. opcua客户端实现断线重连_PLCopen amp; OPC UA信息模型
  8. Scrapy爬虫基本使用
  9. python学习第八讲,python中的数据类型,列表,元祖,字典,之字典使用与介绍
  10. Qt数据库sqlite