JPEG2000
的實現
kakadu
中是用一個
16
位數來表示失真長度曲線的斜率;在整個編碼過程中,使用斜率值的右移四位的標量量化值。
編碼的分配表面是按照塊進行的,實際并是整個壓縮過程考慮的。
JPEG2000
使用一個
4096
元素的量化斜率值數組來存儲壓縮過程中遇到的斜率值(
quant_slope_rates
)。
當第一次編碼的時候,從
4096
個元素找滿足碼率的斜率下限,實際上這個時候沒有任何壓縮,數組的所有元素都為
0
;所以開始的時候得到的斜率值是
1
。第一個
block
使用斜率值
1
作為塊編碼的依據。
碼塊編碼需要兩個關于度量失真的參數:
wmse
和失真斜率。編碼為每個編碼過程定義了一個
pass_wmse_change
;這里面保存了碼塊每個編碼過程中對斜率的貢獻。如果使第一個
block
的第一個編碼過程,那么采用
-1
的估計失真長度曲線斜率;否則采用一個斜率的對數值。
1.?
首先將
wmse
分成
2
的
32
次方等份,這個作為每個過程的
pass_wmse_scale
。這里分成這些等份的原因在于編碼的時候使用的
32bit
的整數;當然最高位為符號位。每個編碼過程的
wmse
的
scale
都不一樣,當前過程的
pass_wmse_scale
是上個過程的四分之一。由于位平面編碼并非從第
30
位開始,所以對于丟棄的
msb
,需要乘以指定數個
1/4
。
注,這里不知道為什么要乘
1/4
。
2.?
進行一次過程編碼后,根據當前過程的信息查表計算得到該過程對整個圖像失真的改變值
distortion_change
。這個值于當前過程的
pass_wmse_scale
的乘積作為當前過程的
wmse
改進值存放到每個過程對應的
pass_wmse_change
數組中。
3.?
如果不是第一個
block
的第一個編碼過程;那么預測的斜率門限值應該是大于
0
,那么檢查并判斷當前過程是否已經滿足該斜率值了。基本按照如下方式計算:
a)????????
每個過程由一個編碼長度值
pass_lengths
和
wmse
的改進值:
pass_wmse_changes
;第一個作為長度的改進量,第二個作為失真的改進量。
b)???????
如果斜率與上面長度改進量的乘積比失真改進量大,說明這個過程以后的斜率都要比預測的斜率值小了;那么這個時候可以停止該
block
的編碼過程了。
注,這一步實際上也算是比較耗時間的過程。
4.?
完成需要的編碼過程后,對應編碼過程應該已經由了失真信息和長度信息。這個時候需要來檢查上面編碼過程中那些過程結束是優化的,同時找出每個編碼過程對應的斜率。這里以實際編碼的過程作為參數。
5.?
開始的時候設置斜率位-
1
;然后累計第一個過程的長度和失真值(分別在
pass_lengths
和
pass_wmse_change
中),得到
D
和
L
的比值,這個作為當前過程的斜率;對于第二個過程需要累計第一個、第二個兩個過程的值,得到一個斜率值;最終得到的值如果小于等于
0
;那么設置該過程的斜率為
0
;否則取上面值的對數作為當前過程的斜率值。
6.?
完成上面操作后,再檢查保留的過程中,按照編碼順序后面的過程斜率是否比前一個過程的斜率大,如果大保留后面那個過程的斜率,小的值修改為
0
。因此在完成
5
和
6
之后,被保存下來的點值都大于
0
,二其他被拋棄的點斜率變為
0
。
7.?
在完成
block
編碼后需要更新全局狀態(其在
kd_compressed_stats
中。
8.?
首先我們將當前
block
的大小,也就是多少個樣本添加到被編碼過程的樣本數中(
num_coded_samples
),第一個
block
時,這個值時
0
。這里需要這個值作為
trim
的依據和下個
block
編碼時使用的值。
9.?
統計每個編碼過程的斜率和長度值,并將斜率值量化為
1/16
作為數組
quant_slope_rates
(這是
1
個
4096
元素的數組,里面保存在該斜率下總共編碼的長度,也就是說如果不同的
block
具有相同的斜率的過程長度值被累加到一起)入口;當然,如果那些斜率為
0
的點需要被跳過,其長度被累加到下個在曲線上的編碼過程。同時更新一下當前可以使用的最大和最小斜率值。
10.?????????????
在
8
中提到的
num_coded_samples
用來檢查是否需要考慮
trim
多于的數據。多余數據被
trim
的檢查點為總體樣本的:
2/16
、
3/16
、
4/16…
處,后面都是按照、
/16
增加。
11.?????????????
一旦需要
trim
的時候,首先按照總樣本數量(注意這里不是已經編碼的樣本數量)和目標碼率計算目標碼流的長度,然后在
quant_slope_rates
中找到斜率,在這個斜率點所有
block
的所有過程長度的累加值比上面的總目標長度剛好大。而
trim
操作按照這個斜率值檢查所有已經編碼的
block
,
trim
掉所有比這個效率小的過程。可以看到在整個編碼過程中,這樣的
trim
操作最多需要進行
15
次,每次都一可能從所有塊中將小于指定斜率的編碼過程
trim
掉。上面的
trim
操作不會影響
quant_slope_rates
的值。
12.?????????????
上面已經完成了一個
block
的編碼;下面開始第二個
block
的時候稍微與第一個有點不同;主要的不同在于現在
quant_slope_rates
中已經包含斜率長度值了。根據
num_coded_samples
(這里保守增加了額外長度)和目標碼率計算期望的編碼長度;然后從
quant_slope_rates
中發現到這個長度的斜率值,這個值作為當前
block
編碼的最低的斜率門限。