色彩空間的編程

色彩空間的編程

假設有這麼一個問題,一個油氣田公司的報表,想表示在過去的一年裏,十二個月中每個月的原油產量和天然氣產量的趨勢是什麼樣的,怎麼用一個簡單的圖表表示?大家可能會立刻想到,把每個月的產量在圖表上標一個點,然後把這些點連起來,就成了趨勢線,原油產量連成一條線,天然氣產量連成另一條線。那麼如何區分哪條線是原油,哪條線是天然氣呢,答案也是很容易想到的,就是用紅顏色的線表示原油,藍顏色的線表示天然氣。或者說紅顏色的線表示原油,綠顏色的線表示天然氣。到目前爲止,用戶和程序員想的都是一樣的。

這時候,用戶說了,我想用黃色的線表示原油,用紫色的線表示天然氣,行不行?程序員稍稍遲疑了一下,行是行,只不過不如紅、綠、藍三種顏色來得方便。有一點色彩方面知識的人都知道,紅、綠、藍這三種顏色是最純淨的三種色,非常悅眼,稱爲三原色,其它的顏色都是由這幾種顏色混和成的。從程序員的角度來看,產生所有顏色只要用RGB(r, g, b)這個函數就行,這裏rgb這三個參數表示這三種色的量,最大爲255,最小爲0,比如想產生紅色,只要用RGB(255,0,0)就行了,同理,綠色就是RGB(0,255,0),藍色就是RGB(0,0,255),那麼黃色是怎麼出來的呢,本人在過去很長一段時間內都不知道,直到會用RGB函數以後才試出來的,是RGB(255,255,0),也就是紅色和綠色一混合就出來了。同樣紫色也是,得試很多次才能試出來,當然,色彩學得比較好的不用試也知道。這就是前面的用戶說要畫黃色線和紫色線時程序員比較遲疑的原因,畢竟不是三原色之一,還得試出來。

在程序員糾結畫什麼顏色好時,用戶又說了,我想把成品油的產量也加上去,顏色隨你定。程序員這才放心了,三條線正好使用三原色,正合適。當程序員正想準備實施編碼時,用戶又想起什麼事來,對程序員說,慢着!你能不能把成品油分類,像重油、輕油之類的,還有石蠟這樣的副產品也加上去。程序員稍稍想了一下,數了數:原油、天然氣、成品油、重油、輕油、石蠟。共6種,三原色佔去三種、三原色中兩兩混合又是三種,也還合適。這時候用戶跑去喝咖啡去了,臨走時對程序員說:你先假設幾個數,把圖表畫出來看看效果。程序員則繼續編碼,不一會兒,圖表出來了,圖表中的線條花花綠綠的非常好看,連程序員自己都很陶醉,等用戶過來檢查成果。

用戶喝完咖啡過來了,看着五顏色六色的圖表也覺得很不錯,他忽然想起了一個問題,又對程序員說,效果很不錯,嗯......不過,我想把成品油再細分一下,不要重油、輕油了,加上汽油、煤油、柴油、石蠟和瀝青,天然氣......也細分一下吧,甲烷和乙炔,先暫時分這兩種,以後可能分得更細......噢,要不然把所有的這些成分做在界面上,可以選擇的,我選哪個,就畫哪個,全選上就全都畫......用戶喝了咖啡,好像補充了能量,一下子想出了很多需求,滔滔不絕地向程序員表述了出來。程序員一開始還頻頻點頭,一邊點頭一邊說行、沒問題之類的,到最後,卻陷入了沉思之中。

我想大家都猜到了程序員在想什麼,如果只是規定好了要畫幾條線,哪怕是再多的線也沒問題,大不了一種顏色一種顏色地試,我們可以在Windows帶的畫圖板中一種一種地試,哪種顏色好看就用哪個,只要任何兩種顏色之間不重複就行。當用戶說完最後一條需求,程序員糾結了。因爲顏色不能再定死了,用戶選擇了幾種,程序員就得畫上幾條線,線條的數量都是不固定的,程序員怎麼能再試完再畫呢?

這就出現了這麼一個問題,如何生成指定數量的不同的顏色,另外加一個要求,顏色要儘量好看。也就是說生成的顏色要符合兩個要求,首要是區分開,其次是好看。

