天天看點

《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換

本節書摘來自異步社群《點睛:actionscript3.0遊戲互動程式設計》一書中的第1章,第1.3節,作者:遊志德 , 彭文波 更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

從前面的讨論可知,rgb模式是一個數理性質較強的概念,對于大部分色彩來說,我們很難通過rgb的數值得知它代表什麼顔色以及它的明暗和鮮豔程度如何。

《憶江南》中的景觀之是以能直接用最簡單的三原色來渲染,完全是因為它所描繪的江南美景足夠的清澈純淨而且顔色的種類較少。

實際上,大多數情況下,顔色的種類遠不止紅綠藍三種,例如北宋的蘇東坡在以歌詠殘秋季節景物為主題的《贈劉景文》一詩中就有這樣的一句:“一年好景君須記,最是橙黃桔綠時。”

類似的詩句舉不勝舉,例如韓愈的《晚春》中還提到了紫色:“草樹知春不久歸,百般紅紫鬥芳菲。”

從以上的例子我們不難看出,單憑紅綠藍三種顔色遠不能在感官認知上對萬千世界中豐富的色彩給出較為準确的定義。此外,即使我們确定了顔色種類,顔色的明暗或者飽和程度也需要加以描述。“綠樹陰濃夏日長,樓台倒影入池塘。”(高骈《山亭夏日》)中的“陰濃”就在亮度方面對綠色的深度進行了修飾。

作為21世紀的文藝程式員,我們也要在感性與理性之間尋找出屬于自己的一片天。hsb模式就幫了我們很大的忙。

hsb通過h(hue,色相)、s(saturation,飽和度)和b(brightless,亮度)來描述色彩的構成,與感官認知相當地吻合。同時讓我們感到欣慰的是,hsb模型的數學計算并沒有想象中的複雜,而且很容易就能轉換到計算機可以識别的rgb模式中,讓科學與藝術再次擦出閃耀的火花!

筆者不希望像其他介紹actionscript乃至美術的書一樣寥寥幾句就帶過hsb模式,或者直接把公式貼上來,畢竟這是“百度一下你就知道”的知識,直接搬過來也沒什麼意義可言了。是以,我們會簡單講下自己的了解,但與此同時,書上會貼出一些百度回來的内容,畢竟受篇幅所限,不可能面面俱到。

1.3.1 hsb模式的色彩空間模型及其分支

圖1-21所示為我從以上連結的文章複制過來的一張色彩空間示意圖,可見hsb在業界至少還可以細分成hsl和hsv兩種模式。它們都使用了三維坐标系來描述色彩值的分布。

第一個屬性是色相,它代表顔色的種類,如紅、黃、綠就分别屬于不同種類的顔色。色相值的大小來源于實體學中的可見光譜(也就是我們常說的七色彩虹),其中,位于兩端的紅光與紫光在顔色形态上(可能與反射色光的種類有關)比較接近。是以偉大的實體學家牛頓首次把直線狀的顔色光譜圍成一個圓環并将色相坐标軸做成了環狀。在這樣的一個色相環中,0度和360度完全等價,為紅色,其他顔色則根據它們在彩虹漸變中的順序依次排列,分别為:橙30,黃60,綠120,藍240,紫300(分布不均勻的原因跟rgb處理有關,實際上分布均為的模式更有利于指導色彩搭配)。引入亮度和飽和度以後,所有顔色便組成了一個實心圓柱體(實質上它們都可以由圓錐體展開,詳情可以查閱原文)。對于這一個屬性,hsv和hsl的了解完全一緻。圖1-21中,環形箭頭所指的角度(即實線與虛線之間的夾角,順時針為正,逆時針為負)就等于hue的值。

《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換

saturation值在坐标系中表現為坐标點到圓心(圓柱中軸線)的距離,距離圓心越遠,飽和度越高,色彩越鮮豔,取值範圍為0~100。

最後一個屬性代表亮度,兩種色彩模式用了不同的單詞(lightness和value),坐标系裡,它表示目前點到圓柱底部的距離,取值範圍為0~100。

圖1-22中,左側圓點所表示的是h=240、s=67、l=100的白色,右側圓點則表示h=90、s=67、v=83的綠色。

我們無法用很簡潔的語句概括它們之間的異同,但我們還是可以通過圖1-22看出一些特征性的差别。

1)hsl的亮度跟數學的概念非常吻合,亮度為0時必然全黑,亮度為100時必然全白;而hsv隻有亮度等于0的時候為全黑,亮度為100時rgb可能隻有一種顔色的光被全部反射出來。

2)兩者對飽和度的了解不甚一緻,hsl認為很白的顔色也能代表飽和,但hsv認為很白就一定很不鮮豔。是以hsv模式裡,隻有當s等于0時才有可能全白。而s=100、v=100隻相當于hsl模式中l=50的位置。

