#(26):反走樣
我們在光柵圖形顯示器上繪制非水平、非垂直的直線或多邊形邊界時,或多或少會呈現鋸齒狀外觀。這是因為直線和多邊形的邊界是連續的,而光柵則是由離散的點組成。在光柵顯示設備上表現直線、多邊形等,必須在離散位置采樣。由于采樣不充分重建后造成的信息失真,就叫走樣;用于減少或消除這種效果的技術,就稱為反走樣。
反走樣是圖形學中的重要概念,用以防止通常所說的“鋸齒”現象的出現。很多系統的繪圖 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);
}
~~~
看看運行后的結果:
[](http://files.devbean.net/images/2012/11/qt-antialiasing.png)
注意看左側橢圓與右側橢圓在邊界處的區別。左側沒有使用反鋸齒,明細顯示出鋸齒的樣子;右側則增加了反鋸齒代碼。
在這段代碼中,我們創建了一個黑色 5 像素寬的畫筆,使用了點線的樣式,圓形筆帽:
~~~
painter.setPen(QPen(Qt::black, 5, Qt::DashDotLine, Qt::RoundCap));
~~~
然后我們使用一個黃色的畫刷填充,繪制一個橢圓。
第二個橢圓的繪制與第一個十分相似,唯一的區別是多了一句
~~~
painter.setRenderHint(QPainter::Antialiasing, true);
~~~
顯然,我們通過這條語句,將`Antialiasing`屬性(也就是反走樣)設置為 true。經過這句設置,我們就打開了`QPainter`的反走樣功能。還記得我們曾經說過,`QPainter`是一個狀態機,因此,只要這里我們打開了它,之后所有的代碼都會是反走樣繪制的了。由于反走樣需要比較復雜的算法,在一些對圖像質量要求不是很高的應用中,是不需要進行反走樣的。為了提高效率,一般的圖形繪制系統,如 Java2D、OpenGL 之類都是默認不進行反走樣的。
雖然反走樣比不反走樣的圖像質量高很多,但是,沒有反走樣的圖形繪制還是有很大用處的。首先,就像前面說的一樣,在一些對圖像質量要求不高的環境下,或者說性能受限的環境下,比如嵌入式和手機環境,一般是不進行反走樣的。另外,在一些必須精確操作像素的應用中,也是不能進行反走樣的。這是由于反走樣技術本身的限制的。請看下面的圖片:
[](http://files.devbean.net/images/2012/11/ps-points.png)
這是使用 Photoshop 的鉛筆和畫筆工具繪制的 1 像素的點,放大 3200% 的視圖。在一定程度上,我們可以認為,Photoshop 的鉛筆工具是不進行反走樣,而畫筆是要進行反走樣的。在放大的情況下就會知道,有反走樣的情況下是不能進行精確到 1 像素的操作的。因為反走樣很難讓你控制到 1 個像素。這不是 Photoshop 畫筆工具的缺陷,而是反走樣算法的問題。反走樣之所以看起來比較模糊,就是因為它需要以一種近似色來替換原始的像素色,這樣一來就會顯得模糊而圓滑。
- (1)序
- (2)Qt 簡介
- (3)Hello, world!
- (4)信號槽
- (5)自定義信號槽
- (6)Qt 模塊簡介
- (7)MainWindow 簡介
- (8)添加動作
- (9)資源文件
- (10)對象模型
- (11)布局管理器
- (12)菜單欄、工具欄和狀態欄
- (13)對話框簡介
- (14)對話框數據傳遞
- (15)標準對話框 QMessageBox
- (16)深入 Qt5 信號槽新語法
- (17)文件對話框
- (18)事件
- (19)事件的接受與忽略
- (21)事件過濾器
- (22)事件總結
- (23)自定義事件
- (24)Qt 繪制系統簡介
- (25)畫刷和畫筆
- (26)反走樣
- (27)漸變
- (28)坐標系統
- (29)繪制設備
- (30)Graphics View Framework
- (31)貪吃蛇游戲(1)
- (32)貪吃蛇游戲(2)
- (33)貪吃蛇游戲(3)
- (34)貪吃蛇游戲(4)
- (35)文件
- (36)二進制文件讀寫
- (37)文本文件讀寫
- (38)存儲容器
- (39)遍歷容器
- (40)隱式數據共享
- (41)model/view 架構
- (42)QListWidget、QTreeWidget 和 QTableWidget
- (43)QStringListModel
- (44)QFileSystemModel
- (45)模型
- (46)視圖和委托
- (47)視圖選擇
- (48)QSortFilterProxyModel
- (49)自定義只讀模型
- (50)自定義可編輯模型
- (51)布爾表達式樹模型
- (52)使用拖放
- (53)自定義拖放數據
- (54)剪貼板
- (55)數據庫操作
- (56)使用模型操作數據庫
- (57)可視化顯示數據庫數據
- (58)編輯數據庫外鍵
- (59)使用流處理 XML
- (60)使用 DOM 處理 XML
- (61)使用 SAX 處理 XML
- (62)保存 XML
- (63)使用 QJson 處理 JSON
- (64)使用 QJsonDocument 處理 JSON
- (65)訪問網絡(1)
- (66)訪問網絡(2)
- (67)訪問網絡(3)
- (68)訪問網絡(4)
- (69)進程
- (70)進程間通信
- (71)線程簡介
- (72)線程和事件循環
- (73)Qt 線程相關類
- (74)線程和 QObject
- (75)線程總結
- (76)QML 和 QtQuick 2
- (77)QML 語法
- (78)QML 基本元素
- (79)QML 組件
- (80)定位器
- (81)元素布局
- (82)輸入元素
- (83)Qt Quick Controls
- (84)Repeater
- (85)動態視圖
- (86)視圖代理
- (87)模型-視圖高級技術
- (88)Canvas
- (89)Canvas(續)