程序員起先是這麼想的,把RGB三原色的量分成幾份,每次加一份。比如要畫條8條不同的線,那麼,就把255分成8份,第一條線是RGB(0,0,0),第二條線是RGB(255/8,255/8,255/8),這裏面的三個參數都要取整。第三條線就是(255*2/8,255*2/8,255*2/8),以此類推。這樣實現起來是相當簡單,可實現效果呢,等程序員一畫出來,就傻眼了,畫出來的線既不符合第一種要求,也不符合第二條要求。第一條是黑色的,後面的依次灰度下降,全都是灰灰的線條,完全沒有一點美感可言,而且相鄰的兩條線幾乎分不出來,這個算法完全失敗了。

程序員在第一種算法的基礎上,吸取教訓,產生了第二種算法,第二種算法是這樣的,比如要生成9種線,那麼在色彩的每一個分量上都分別累加,前三個色彩在紅色分量上區分,如第一種顏色爲RGB(255/3,0,0),第二種:RGB(255*2/3,0,0),第三種(255,0,0),中間三種色彩在綠色分量上區分,後三種色彩在藍色分量上區分。這種算法在結果上與前一種算法相比有了長足的進步,相比之下美觀多了,而且在量小的情況下也容易互相區分出來。但其缺點也是明顯的,只有三種基本顏色,全靠其灰度來區分,當數量稍大時,兩種顏色很容易辨別不出來。

以上兩種算法犯的毛病有一個共同點就是沒有充分利用色彩空間。何爲色彩空間?就是將三個原色作爲三個座標軸,形成的一個正立方體,由此可見,原點的顏色爲RGB(0,0,0),即爲黑色,而與原點相對的那個點的顏色爲RGB(255,255,255),即爲白色。第一種算法產生的顏色都集中在從黑到白的這條直線上,自然就都是灰色的了。第二種算法都集中在三個座標軸上,所以可選擇的顏色相當侷促。那麼我們最終要做的就是充分利用這個色彩空間。

程序員經過長久的思考,想出了以下的方法,爲了簡單起見,不排除產生灰色的線,但要排除白色,因爲在圖表上顯示出不出來,對於給定的數,把這個數均勻地分配到色彩空間中,比如對於9這個數,我們把紅色分爲2份,這就能產生3個不同的量,0,255/2,255,把綠色分爲一份,可以產生2個不同的量,0255,把藍色分爲一份,可以產生2個不同的量,0255,把這其中的每一種做組合,就會產生12種組合(3*2*2),再去掉白色,還有11種,最後兩種放棄不用,完全可行。這樣,我們就充分利用了色彩空間。

有人問了,你這紅色分2份,綠色分1份,藍色分1份,這份數是怎麼出來的?這個問題正是算法最關鍵的地方,如何均分色彩空間。我們力求均勻,也就是我們儘量讓每個分量分的份數一樣,比如都分2份,但是份數一樣也會產生浪費,比如產生9種顏色,每個分量都分一份,產生2*2*2種顏色,不夠,都分兩份,就會產生3*3*3種顏色,產生27種,大部分用不着,太浪費了。於是我們把每個分量一點一點地往上加,比如都分一份不行,那麼把其中一個分量加1,也就是紅色分成2份,這下就夠了。如何找到這剛好不夠用的每份都分爲1份呢,那就只好對所要求的顏色數量進行開立方,比如9開立方就是2點幾,再取整,就是22的話就是分成一份,3的話就是分成2份,以此類推。我們在均分顏色空間時,就從這個開立方取整的數開始找,第一個分量加1看看夠不夠,不夠再把第二個分量加1,最差不過把三個分量都加1

上面的這個算法是要花費一番工夫來編碼實現的,不過相對於實現之後的成就感,這點辛苦就不值得一提了。任何一個成功的算法都是經過反覆試算觀察結果最終得到的,改進不合理的算法,形成自己的思路,進而實現效果更好的算法,不正是程序員的工作職責所在嗎?爲工作中的小成就而喜悅,爲生活中的小樂趣而快樂,正是人生的一大美事。

發佈了56 篇原創文章 · 獲贊 7 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章