使用QImage进行高质量绘制(High-Quality Rendering with QImage)
2016-04-26 19:43
513 查看
分类: C++ GUI Programming with Qt 4 (59)
在进行绘图时,我们经常要面对速度和效率两者之间矛盾。在X11和MacOsX系统上,在QWidget和QPixmap绘图要依赖平台自身的绘图引擎。在X11上,与X server的通信很少,Qt只是发送绘图命令而不是真正的绘图数据。这种画法的不足是Qt要收到平台自身绘图引擎的限制。
在X11上,消除锯齿和支持分数坐标这些功能只有在Xserver上安装了XRender扩展才能实现;
在MacOsX平台,它自己的绘图引擎在绘制多段线时使用了和X11和Windows不同的算法,因此得到的结果会有稍许差别。
当准确性比效率重要时,我们可以先绘制在QImage上,然后把结果拷贝到屏幕。在QImage绘图使用Qt自己的绘图引擎,因此在所有平台上都能得到一致的结果。使用这个方法的额外工作是用QImage::Format_RGB32或者QImage::Format_ARGB32_Premutiplied参数创建QImage对象。
QImage::Format_ARGB32_Premutiplied和传统的ARGB32格式(0xaarrggbb)格式完全一致,不同在于红,绿,蓝三个通道值都“乘以”了alpha通道值。这样,0x00到0xFF的RGB颜色值范围变为0x00到alpha通道值。例如50%透明度的蓝色用ARGB格式表示为0x7F0000FF,在用Format_ARGB32_Premutiplied表示时为0x7F00007F,同理,75%透明度的黑绿色在ARGB格式中表示为0x3F008000,在Format_ARGB32_Premutiplied格式中表示为0x3F002000。
如果我们想用消除锯齿的方式绘制一个控件,并希望在没有XRender扩展的X11平台上也得到很好的结果,在原来需要依靠XRender的paintEvent()函数代码如下:
在上面的代码中,我们创建了一个Format_ARGB32_Premultiplied 格式的QIamge,大小和控件相同,创建一个QPainter绘制这个图像。QPainter::initFrom()调用用控件的设置初始化画笔,刷子和字体。然后想以前一样绘制。最后,创建控件的QPainter对象,把图片拷贝到控件上。
这种方式能够在不同的平台上得到效果一样的结果,但是绘制的文字除外,因为这取决于安装的字体。
Qt绘图引擎的另外一个尤为有用的功能是它能支持混和模式。在进行绘图时,原图像和目标图像能够组合起来。这个混和支持多种绘图操作:如笔,刷子,渐变色,图像等。
缺省的组合模式为QImage::CompositionMode_SourceOver ,即原象素(正在绘制的象素)和目标象素(已经存在的象素)混和,原象素的alpha分量定义为最终的透明度。图8.11显示了不同的模式下绘制的半透明蝴蝶的效果。
Figure 8.11. QPainter’s composition modes
函数QPainter::setCompositionMode()用来设置组合模式。下面的代码创建一个QImage,包含一个蝴蝶和一个棋盘格子的混和:
QImage resultImage = checkerPatternImage;
QPainter painter(&resultImage);
painter.setCompositionMode(QPainter::CompositionMode_Xor);
painter.drawImage(0, 0, butterflyImage);
一个需要注意的问题是,QImage::CompositionMode_Xor模式对alpha通道也同样适用。如果用白颜色0xFFFFFFFF同它自己混和,得到的将是透明色0x00000000,而不是0xFF000000。
在进行绘图时,我们经常要面对速度和效率两者之间矛盾。在X11和MacOsX系统上,在QWidget和QPixmap绘图要依赖平台自身的绘图引擎。在X11上,与X server的通信很少,Qt只是发送绘图命令而不是真正的绘图数据。这种画法的不足是Qt要收到平台自身绘图引擎的限制。
在X11上,消除锯齿和支持分数坐标这些功能只有在Xserver上安装了XRender扩展才能实现;
在MacOsX平台,它自己的绘图引擎在绘制多段线时使用了和X11和Windows不同的算法,因此得到的结果会有稍许差别。
当准确性比效率重要时,我们可以先绘制在QImage上,然后把结果拷贝到屏幕。在QImage绘图使用Qt自己的绘图引擎,因此在所有平台上都能得到一致的结果。使用这个方法的额外工作是用QImage::Format_RGB32或者QImage::Format_ARGB32_Premutiplied参数创建QImage对象。
QImage::Format_ARGB32_Premutiplied和传统的ARGB32格式(0xaarrggbb)格式完全一致,不同在于红,绿,蓝三个通道值都“乘以”了alpha通道值。这样,0x00到0xFF的RGB颜色值范围变为0x00到alpha通道值。例如50%透明度的蓝色用ARGB格式表示为0x7F0000FF,在用Format_ARGB32_Premutiplied表示时为0x7F00007F,同理,75%透明度的黑绿色在ARGB格式中表示为0x3F008000,在Format_ARGB32_Premutiplied格式中表示为0x3F002000。
如果我们想用消除锯齿的方式绘制一个控件,并希望在没有XRender扩展的X11平台上也得到很好的结果,在原来需要依靠XRender的paintEvent()函数代码如下:
void MyWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); draw(&painter); } 下面的代码为重写的paintEvent(),使用了Qt的平台独立的绘图引擎: void MyWidget::paintEvent(QPaintEvent *event) { QImage image(size(), QImage::Format_ARGB32_Premultiplied); QPainter imagePainter(&image); imagePainter.initFrom(this); imagePainter.setRenderHint(QPainter::Antialiasing, true); imagePainter.eraseRect(rect()); draw(&imagePainter); imagePainter.end(); QPainter widgetPainter(this); widgetPainter.drawImage(0, 0, image); }
在上面的代码中,我们创建了一个Format_ARGB32_Premultiplied 格式的QIamge,大小和控件相同,创建一个QPainter绘制这个图像。QPainter::initFrom()调用用控件的设置初始化画笔,刷子和字体。然后想以前一样绘制。最后,创建控件的QPainter对象,把图片拷贝到控件上。
这种方式能够在不同的平台上得到效果一样的结果,但是绘制的文字除外,因为这取决于安装的字体。
Qt绘图引擎的另外一个尤为有用的功能是它能支持混和模式。在进行绘图时,原图像和目标图像能够组合起来。这个混和支持多种绘图操作:如笔,刷子,渐变色,图像等。
缺省的组合模式为QImage::CompositionMode_SourceOver ,即原象素(正在绘制的象素)和目标象素(已经存在的象素)混和,原象素的alpha分量定义为最终的透明度。图8.11显示了不同的模式下绘制的半透明蝴蝶的效果。
Figure 8.11. QPainter’s composition modes
函数QPainter::setCompositionMode()用来设置组合模式。下面的代码创建一个QImage,包含一个蝴蝶和一个棋盘格子的混和:
QImage resultImage = checkerPatternImage;
QPainter painter(&resultImage);
painter.setCompositionMode(QPainter::CompositionMode_Xor);
painter.drawImage(0, 0, butterflyImage);
一个需要注意的问题是,QImage::CompositionMode_Xor模式对alpha通道也同样适用。如果用白颜色0xFFFFFFFF同它自己混和,得到的将是透明色0x00000000,而不是0xFF000000。
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- Seafile Server本地权限提升漏洞(CVE-2014-5443)
- 从USB安装Ubuntu Server 10.04.3 图文详解
- QT学习 第一章:基本对话框
- 如何写好 C main 函数
- 使用Shiboken为C++和Qt库创建Python绑定
- 使用zabbix监控Nginx活动状态--Part1
- 高效访问Internet-启用ISA Server的缓存
- Qt 5.6更新至RC版,最终版本近在咫尺
- windows server域用户提升到本地更高权限组中的方法
- 完美解决SQL Server 安装问题:以前的某个程序安装已在安装计算机上创建挂起的文件操作
- IIS 错误 Server Application Error 详细解决方法
- 在WINXP系统上安装SQL Server企业版的方法
- SQL Server 存储过程的分页
- SQL Server复制需要有实际的服务器名称才能连接到服务器
- SQL Server 2000向SQL Server 2008 R2推送数据图文教程
- SQL server 表操作介绍
- SQL Server 2000 注入防护大全(二)
- SQL Server 2000 注入防护大全(一)
- 怎样把Windows server 2003转换成工作站系统