關於圖像的YC壓縮與YC伸張

這兩天一直在研究圖像的RGB顯示超限的問題,谷歌了老半天,終於找到一篇Silky的帖子。帖子內容如下,希望可以幫到有需要之人。

 

我把以前寫過的東西做一個整理,因爲時間的關係,我沒有辦法把每一個細節都講得非常的詳細,不過我會把大概的原因,和處理的方法,儘量用很精簡的方式,條列整理出來。
如果對更深入的原理有興趣,請搜尋過去零散的討論。

一切都要從 ITU-R BT.601 這個"建議"開始說起。
現今的 DVD/VCD/DV 都是遵循 ITU-R BT.601 這個規格,這個規格規定了,模擬影像轉數字時,取樣的方式,儲存的數據格式、數據範圍等等。
當影像轉爲 MPEG 的時候,RGB 數據要轉成 MPEG 使用的 YUV 格式。ITU-R BT.601 裏面規定了這個 RGB <-> YUV 的轉換式,數據範圍 0~255 的 RGB 要轉爲 YUV 的時候,要先做數據範圍的壓縮,把範圍壓縮成 16~235,然後才轉成 YUV 儲存起來。然後 MPEG 解壓縮的時候,解出來的 YUV,要做數據範圍的擴張,將 Y: 16~235, UV: 16~240 的數據擴展爲 0~255 的 RGB,也就是還原回原來的 RGB 數值,然後才能顯示在顯示器的屏幕上。
這個 0~255 RGB -> 16~235 YUV 的過程,就叫做 YC 壓縮。
反過來 16~235 YUV -> 0~255 RGB 的過程就叫做 YC 伸張。

我們可以很清楚地看到,YC 伸張和壓縮要互相搭配,最終顯示出來的結果才正確。
如果:
A. 播放時
1. 轉 MPEG 的時候沒有做 YC 壓縮,儲存的是 0~255 的 YUV,播放時就不可以做 YC 伸張,否則 0~255 的資料再伸張一次,會變成 -19~278。
當然,8 bits 的數據儲存範圍只能是 0~255,數據超出的範圍會被削掉(clipping),整個畫面對比會過強,色彩會崩潰。

2. 轉 MPEG 的時候有做 YC 壓縮,儲存的是 16~235 的 YUV,播放時就一定要做 YC 伸張,如果不做 YC 伸張,顯示的是 16~235 YUV -> 16~235 RGB。
RGB [235,235,235] 在顯示器上看起來不是純白,而會有點灰灰的,[255,255,255] 纔是純白。
相同的,[16,16,16] 看起來也不會是純黑,[0,0,0] 纔是純黑。
16~235 的 RGB,數據範圍(動態範圍)縮小,對比會變差,色彩黯淡,看上去好像蒙上了一層白紗。

顯示卡的 DirectDraw Overlay,使用硬件的 YUV -> RGB 色彩空間轉換,都會遵守 ITU-R BT.601 的建議,認爲 MPEG 的 YUV 數據範圍應該是 16~235,所以都會做 YC 伸張。
所以我們可以得到結論,當轉成 MPEG 的時候,一定要確保 YUV 的數據範圍是 16~235,這樣在計算機上看、在電視上看,纔會看到正確的色彩、對比表現。

所以
B. 壓縮時
1. 如果輸入的 RGB 數據範圍是 0~255,轉 MPEG-2 時就要先做 YC 壓縮,轉成 16~235 的 YUV,這樣將來播放時顯示纔會正確。

2. 如果輸入的 RGB 數據範圍是 16~235,轉 MPEG-2 時就不能做 YC 壓縮,要直接轉成 16~235 的 YUV,這樣將來播放時顯示纔會正確。
如果輸入的是 16~235 RGB,轉 MPEG 時又再做一次 YC 壓縮,數據範圍會變成 30~218 YUV,這樣即使將來播放時做 YC 伸張,還是隻能伸張到 16~235 的 RGB,結果還是不對。