事實上,這兩種色彩模式都存在一定的缺陷,如黃色比粉紅往往要刺眼一些,但是hsl模式中,黃色的亮度還不如粉紅的高;又比如淡紫比深藍的感覺要鮮豔,hsv模式卻告訴我們,前者的飽和度比後者要低。

灰階值(1.4節會講述)可以在一定程度上解決以上問題,但是局限性依然很大。筆者曾經幻想過用純數學手段來彌補自己美術細胞的不足,結果都以失敗告終,直至某位美工給我筆者薦了幾款配色軟體以後我才如夢初醒。一個看起來不太起眼的colorpicker也得占用十幾兆的存儲空間,查閱安裝目錄後發現,光資料表就接近10mb,而且還是壓縮過的。可見美學的知識還真不是區區幾條數學公式就說了算。但無論如何,在此筆者還是代表全天下沒有美術功底的程式員們,向設計出hsb模型的數理學家緻以崇高的敬意。

一般涉及取色器的軟體都會使用到hsb模式,而且hsl和hsv兩者隻選其一,比如windows的系統顔色面闆和microsoft office會使用hsl,而adobe系列的軟體如flash、photoshop則傾向于選擇hsv。因為使用hsv的軟體往往喜歡用b代替v,是以導緻筆者經常搞混hsb、hsl和hsv之間的關系,也讓筆者在後續的日子裡走了不少彎路。在此希望筆者的前車之鑒,可以讓大家不會重蹈覆轍。在碰到類似問題的時候,建議先搞清楚别人所提到的hsb具體是指hsl、hsv還是廣義上的色相模型。

1.3.2 軟體中的拾色器如何實作hsb的色彩空間模型

閱讀本書的朋友恐怕很少有機會接觸到圓柱形的三維取色器,而hsb模式卻是一個立體的空間。那麼,軟體裡的顔色拾取器是如何在平面裡展現出3d坐标系的呢?讓我們從windows調色闆開始研究。

圖1-22是windows系統調色闆的界面。抛開左側的顔色清單不談,我們可以把windows調色闆分為兩個部分:一個二維的平面和一個一維的滑動條。乍一看似乎跟之前的圓柱體空間扯不上任何關系,不過大家有沒發現,最右側那個一維的條是不是跟圓柱體的母線很像,自上而下呈現出逐漸變暗的趨勢嗎?沒錯,它就相當于圓柱體的高度變化。一維條左邊的色彩選取平面就相當于圓柱體的橫截面了,隻是被拉成了矩形而已。因為我們可以看到,左邊緣跟右邊緣都是紅色,而底部始終為灰色,這足以證明它就是圓環的一個變體。

《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換

小提示

在配套源碼裡,筆者給出了從圓形色盤展開為矩形的一個示範動畫,有興趣的讀者可以自行查閱。

我們觀察一下滑塊拖動時hsl 3個值的變化,rgb部分在這裡就先忽略了,因為取色面闆的建構原理都基于hsl模式。注意,這3個值的取值範圍都被調整為0~240。

我們隻拖動右側的滑塊,hsl 3個值當中隻有l在變化,這跟色彩空間示意圖相當吻合;小心翼翼地拖動二維面闆上的十字準星,讓它隻在水準方向移動,則隻有h值在變化(windows面闆用了e這個字母);而隻作豎直方向移動的話,就隻更改s的值了。

筆者不是美術專業人士,但有閱讀過跟網頁色彩搭配有關的書籍,裡面曾提到過,要使整個頁面的色彩比較協調,其中的一個辦法就是讓色相、飽和度跟亮度這三者之中至少有一項保持基本一緻。是以這樣的面闆對于調出一套比較合理的配色方案還是會有一定幫助的。

當圓柱體被平面化以後,這3條坐标軸就可以随意組合了,不一定再是亮度占着一維空間。下面我們再來看看flash cs 5.5軟體裡的顔色面闆。

啟動flash cs6/ 5.5,在確定有fla文檔打開的前提下,選擇菜單項【視窗】|【顔色】(alt+shift+f9),就能打開如圖1-23所示的顔色面闆。

我們確定下拉框標明的是純色,在其下方的單選按鈕選中的是hsb中的b選項,将會看到跟windows系統調色闆非常相似的界面。不同的是,一維滑動條最上方不再顯示白色,因為flash cs6/5.5使用的是hsv模式,即使把b拖到100%,也還是呈現出紫色來。

拖動一維滑動條上的滑塊,我們還可以看到,二維調色面的色彩也會随之更改,即圓柱截面實時更新。與windows系統調色闆相比,這絕對是個優勢。它會根據目前點的高度實時截取圓柱的橫截面,使我們可以第一時間觀察到真實的顔色值,非常直覺,如圖1-24所示。

《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換
《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換

與此同時,一維軸的屬性還可以由使用者指定。我們可以把單選按鈕標明到h或者s上,然後左側的平面就将由另外兩個坐标軸進行建構,如圖1-25、圖1-26所示。

我們甚至可以将一維軸設定為r、g或者b,但個人認為此舉沒有太實在的美學意義。

flash cs6新增的kuler面闆(實際上它隻是個網站,安裝完成以後在cs5.5的【擴充菜單項】裡也能找到)比較準确地還原了色彩空間的示意圖,用圓來表示h和s坐标軸所構成的平面,進而更有助于我們了解hsv模式的原型尤其是h的概念,如圖1-27所示。

《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換
《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換
《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換

但需要注意的一點是,kuler的色環将紅和黃的角度拉開了,跟hsb模型中的色環有所不同。因為這樣的分布更符合美術上的色彩對比概念,對色彩搭配更有幫助。

與rgb模式相比,hsb更直覺地描述了人類對色彩的真實感覺,為色彩的視覺變化提供了一套非常有指導意義的解決方案。諸如變色、明暗調整、對比度更改這一類的事兒,hsb都能很完美地實作。雖說rgb也能通過色光反射量實作一些變換,但它對肉眼來說太不友好了,出來的效果也頗為生硬。

下面我們來研究下hsb和rgb之間的轉換公式。

1.3.3 hsb與rgb之間的互轉公式及hsl和hsv對色彩屬性了解的異同

首先,hsl和hsv對h的定義一緻,公式如下。

《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換

max=min意味着r、g、b 3個值始終相等,隻能呈現出黑白灰3種顔色。色相值在這種情況下沒有任何意義,是以幹脆讓它等于0。

然後,hsb模式将色相環等分成3個長度均為120°的區間,如圖1-28所示。

《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換

[0,60]u[300,360]為紅色區間,[60,180]為綠色區間,[180,300]為藍色區間。判斷rgb顔色的h值位于哪個顔色區間也非常簡單,我們隻要找出色光反射量最大的那個通道即可。

紅色被劃分到了兩側,是以當色相位于紅色區間時要多加一個條件,但它并不複雜,因為h軸本身是環狀結構,左側與右側實際上是重合的。是以這一步的判斷僅僅是為了確定計算出來的角度始終落在[0, 360]的區間内而不至于出現負數。是以當max=r時,公式可以合并如下。

(60*(g−b)/(max−min)+360)%360

但是我們寫程式的時候,一般都還是用邏輯判斷來處理,因為取餘數的執行效率比較差。

然後我們看看hsl裡面l和s的計算方法。

《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換

可見,隻有當max和min都取到通道的最大值,即r=g=b=255時,亮度才能達到100%,換而言之,hsl模式裡,亮度最大的隻有白色,這跟hsl的色彩空間示意圖不謀而合。

max=min or l=0意味着r=g=b,這時候的顔色必然是黑白灰的其中一種,自然就沒有飽和度了。

而hsv中,v和s的計算公式如下。

《點睛:ActionScript3.0遊戲互動程式設計》——1.3 HSB模式及其與RGB間的轉換

作為實體意義是亮度的v,它達到最大值的要求比hsl模式低,rgb 3個通道中隻要有一個等于255,亮度就達到最大值。這樣的差異,可能導緻兩種顔色的明暗比較在不同的模式描述下出現不同的結果,即顔色a和顔色b之間存在l(a)>l(b)但v(a)

飽和度為0的定義,兩種模式沒有差别,而飽和度的計算規則也都以r、g、b通道值的差作為主要的決定因素,再除以亮度進而得到标準化的結果。然後,因為亮度計算的差異,l的色彩變化範圍要比v大一倍,是以hsl模式的除數必須等于亮度的2倍才可以使被擴大的範圍得以抵消,加上較明亮的顔色,hsv和hsl在飽和度方面沒有達成共識,hsl模式的s公式就要寫成分段函數了。

而hsv/hsl轉rgb則是rgb轉hsv/hsl的逆運算,雖然在一些極端條件下,這種運算并不可逆,但請放心,這些問題不會影響到我們對色彩的使用。

比如h=250,s=60,l=100和h=300,s=50,l=100,它們的rgb數值都等于255,這時候再轉回hsl,就是h=0,s=0,l=100,值是變了,不過結果都還是白色。這跟地球極點處的經緯度算法非常相似。

1.3.4 hsb與rgb互轉公式的actionscript實作

為了讓hsb轉rgb這個通用的算法在後續的項目裡可以重用,我們先把這個轉換公式做成一個工具類并且放入到公共類庫裡。當然了,這樣的類,網上也有很多現成的可以直接拿過來用(個人推薦frocessing工具包)。

類裡的算法看起來跟上述的公式略有出入,一方面是因為我們借用了一些現成的代碼,另一方面是因為我們把s和l/v的取值範圍從0~1改成了0~100。

受篇幅所限,我們就不在這裡貼出實作的代碼了,讀者可自行查閱publicclasses中的convertcolor類。

代碼清單1-11

繼續閱讀