本節書摘來自華章計算機《java數字圖像處理:程式設計技巧與應用實踐》一書中的第1章,第1.1節,作者 賈志剛,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。
在開始本書内容之前,筆者假設你已經有了面向對象語言程式設計的基本概念,了解java語言的基本文法與特征,原因在于本書的所有源代碼都是基于java語言實作的,而且是基于java開發環境運作與示範所有圖像處理算法的。本書第1章到第3章是為了幫助讀者了解與掌握java 圖形與gui程式設計的基本知識與概念而寫的。本章主要介紹java gui程式設計中基本的圖形知識,針對gui程式設計,java語言提供了兩套幾乎并行的api,分别是swing與awt。早期的java gui程式設計中主要使用awt的相關元件,但是awt的功能并不是十分強大,而且嚴重依賴本地接口。于是在java 1.3及後續版本中引入了swing工具實作gui程式設計,swing中的元件大多數都是基于純java語言實作的,而不是通過本地元件實作的,是以它們是輕量級的gui元件,同時swing對圖形與圖像的支援操作也有很大的提高與增強。如何區分awt元件與swing元件?一個簡單而且相當直覺的方法是看class的名稱,swing的元件大多數帶有大寫的字首字母j。
graphics作為java的圖形引擎繪制接口,幾何形狀、文字、圖像的繪制都必須通過它完成,此外,graphics還支援繪制過程的控制,可以設定畫筆顔色、紋理、顔色填充方法、合成與裁剪路徑及各種stroke與fill的屬性等。使用者程式通常都是通過graphics來通路繪制引擎,進而實作各種圖形與圖像繪制的,是以可以說graphics是swing中最重要的接口對象。好吧,下面讓我們一起揭開graphics的神秘面紗。
簡單地說graphics是java圖形繪制引擎的通路接口,隻有通過它才可以通路到java gui的圖形繪制引擎,實作圖形的繪制與繪制過程的控制。
grahpics的功能大緻可以分為兩類,第一類是通過draw或fill方法來實作各種圖形的繪制與填充,第二類是設定各種繪制屬性,最簡單的包括設定字型、顔色、填充方法等。此外,在java 2d中graphics還可以被轉型為graphics2d對象,進而提供更高精度的圖形繪制,設定更多繪制屬性來控制繪制過程。
在java swing中正确擷取graphics對象的方法有兩種。
第一種是從bufferedimage對象執行個體中擷取,其代碼如下:

第二種方法是通過重載swing元件的paintcomponent(graphics g)或paint(graphics g)方法來實作,個人推薦采用重載paintcomponent(graphics g)方法來實作,因為重載paint(graphics g)是awt時代遺留下來的産物,是一個重量級繪制重載,通常用于canvas對象的重載繪制。
除了以上兩種推薦的做法以外,筆者經常還看到直接通過swing元件的getgraphics去擷取graphics對象的,這樣做的壞處是一旦該元件沒有被顯示,所對應的graphics對象将傳回null。而且這種做法常會導緻一些意想不到的錯誤,是以應該盡量避免這麼做。下面提供一個這麼做導緻錯誤的代碼示例,如下:
在擷取了java圖形裝置對象graphics之後,就可以調用它的繪制方法來實作圖形繪制與填充了。簡單的示例代碼如下:
上述代碼将會繪制一個藍色邊框的矩形,其中“10,10”表示矩形開始繪制的左上角位置,“50,50”分别代表矩形的長度與高度。
在使用完graphics對象以後,請記得一定要銷毀圖形裝置對象,可通過調用方法dispose()來釋放圖形繪制時所使用的任何資源。特别是當圖形裝置是從你自己的buffered-image對象中建立出來的時候,記得使用完以後一定要調用dispose()方法來釋放資源。假設沒有調用dispose(),一般情況下java的gc也會自動調用來釋放資源,但還是強烈建議在繪制完成以後顯式調用dispose()方法來確定被使用的資源得到及時釋放而不是依賴java gc。原因在于當你使用的graphics來自bufferedimage對象時,graphics對象不會被自動銷毀,而依賴gc調用來清理與釋放資源并不能保證及時釋放,可能導緻程式堆記憶體過度消耗産生oom(out of memory)問題。
graphics可以向下轉型為graphics2d對象,可以通過設定繪制屬性來實作對圖形繪制品質的控制。其接受對象為renderinghints的枚舉類型,通過方法setrenderinghint(rendering-hints.key, renderinghints.value)來實作,一般常用的key與value有如下形式。
控制圖形邊緣反鋸齒時,renderinghints.key_antialiasing的值為:
renderinghints.value_antialias_on表示支援邊緣反鋸齒。
renderinghints.value_antialias_off表示不支援邊緣反鋸齒。
控制文字或文本邊緣反鋸齒時,renderinghints.key_text_antialiasing的值為:
renderinghints.value_ text_antialias_on表示支援文本邊緣反鋸齒。
renderinghints.value_ text_antialias_off表示不支援文本邊緣反鋸齒。
控制圖像的插值方法時,key_interpolation的值為:
renderinghints.value_interpolation_bicubic表示使用雙立方插值方法。
renderinghints.value_ interpolation_bilinear表示使用雙線性插值方法。
renderinghints.value_ interpolation_nearest_neighbor表示使用臨近點插值方法。
控制繪制方法時,key_rendering的值為:
renderinghints.value_ render_quality表示支援繪制品質優先。
renderinghints.value_ render_speed表示支援繪制速度優先。
控制繪制過程是否支援抖動時,key_dithering的值為:
renderinghints.value_ dither_disable表示不支援抖動。
renderinghints.value_ dither_enable表示支援抖動。
更多的繪制屬性控制可以參考官方文檔,需要強調的是,由于java的跨平台屬性導緻并不是所有的renderinghints設定都會起作用,是以有些屬性可能隻有在某些特定的平台才支援。但是最常見的圖形與文本的反鋸齒功能幾乎所有的作業系統平台都支援!