程式設計小知識之 Dithering

2021-10-01 03:43:23 字數 1841 閱讀 7228

本文簡單介紹了 dithering(抖動) 的一些知識

圖形後處理有一種操作稱為 dithering(抖動),所謂 dithering,就是一種能夠在較小色彩空間上"模擬出"較大色彩空間的影象處理方法,說的有些抽象,我們來舉個例子:

假設我們需要在顯示器上顯示以下(來自這裡):

的畫素格式為 rgb

24rgb24

rgb2

4(畫素的 r,g

,br,g,b

r,g,

b 通道各佔 1

11 個位元組(8

88 位),乙個畫素占用 3

33 個位元組(共 24

2424

位)),rgb

24rgb24

rgb2

4 格式的畫素總共能夠表達 224=

16777216

2^ = 16777216

224=16

7772

16種不同的顏色,現在的大部分顯示器也能夠顯示這麼多種顏色(這裡我們暫時忽略伽馬校正等因素的影響),所以我們不用對做什麼特殊處理,直接輸出顯示即可~

但是如果顯示器能夠顯示的顏色數量有限(譬如只能顯示 216

21621

6 種顏色),那麼就需要對原進行處理了,一種簡單的方法就是對畫素進行截斷或者捨入處理,但是這樣會讓產生明顯的色帶(color banding)現象,譬如上面所示的,經過(畫素)截斷(捨入)之後,大概會顯示成這個樣子(來自這裡):

可以看到顯示效果很差,那有沒有辦法改善呢?答案就是使用 dithering(抖動): dithering(抖動) 通過調整乙個畫素周圍畫素的顏色值,使人眼產生錯覺,從而"模擬出"更多的顯示顏色(譬如將黑白兩種顏色並列在一起就可以"模擬出"灰色(人眼錯覺的關係)),仍然拿上面的舉例,經過 dithering(抖動) 之後,顯示效果會變成這樣(來自這裡):

可以看到顯示效果較之前的版本要好了不少(雖然兩者的顏色空間(使用到的顏色數量)其實是相同的)

那具體 dithering(抖動) 是怎麼調整畫素的呢?方法其實有不少,這裡我們簡單介紹一下經典的 floyd–steinberg 演算法,演算法的基本思想就是使用誤差擴散(error diffusion),所謂誤差擴散,簡單來說,就是將畫素截斷或者捨入之後的顏色誤差擴散(新增)到周圍的畫素顏色上去, floyd–steinberg 演算法採用的誤差擴散方式如下所示(來自wiki):

圖中的 * 號代表的就是當前正在處理(抖動)的畫素,該畫素截斷或者捨入之後的顏色誤差會按 7/16

,1/16

,5/16

,3/16

7/16, 1/16, 5/16, 3/16

7/16,1

/16,

5/16

,3/1

6 的比例新增到其 右, 右下, 下, 左下 的畫素上去, wiki 上已經給出了相關偽碼,這裡也有乙份完整的**實現(基於 unity),有興趣的朋友可以仔細看看~

參考資料

程式設計小知識之 Dispose 模式

本文簡述了 c 中 dispose 模式的一些知識 之前對 c 中的 dispose 模式只有些模糊印象,近來又了解了一些相關知識,在此簡單做些記錄 c 程式中每種型別都可以看做是一種資源,這些資源可以分成兩類 託管資源 受 clr 管理 分配和釋放 的資源,譬如 new 出的某個型別物件 非託管資...

網路程式設計小知識

pdu 協議資料單元,有隱藏size上限,如果應用程式的包超過指定上限會被劃分為多個pdu傳送 tcp不提供記錄結束標記,需要應用程式自己提供,比如http的 r n 編寫tcp協議需要注意ipv4和ipv6的相容性,可以在應用程式中實現協議無關性。getaddrinfo 多執行緒的socket程式...

程式設計小知識之 Lua 長度運算子

本文講解了 lua 中長度運算子 的一些知識 注 以下討論基於 lua 5.3.5 版本 基礎 lua 中的長度運算子 可以用於獲取 table 的 長度 舉個簡單的例子 local t print t 3但其實對於 table 而言,長度運算子並不等同於獲取 table 的 長度 更準確一些的說法...