那麼,重點就是
1. 怎麼知道輸入的訊源是 16~235 RGB,還是 0~255 RGB?
2. 怎麼知道壓縮的 MPEG 軟件在轉 RGB -> YUV 的時候會做 YC 壓縮,還是不做 YC 壓縮?

 

我們先看第一點,假設你的訊源是:
1. DivX/XviD 的 AVI,要轉 DVD/SVCD/VCD
DivX 和 XviD 都遵循 ITU-R BT.601 規範,解碼輸出 RGB 時都會做 YC 伸張,所以以 DivX/XviD 的 AVI 作爲訊源,都是 0~255 範圍的 RGB。

2. 訊源是 DVD,或 HDTV 的 MPEG-2 TS,或其它 MPEG 文件
看你用來解碼 MPEG,輸出 RGB 的軟件是哪一個,這個軟件解碼輸出的設定爲何。

例如:
2a. 解碼軟件是 DVD2AVI,在 RGB -> YUV 的設定底下有兩個選項,一個叫做 PC Scale,另一個叫做 TV Scale。選 PC Scale,解碼就會使用 PC Scale 的轉換式,輸出 0~255 的 RGB;選 TV Scale,解碼就會輸出 16~235 的 RGB。

由上述的說明,我們可以知道 DVD2AVI 的一個運用:
當我們不勾選 DVD2AVI -> Help -> DirectDraw Overlay 時,DVD2AVI 不會啓動 DirectDraw Overlay,而是走傳統的 GDI 顯示方式,輸出 RGB 給顯示卡顯示。此時畫面上看到的色彩,會受 YUV -> RGB 選項底下設定的 PC/TV Scale 影響;選 TV Sclae,顏色黯淡;選 PC Scale,顏色正確。
當我們啓動 DirectDraw Overlay,此時畫面的顯示,是由 DVD2AVI 直接輸出 YUV,走 DirectDraw Overlay,丟給顯示卡去做 YUV -> RGB 的色彩空間轉換。此時畫面上顯示的顏色,由顯示卡決定,PC/TV Scale 的設定完全不影響看到的畫面。
而顯示卡的色空間轉換,如前所述,不亂搞的話,都是遵循 ITU-R BT.601,用 PC Scale。

在接下去說明之前,要先介紹兩個名詞:
0~255 的 RGB,又叫做 full-range RGB
16~235 的 RGB,又叫做 compressed-range RGB

更深入的介紹,有興趣的人可以參考 SGI 網站上的這一篇好文章
Digital Media Programming Guide Chapter 2. Digital Media Essentials

知道這兩個新名詞後,接着往下看
2b. 解碼軟件是 m2v,在 m2v 的設定畫面裏,YUV Range 底下有兩個選項讓你選擇,一個是 Full Range,另一個是 ITU-R BT.601 Range。怎麼樣,是不是覺得這兩個名詞很熟悉  

相信看過上面的解釋,您應該可以猜到,選 Full Range 的意思是代表告訴 m2v,我的 YUV 數據範圍已經是 0~255 的 YUV 了,不要再做伸張了唷。所以選 Full Range,m2v 就不會做伸張,而是直接轉換。
相反的選 ITU-R BT.601 Range,就是告訴 m2v,我的 YUV 數據範圍是 16~235,輸出時請做 YC 伸張。

所以:
1) m2v 選 Full Range,等於 DVD2AVI 的 TV Scale,輸出時不做 YC 伸張,16~235 YUV 輸出的是 16~235 RGB。

2) m2v 選 ITU-R BT.601 Range,等於 DVD2AVI 的 PC Scale,輸出時會做 YC 伸張,16~235 YUV 輸出的是 0~255 的 RGB。

其它 MPEG Decoder,請自行實驗其輸出結果。

3. 如果訊源是 DV-AVI
看用來解碼的 DV Codec 是哪一個。
如果是 Canopus DV Codec,不會伸張,16~235。
如果是 MS DV Codec, Panasonic DV Codec,會伸張,0~255。

4. 訊源是用 PhotoShop 等繪圖軟件,自制的計算機動畫
無庸置疑,是 0~255 RGB。

 

OK,這樣我們就知道訊源是 0~255 還是 16~235 了,接下來,第二點,MPEG 壓縮軟件會不會做 YC 壓縮?

答案是,不同軟件有不同做法。我試驗過的幾個:
1. 可以自由切換選擇要不要做 YC 壓縮
TMPGEnc, CCE SP

2. 一律做 YC 壓縮,當成輸入的都是 0~255 RGB
MainConcept MPEG Enocder, Panansonic MPEG2&1 Encoder
DivX, XviD

3. 一律不做 YC 壓縮,當成輸入的都是 16~235 RGB
MPEG Conversion Studio, ProCoder。

我們以 TMPGEnc 爲例
TMGEnc 選擇切換要不要做 YC 壓縮的選項,叫做 "Output YUV data as Basic YCbCr ont CCIR601"。
名詞解釋時間  
0~255 YUV = full-range YUV,TMPGEnc 叫做 Basic YUV (YCbCr)。
16~235 YUV = compressed-range YUV = ITU-R BT.601 YUV,TMPGEnc 叫做 CCIR601 YUV。

勾選 "Output YUV data as Basic YCbCr ont CCIR601" 這個選項,TMPGEnc 就會認爲要輸出的是 Basic YUV = 0~255 YUV,所以不做 YC 壓縮,直接轉換。
不勾選這個選項,TMPGEnc 會認爲要輸出的是 CCIR601 YUV = 16~235 YUV,所以會做 YC 壓縮,轉成 16~235 YUV。

會不會很複雜,開始頭暈了? ^^;
沒關係,我最後會總結整理成一個很簡單的列表,但是在此之前我必須先說明完原理,因爲組合的情況有很多種,不同 Decoder 輸出不一樣,不同 MPEG 壓縮軟件的處理不一樣,我不可能有時間一一去測試所有的組合情況,所以唯有您自行理解原理,瞭解吸收了以後,遇到不同的組合,您才能知道要怎麼設定,而不是隻死記一種做法,這也是爲什麼我會不厭其煩地,再三地解釋、說明這些令人頭暈的道理 ^^;

那麼會有哪些組合的情況呢?
在 TMPGEnc 的網站上曾經出現過一篇很精彩的討論,參與討論的有 TMPGEnc 的作者崛老,還有 m2v 的作者 marumo(那位署名 "茂木" 的即是 marumo)。
在這篇討論中崛老提到,"Output YUV data as Basic YCbCr ont CCIR601" 選項做的事情,是當 RGB -> YUV 的時候,使用不同的轉換式,不勾會做 YC 壓縮,勾了就不做 YC 壓縮。崛老還舉出了所有可能的情況,我把他翻譯過來給大家看:
http://www.pegasys-inc.co.jp/bbscgi/bbs/board.cgi?board=tmpgenc&cmd=topic&wparam=182

1. 當訊源不是 CCIR601 標準,也就是 (0~255) 時
不勾 ==> RGB(0~255) -> YUV(16~235) 正確 ^_^

勾 ==> RGB(0~255) -> YUV(0~255)
播放時會做伸張 YUV(0~255) -> RGB(-19~278) 超過 0 和 255 的數據都會被削掉,
畫面色彩崩潰,錯誤 >_<

2. 當訊源是 CCIR601 標準,也就是 (16~235) 時
不勾 ==> RGB(16~235) -> YUV(30~218) 顏色變淡、對比變差,畫面好像罩上了一層白霧 >_<

勾 ==> RGB(16~235) -> YUV(16~235) 正確 ^_^

