反走样

今天继续前面的内容。既然已经进入2D绘图部分,那么就先继续研究一下有关QPainter的东西吧!
 
反走样是图形学中的重要概念,用以防止“锯齿”现象的出现。很多系统的绘图API里面都会内置了反走样的算法,不过默认一般都是关闭的,Qt也不例外。下面我们来看看代码。这段代码仅仅给出了paintEvent函数,相信你可以很轻松地替换掉前面章节中的相关代码。
  图片 1void
PaintedWidget::paintEvent(QPaintEvent *event)
图片 2{
图片 3        QPainter
painter(this);
图片 4        painter.setPen(QPen(Qt::black,
5, Qt::DashDotLine, Qt::RoundCap));
图片 5        painter.setBrush(Qt::yellow);
图片 6        painter.drawEllipse(50,
150, 200, 150);
图片 7
图片 8        painter.setRenderHint(QPainter::Antialiasing,
true);
图片 9        painter.setPen(QPen(Qt::black,
5, Qt::DashDotLine, Qt::RoundCap));
图片 10        painter.setBrush(Qt::yellow);
图片 11        painter.drawEllipse(300,
150, 200, 150);
图片 12}  
看看运行后的效果:  
图片 13  
左边的是没有使用反走样技术的,右边是使用了反走样技术的。二者的差别可以很容易的看出来。
  下面来看看相关的代码。为了尝试画笔的样式,这里故意使用了一个新的画笔:
 
图片 14painter.setPen(QPen(Qt::black,
5, Qt::DashDotLine, Qt::RoundCap));  
我们对照着API去看,第一个参数是画笔颜色,这里设置为黑色;第二个参数是画笔的粗细,这里是5px;第三个是画笔样式,我们使用了DashDotLine,正如同其名字所示,是一个短线和一个点相间的类型;第四个是RoundCap,也就是圆形笔帽。然后我们使用一个黄色的画刷填充,画了一个椭圆。
  后面的一个和前面的十分相似,唯一的区别是多了一句  
图片 15painter.setRenderHint(QPainter::Antialiasing,
true);  
,不过这句也很清楚,就是设置Antialiasing属性为true。如果你学过图形学就会知道,这个长长的单词就是“反走样”。经过这句设置,我们就打开了QPainter的反走样功能。还记得我们曾经说过,QPainter是一个状态机,因此,只要这里我们打开了它,之后所有的代码都会是反走样绘制的了。
 
看到这里你会发现,反走样的效果其实比不走样要好得多,那么,为什么不默认打开反走样呢?这是因为,反走样是一种比较复杂的算法,在一些对图像质量要求不高的应用中,是不需要进行反走样的。为了提高效率,一般的图形绘制系统,如Java2D、OpenGL之类都是默认不进行反走样的。
 
还有一个疑问,既然反走样比不反走样的图像质量高很多,不进行反走样的绘制还有什么作用呢?前面说的是一个方面,也就是,在一些对图像质量要求不高的环境下,或者说性能受限的环境下,比如嵌入式和手机环境,是不必须要进行反走样的。另外还有一点,在一些必须精确操作像素的应用中,也是不能进行反走样的。请看下面的图片:
  图片 16
上图是使用Photoshop的铅笔和画笔工具画的1像素的点在放大到3200%视图下截下来的。Photoshop里面的铅笔工具是不进行反走样,而画笔是要进行反走样的。在放大的情况下就会知道,有反走样的情况下是不能进行精确到1像素的操作的。因为反走样很难让你控制到1个像素。这不是Photoshop画笔工具的缺陷,而是反走样算法的问题。如果你想了解为什么这样,请查阅计算机图形学里面关于反走样的原理部分。

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);
}

看看运行后的结果:

图片 17

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

在这段代码中,我们创建了一个黑色 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 之类都是默认不进行反走样的。

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

图片 18

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

博客转载自:

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);
}

看看运行后的结果:

图片 19

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

在这段代码中,我们创建了一个黑色 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 之类都是默认不进行反走样的。

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

图片 20

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

概念:

本文出自 “豆子空间”
博客,请务必保留此出处

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

用离散量表示连续量引起的失真现象称之为走样(aliasing)

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

用于减少或消除这种效果的技术称为反走样(antialiasing)

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);
}

方法:

看看运行后的结果:

  • 提高分辨率:只能减轻而不能消除锯齿问题
  • 区域采样:每个象素是一个具有一定面积的小区域,将直线段看作具有一定宽度的狭长矩形。当直线段与象素有交时,求出两者相交区域的面积,然后根据相交区域面积的大小确定该象素的亮度值。
  • 加权区域取样:使相交区域对象素亮度的贡献依赖于该区域与象素中心的距离

图片 21

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

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

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

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

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

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

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

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

图片 22

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

相关文章