Qt 学习之路 2(26):反走样

豆子 2012年11月12日 Qt 学习之路 2 9条评论

我们在光栅图形显示器上绘制非水平、非垂直的直线或多边形边界时,或多或少会呈现锯齿状外观。这是因为直线和多边形的边界是连续的,而光栅则是由离散的点组成。在光栅显示设备上表现直线、多边形等,必须在离散位置采样。由于采样不充分重建后造成的信息失真,就叫走样;用于减少或消除这种效果的技术,就称为反走样。

反走样是图形学中的重要概念,用以防止通常所说的“锯齿”现象的出现。很多系统的绘图 API 里面都内置了有关反走样的算法,不过由于性能问题,默认一般是关闭的,Qt 也不例外。下面我们来看看代码:

 
 
void paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setPen(QPen(Qt::black, 5, Qt::DashDotLine, Qt::RoundCap));
painter.setBrush(Qt::yellow);
painter.drawEllipse(50, 150, 200, 150);

painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(QPen(Qt::black, 5, Qt::DashDotLine, Qt::RoundCap));
painter.setBrush(Qt::yellow);
painter.drawEllipse(300, 150, 200, 150);
}

1
2
3
4
5
6
7
8
9
10
11
12
void paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setPen(QPen(Qt::black, 5, Qt::DashDotLine, Qt::RoundCap));
    painter.setBrush(Qt::yellow);
    painter.drawEllipse(50, 150, 200, 150);
 
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setPen(QPen(Qt::black, 5, Qt::DashDotLine, Qt::RoundCap));
    painter.setBrush(Qt::yellow);
    painter.drawEllipse(300, 150, 200, 150);
}

看看运行后的结果:

注意看左侧椭圆与右侧椭圆在边界处的区别。左侧没有使用反锯齿,明细显示出锯齿的样子;右侧则增加了反锯齿代码。

在这段代码中,我们创建了一个黑色 5 像素宽的画笔,使用了点线的样式,圆形笔帽:

 
 
painter.setPen(QPen(Qt::black, 5, Qt::DashDotLine, Qt::RoundCap));
1
painter.setPen(QPen(Qt::black, 5, Qt::DashDotLine, Qt::RoundCap));

然后我们使用一个黄色的画刷填充,绘制一个椭圆。

第二个椭圆的绘制与第一个十分相似,唯一的区别是多了一句

 
 
painter.setRenderHint(QPainter::Antialiasing, true);
1
painter.setRenderHint(QPainter::Antialiasing, true);

显然,我们通过这条语句,将Antialiasing属性(也就是反走样)设置为 true。经过这句设置,我们就打开了QPainter的反走样功能。还记得我们曾经说过,QPainter是一个状态机,因此,只要这里我们打开了它,之后所有的代码都会是反走样绘制的了。由于反走样需要比较复杂的算法,在一些对图像质量要求不是很高的应用中,是不需要进行反走样的。为了提高效率,一般的图形绘制系统,如 Java2D、OpenGL 之类都是默认不进行反走样的。

虽然反走样比不反走样的图像质量高很多,但是,没有反走样的图形绘制还是有很大用处的。首先,就像前面说的一样,在一些对图像质量要求不高的环境下,或者说性能受限的环境下,比如嵌入式和手机环境,一般是不进行反走样的。另外,在一些必须精确操作像素的应用中,也是不能进行反走样的。这是由于反走样技术本身的限制的。请看下面的图片:

这是使用 Photoshop 的铅笔和画笔工具绘制的 1 像素的点,放大 3200% 的视图。在一定程度上,我们可以认为,Photoshop 的铅笔工具是不进行反走样,而画笔是要进行反走样的。在放大的情况下就会知道,有反走样的情况下是不能进行精确到 1 像素的操作的。因为反走样很难让你控制到 1 个像素。这不是 Photoshop 画笔工具的缺陷,而是反走样算法的问题。反走样之所以看起来比较模糊,就是因为它需要以一种近似色来替换原始的像素色,这样一来就会显得模糊而圆滑。

