一種簡單的文字描邊方法


 

© 版權所有 conmajia 2012

在色彩豐富的圖片上顯示文字的時候,由於背景色變化的關系,文字往往不能清晰呈現。就像很多早期電影使用純白色字幕,在藍天白雲的畫面下常常看不清楚字幕。這時候,就需要文字描邊這種能夠突出顯示文字的效果了,就像這樣。

(動畫截圖 by Wong Shao Voon)

怎樣實現這樣的效果呢?下面我粗略介紹下目前常見的幾種方法。最后介紹我構思的一種簡單而實用的實現方法。

一般方法

第一種思路:文字即圖片

  1. 將TextBlock 轉換為WriteableBitmap
  2. 對WriteableBitmap 的Pixels 進行循環,判斷每一個像素點的值最終達到描邊的效果。

參考《Silverlight字體描邊

這種思路將文字轉為圖片,根據判斷圖片上每個像素點,效率低下,最終效果簡單,如下圖所示。

第二種思路:像素着色器

該方法基本思路為:假定只會對TextBlock應用像素着色器,那么TextBlock是一個矩形,文字所在像素的 alpha分量必定大於0,否則必定是透明像素。判斷如果當前像素的上,下,左,右任意一個像素不透明,則說明本像素需要被描邊,否則就輸出文字顏色。由於需要知道相鄰像素,所以還需要傳入TextBlock的ActualWidth和ActualHeight。 這樣, 當前位置的 x+ 1/width 就是相鄰像素的坐標,就可以用tex2D函數來提取它的顏色值。還需要輸入描邊的顏色,還有文字的顏色。

參考《SILVERLIGHT像素着色器編寫簡明指南 附送文字描邊效果

仍然是一個「大炮打蚊子」的思路,將文字進行逐像素的處理。和思路1唯一的區別在於使用了像素着色器,讓把部分工作交給GPU來完成,「看起來」很高效很快速。但是如果禁用了硬件加速就變成和1一樣了。下面是該方法的效果截圖。

第三種思路:GDI+路徑繪圖

這種方法不再是逐像素處理了。其基本思路是將文字字符串添加到GDI+的繪圖路徑中(GraphicsPath),然后再DrawPath()。利用不同的筆刷,這種方法可以「畫」出非常華麗的描邊效果,就像這樣。

這是擴展性最好的方法。由於利用了GDI+的高級特性,所以可以利用不同的筆刷如紋理、漸變,以及多次繪圖等方法做出非常精美的描邊、陰影效果。唯一的遺憾就是代碼量較大(比前面2種要少很多了)。

參考文章《C# 水印圖片+文字描邊+發光文字。看示圖及Demo

關於該方法的高級效果設計,參考《Outline Text》一文(Code Project「Best C++/MFC article of Sep 2009」比賽獲獎文章)。

 

簡易方法

看了前面幾種設計思路后,你有沒有一頭霧水的感覺?或者眼花繚亂的感覺?難道我們只有這樣實現嗎?需要「描邊」文字,就一定要「描」嗎?

其實完全沒有必要。曾經我在山寨Safari時,介紹過一種簡單的通過重復繪制文字實現高光效果的方法。

如下圖所示。當底層文字和頂層文字相差1px時,就會呈現出不同的陰影/高光效果。如果把這個思路拓展下,把上、下、左、右四個方向的偏差結合到一起,就會像下圖最后顯示的效果一樣,得到了「描邊」文字的效果。

接下來在GDI+里面實現它。 

 1     // Code by Conmajia
 2     // txtPoint是繪制文字的定位點
 3     txtPoint.Offset(-1, 0);  // 繪制左背景文字
 4     e.Graphics.DrawString(this.Text, this.Font, backBrush, txtPoint);
 5     txtPoint.Offset(2, 0);  // 繪制右背景文字
 6     e.Graphics.DrawString(this.Text, this.Font, backBrush, txtPoint);
 7     txtPoint.Offset(-1, -1);  // 繪制下背景文字
 8     e.Graphics.DrawString(this.Text, this.Font, backBrush, txtPoint);
 9     txtPoint.Offset(0, 2);  // 繪制上背景文字
10     e.Graphics.DrawString(this.Text, this.Font, backBrush, txtPoint);
11     txtPoint.Offset(0, -1);  // 定位點歸位
12 
13     // 繪制前景文字
14     e.Graphics.DrawString(this.Text, this.Font, foreBrush, txtPoint);

 

下面請欣賞效果

 

結語

遇到問題,不一定需要完全跟着問題走。就像這次,需要「描邊」,但誰說的,非得要「描」邊呢?你要的只是效果,而不是過程,所以要跳出問題表象的禁錮,就能獲得更加寬廣的視野。

© 版權所有 conmajia 2012

(全文完)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM