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