然後崛老說像 Canopus DV Codec 這種 CCIR601 標準(不做伸張)的訊源,
要勾選才正確;反過來說,非 CCIR601 標準的訊源(做過伸張),不勾選才正確。

 

所以總結起來,如果訊源是 MPEG,用 DVD2AVI 解碼,則正確的做法

代碼:

DVD2AVI PC Scale -> 0~255 RGB -> TMPGEnc 不勾 "Output YUV data as Basic YCbCr ont CCIR601" DVD2AVI TV Scale -> 16~235 RGB -> TMPGEnc 要勾 "Output YUV data as Basic YCbCr ont CCIR601"同理,如果是 m2v 解碼

代碼:

m2v ITU-R BT.601 Range -> 0~255 RGB -> TMPGEnc 不勾 m2v Full Range -> 16~235 RGB -> TMPGEnc 要勾如果用的是 CCE SP 來壓 MPEG,CCE SP 切換的選項在 Video 裏面,叫做 Luminance level,有兩個選項
16-235 = 做 YC 壓縮 = TMPGEnc 不勾 "Output YUV data as Basic YCbCr ont CCIR601"
0-255 = 不做 YC 壓縮 = TMPGEnc 勾 "Output YUV data as Basic YCbCr ont CCIR601"

所以

代碼:

DVD2AVI PC Scale -> 0~255 RGB -> CCE SP 選 "16-235" DVD2AVI TV Scale -> 16~235 RGB -> CCE SP 選 "0-255"m2v 的情況依此類推。


如果 MPEG 壓縮軟件不能切換 YC 壓縮的選項,例如 ProCoder,那怎麼辦?
我以前寫過一篇,轉貼過來,省打字時間
==
ProCoder 1.5 版有個重要的更新,ITU-R BT.601 color correction 設定,
可以讓你選擇要不要做 YC 壓縮,這是一個很重要的設定。

TMPGEnc 有這個設定,"Output YUV data as Basic YCbCr ont CCIR601",
這個設定不是"改善"色深,而是做"正確"的選擇,保持本來的顏色。
本來就應該要根據輸入的訊源,正確的選擇切換這個選項,才能得到正確的結果。
這個選項不是用來"改善"或者是"補強"用的,不要弄錯了原本的意圖。
其它 MPEG 壓縮程序例如 CCE SP 也有相同的設定。

而 ProCoder v1.01.35 版沒有這個設定,一律將 input 視爲是 CCIR601 YUV
(顏色範圍是 Y:16~235, UV:16~240),所以使用者無法根據使用的訊源做切換。
Canopus 本身的 DV Codec 便是輸出 CCIR601 YUV,其 RGB 範圍是 16~235,
剛好和 ProCoder 互相搭配。但是其它 DV Codec,例如 MS 的 DV Codec
Panasonic 的 DV Codec,輸出的則是 Basic YUV。

這樣壓縮 CCIR601 訊源時沒有問題,但是遇到 Basic YUV(顏色範圍是 YUV:0~255,
例如自行用計算機繪圖製作的 CG 動畫,做過 YC 伸張的 DVD/VCD/DV 訊源... 等等),
ProCoder 就慘了,壓出來的對比會過強,色彩會完全崩潰。

有時候 Basic YUV 的影片本身的對比、色彩並不是很強烈,經過 ProCoder 錯誤的壓縮後,
反而會讓人有"色彩變鮮豔了"的感覺,不過其實那反而不是原本的顏色。
如果影片本身的對比、色彩本來就很強烈,再經過錯誤壓縮,就會發生悽慘的"色崩"現象。
由於這個後果不是我們能預期、控制的,所以如果真要調整顏色,還不如用正確的色彩壓縮設定,
讓所見即所得,然後另外用調整顏色的濾鏡自行修改顏色,調整到我們需要的樣子。