Qt 学习之路 2(26):反走样的更多相关文章

  1. Qt 学习之路 2(57):可视化显示数据库数据

    Qt 学习之路 2(57):可视化显示数据库数据(skip) 豆子 2013年6月26日 Qt 学习之路 2 26条评论 前面我们用了两个章节介绍了 Qt 提供的两种操作数据库的方法.显然,使用QSq ...

  2. Qt 学习之路 2(28):坐标系统

    Qt 学习之路 2(28):坐标系统 豆子 2012年11月25日 Qt 学习之路 2 59条评论 在经历过实际操作,以及前面一节中我们见到的那个translate()函数之后,我们可以详细了解下 Q ...

  3. Qt 学习之路 2(27):渐变

    Qt 学习之路 2(27):渐变 豆子 2012年11月20日 Qt 学习之路 2 17条评论 渐变是绘图中很常见的一种功能,简单来说就是可以把几种颜色混合在一起,让它们能够自然地过渡,而不是一下子变 ...

  4. 《Qt 学习之路 2》目录

    <Qt 学习之路 2>目录 <Qt 学习之路 2>目录  豆子  2012年8月23日  Qt 学习之路 2  177条评论 <Qt 学习之路 2>目录 序 Qt ...

  5. Qt 学习之路 2(73):Qt 线程相关类

    Home / Qt 学习之路 2 / Qt 学习之路 2(73):Qt 线程相关类 Qt 学习之路 2(73):Qt 线程相关类  豆子  2013年11月26日  Qt 学习之路 2  7条评论 希 ...

  6. Qt 学习之路 2(71):线程简介

    Qt 学习之路 2(71):线程简介 豆子 2013年11月18日 Qt 学习之路 2 30条评论 前面我们讨论了有关进程以及进程间通讯的相关问题,现在我们开始讨论线程.事实上,现代的程序中,使用线程 ...

  7. Qt 学习之路 2(70):进程间通信

    Qt 学习之路 2(70):进程间通信 豆子 2013年11月12日 Qt 学习之路 2 16条评论 上一章我们了解了有关进程的基本知识.我们将进程理解为相互独立的正在运行的程序.由于二者是相互独立的 ...

  8. Qt 学习之路 2(67):访问网络(3)

    Qt 学习之路 2(67):访问网络(3) 豆子 2013年11月5日 Qt 学习之路 2 16条评论 上一章我们了解了如何使用我们设计的NetWorker类实现我们所需要的网络操作.本章我们将继续完 ...

  9. Qt 学习之路 2(66):访问网络(2)

    Home / Qt 学习之路 2 / Qt 学习之路 2(66):访问网络(2) Qt 学习之路 2(66):访问网络(2)  豆子  2013年10月31日  Qt 学习之路 2  27条评论 上一 ...

随机推荐

  1. jdbcTemplate学习(二)

    前面讲了增加.删除.更新操作,这节讲一下查询. 查询操作: (一)查询一个值(不需要注入参数) queryForObject(String sql, Class<T> requiredTy ...

  2. 问题:sqlserver有没有类似Oracle的LISTAGG;结果: 灵活运用 SQL SERVER FOR XML PATH

    灵活运用 SQL SERVER FOR XML PATH FOR XML PATH 有的人可能知道有的人可能不知道,其实它就是将查询结果集以XML形式展现,有了它我们可以简化我们的查询语句实现一些以前 ...

  3. Generalized Low Rank Approximation of Matrices

    Generalized Low Rank Approximations of Matrices JIEPING YE*jieping@cs.umn.edu Department of Computer ...

  4. ActionBarActivity的使用注意事项

    1.调用getActionbar()方法返回为空的解决方法 此activity是设计来支持低版本系统用actionbar的,低版本没有getActionbar() 需要使用 getSupportAct ...

  5. 解决列表中增加字典覆盖之前相同key的字典

    dic = {} lst = [] # 先声明一个字典和一个列表 dic['name'] = "chenrun" lst.append(dic) print(lst) dic[&q ...

  6. [Elasticsearch2.x] 多字段搜索 (三) - multi_match查询和多数字段 <译>

    multi_match查询 multi_match查询提供了一个简便的方法用来对多个字段执行相同的查询. NOTE 存在几种类型的multi_match查询,其中的3种正好和在“了解你的数据”一节中提 ...

  7. Mybatis的批处理以及执行Update返回行数为负数

    项目中用到了批量更新. 在开发当中,可能经常会遇到批量处理这种情况,一般都再在java层面进行, 其本质是节省数据库连接打开关闭的的次数,占用更少的运行内存. 下面先记一下批处理映射吧: mybati ...

  8. c++ 与 lua 简单交互参数介绍

    原文http://blog.csdn.net/johnice/article/details/5517431 一.第一个例子 Hello World ! #include <stdio.h> ...

  9. Tensorflow手写数字识别训练(梯度下降法)

    # coding: utf-8 import tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_data #p ...

  10. Java3D-对象基本变换

    一个球体与三个圆柱体形成一个组合体,在该组合体中,球体的透明度属性是由全透明到不透明之间变换,而且包括:旋转.平移等变换. package com.vfsd.test0621; import java ...