1. 程式人生 > >Qt 學習之路 2(26):反走樣

Qt 學習之路 2(26):反走樣

我們在光柵圖形顯示器上繪製非水平、非垂直的直線或多邊形邊界時,或多或少會呈現鋸齒狀外觀。這是因為直線和多邊形的邊界是連續的,而光柵則是由離散的點組成。在光柵顯示裝置上表現直線、多邊形等,必須在離散位置取樣。由於取樣不充分重建後造成的資訊失真,就叫走樣;用於減少或消除這種效果的技術,就稱為反走樣。

反走樣是圖形學中的重要概念,用以防止通常所說的“鋸齒”現象的出現。很多系統的繪圖 API 裡面都內建了有關反走樣的演算法,不過由於效能問題,預設一般是關閉的,Qt 也不例外。下面我們來看看程式碼:

123456789101112voidpaintEvent(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);}

看看執行後的結果:

Qt 反走樣示例

注意看左側橢圓與右側橢圓在邊界處的區別。左側沒有使用反鋸齒,明細顯示出鋸齒的樣子;右側則增加了反鋸齒程式碼。

在這段程式碼中,我們建立了一個黑色 5 畫素寬的畫筆,使用了點線的樣式,圓形筆帽:

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

然後我們使用一個黃色的畫刷填充,繪製一個橢圓。

第二個橢圓的繪製與第一個十分相似,唯一的區別是多了一句

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

顯然,我們通過這條語句,將Antialiasing屬性(也就是反走樣)設定為 true。經過這句設定,我們就打開了QPainter的反走樣功能。還記得我們曾經說過,QPainter是一個狀態機,因此,只要這裡我們打開了它,之後所有的程式碼都會是反走樣繪製的了。由於反走樣需要比較複雜的演算法,在一些對影象質量要求不是很高的應用中,是不需要進行反走樣的。為了提高效率,一般的圖形繪製系統,如 Java2D、OpenGL 之類都是預設不進行反走樣的。

雖然反走樣比不反走樣的影象質量高很多,但是,沒有反走樣的圖形繪製還是有很大用處的。首先,就像前面說的一樣,在一些對影象質量要求不高的環境下,或者說效能受限的環境下,比如嵌入式和手機環境,一般是不進行反走樣的。另外,在一些必須精確操作畫素的應用中,也是不能進行反走樣的。這是由於反走樣技術本身的限制的。請看下面的圖片:

Photoshop 走樣與反走樣對比

這是使用 Photoshop 的鉛筆和畫筆工具繪製的 1 畫素的點,放大 3200% 的檢視。在一定程度上,我們可以認為,Photoshop 的鉛筆工具是不進行反走樣,而畫筆是要進行反走樣的。在放大的情況下就會知道,有反走樣的情況下是不能進行精確到 1 畫素的操作的。因為反走樣很難讓你控制到 1 個畫素。這不是 Photoshop 畫筆工具的缺陷,而是反走樣演算法的問題。反走樣之所以看起來比較模糊,就是因為它需要以一種近似色來替換原始的畫素色,這樣一來就會顯得模糊而圓滑。