由於 ProCoder v1.01.35 沒有提供切換 YC 壓縮的設定,所以遇到 Basic YUV 訊源,
在送給 ProCoder 壓縮之前,你需要先自行用其它軟件,將 Basic YUV 轉爲 CCIR601 YUV,
再送給 ProCoder 壓縮,色彩纔會正確。

Avisynth, AviUtl 都有這個轉換的功能。
==

也就是說如果要給 ProCoder 壓縮,DVD2AVI 一定要選 TV Scale 輸出,m2v 一定要選 Full Range 輸出,如果是使用其它不能選擇輸出模式的 MPEG Decoder,只好用 AviUtl/Avisynth 的 filter 做後製處理。

 

 

OK,基本的講完了 ^^;
接下來進階討論(我的手好酸 ><)...

1. 以上講的是訊源都是 RGB,壓 MPEG 時要做 RGB -> YUV,如果訊源是 YUV,則如何設定?

當訊源已經是 YUV 時,就不用去管 YC 伸張壓縮的設定。
例如用 MainConcept MPEG Encoder 壓 DV-AVI,用 Canopus DV Codec 解碼,MainConcept MPEG Encoder RGB -> YUV 一律做 YC 壓縮,照理說顏色會變淡。但是由於 MainConcept MPEG Encoder 可以接收 YUY2 輸入,所以 Canopus DV Codec 會直接輸出 16~235 YUY2 給 MainConcept MPEG Encoder,這樣一來,就跳過了 RGB -> YUV 的步驟,當然也就沒有 YC 壓縮的問題,所以也就不會出現顏色不正確的情況。

然而如果是 TMPGEnc,以及有用到 VFAPI,因爲 VFAPI 都要轉成 RGB 處理,所以仍需注意 YC 伸張壓縮的設定。
例如如果用 TMPGEnc 壓 DV-AVI,一樣用 Canopus DV Codec 解碼,用默認值轉換式,輸出的是 16~235 RGB,所以便要勾 "Output YUV data as Basic YCbCr ont CCIR601"。

2. 解碼時做 YC 伸張的優缺點?
a. 優點
1) 所見即所得,屏幕上見到的樣子,就是將來壓好 MPEG 解碼輸出的樣子,這樣做後製處理時,比較容易調整。

2) 大部分 MPEG Encoder 都是認爲會接收 0~255 RGB 的輸入,所以 RGB -> YUV 時都會作 YC 壓縮,因此訊源在作解碼時一定要作 YC 伸張,纔會正確。

b. 缺點
1) 0~255,8 bits 的範圍全用光了,沒有留下運算時需要的 headroom。

2) Source (16~235 YUV) -> 0~255 RGB -> MPEG (16~235 YUV)
YC 伸張後再壓縮,會有一點損失

YC 伸張計算式
Y' = (Y - 16) * 255 / (235 - 16)
C' = C * 255 / (255 - (240-16))

CCE SP 的說明書中,解釋 16-235 和 0-255 選項的作用時,有列直接轉換,和 YC 壓縮轉換所使用的不同的計算式
"16-235" --> YC 壓縮轉換
Rd = 219*R + 16*256
Gd = 219*G + 16*256
Bd = 219*B + 16*256
Y = 77*Rd + 150*Gd + 29*Bd / 2^16
CR = (( 131*Rd - 110*Gd - 21*Bd ) / 2^16 ) +128
CB = (( -44*Rd - 87*Gd + 131*Bd ) / 2^16 ) +128

"0-255" --> 直接轉換
Y = 77*Rd + 150*Gd + 29*Bd / 2^8
CR = (( 131*Rd - 110*Gd - 21*Bd ) / 2^8 ) +128
CB = (( -44*Rd - 87*Gd + 131*Bd ) / 2^8 ) +128

如上列所見,這個轉換式有小數點,需要捨棄進位,所以反覆多次 YC 壓縮伸張 RGB <-> YUV 變換,畫質會有一點損失。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章