Revised : 2006/07/31
Since : 2006/07/31
算術符号は区間 [0, 1) を分割したが、レンジコーダは最初に大きな幅(range)たとえば区間
[0, 10000) を設定し、分割していくことで符号化する。
レンジコーダは整数で演算するので、データが多くなるとレンジが小さくなり、分割不可能となる。その時はレンジを拡大する。
レンジ拡大のタイミングを定めることにより、区間全体の大きさを覚えておく必要はない。また、区間の下限値と幅だけで符号化が可能である。
復号化も、符号化と同タイミングでレンジ拡大することにより可能である。
レンジコーダでは区間の下限値を符号語とする。
レンジコーダには大きく分けて、「桁上がりあり」と「桁上がりなし」がある。
説明を簡単にするために、全体を符号なし7bit(負は無)、レンジの精度を5bitとし最低確保する精度は
3bitととする。
上位2bitは桁上がりに対応するためのバッファに使用する。(JAVAのbyte型を想定)
(通常はCPUが高速にあつかえる最大サイズがよい)
最低確保する精度とは、両隣と区別可能であること。つまり、頻度総数の最大値を保証するものである。
例としてabcabaを考える。
まず頻度表を作る。
出現頻度表 | |
文字 | 頻度 |
EOF | 1 |
c | 1 |
b | 2 |
a | 3 |
総数 | 7 |
これをレンジで表す。
R:幅
L:下限値
EOF:end of file
対応表 | |||
文字 | Low | Range | 備考 |
EOF | 6 | 1 | [6 , 7) |
c | 5 | 1 | [5 , 6) |
b | 3 | 2 | [3 , 5) |
a | 0 | 3 | [0 , 3) |
総数は7であり3bitで表せるから、ここから符号化を開始する。
区間は[low , low + range)と表せる。
初期の区間は[0 , 32)とする。
この時32は含まないためレンジは31とする。下限値は0である。
まず、現在のレンジを頻度総数で割り、一個あたりの幅を算出する。
入力文字の下限値に一個あたりの幅を掛け、増加分の下限値を算出し、現在の下限値に加算する。(新たな下限値)
入力文字の頻度に一個あたりの幅を掛け、新たなレンジを算出する。
以上を繰り返す。
幅が最低の精度を確保できなくなった場合、レンジ拡大する。(頻度総数が7で幅が4の場合、一個当たり1bit未満となり符号化できない)
今、精度5bit最低3bitで作業しているため、5-3=2bitが作業領域である。
拡大も下限値、幅とも2bit左シフト(4倍)する。lowの上位2bitは出力する。
ただし、lowの5,4bitがともに1の場合、出力せずに一時保存する。
またバッファ桁上がり回数を+1する。シフト後の上位2bitを0とする。
(シフトすると7,6bitがともに1となりバッファでも桁上がりの可能性があるため)
次の出力時もバッファが桁上がりする可能性がある場合は、バッファ桁上がり回数を+1し、シフト後の上位2bitを0とする。
バッファの桁上がりの可能性がない場合は、バッファが桁上がりしたかを判定する。
lowの上位2bitが01の場合、桁上がりしているので、一時保存+1を出力し、バッファ桁上がり回数分00を出力する。
lowの上位2bitが00の場合、桁上がりしていないので、一時保存をそのまま出力し、バッファ桁上がり回数分11を出力する。
abcabaの符号化について下表に示す。
R拡大 | 入力 | L算出 | low | 出力 | R算出 | range | ||||||||||||
R/総数 | 値 | L+R*入力のL | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 上位2bit | R*入力のR | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
初期値 | 初期値 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 初期値 31 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | ||
31/7=4 | a | 0+4*0=0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 4*3=12 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | |
12/7=1 | b | 0+1*3=3 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1*2=2 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | |
Rを拡大 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 00 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | |||
8/7=1 | c | 12+1*5=17 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1*1=1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | |
Rを拡大 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 00 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | |||
Rを拡大 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 10 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | |||
16/7=2 | a | 16+2*0=16 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 2*3=6 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | |
Rを拡大 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 00 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | |||
24/7=3 | b | 64+3*3=73 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 3*2=6 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | |
Rを拡大 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 10 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | |||
24/7=3 | a | 36+3*0=36 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 3*3=9 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | |
9/7=1 | EOF | 36+1*6=42 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1*1=1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
よって出力符号は出力済み+最終下限値となる。
2進数表記すると00001000100101010となる。
次はこの00001000100101010を復号化する。
頻度表は符号化時と同じである。
区間は[low , low + range)と表せるが、lowをともに減算すれば
区間は[0 , range)とも表せる。
初期のレンジは符号時と同じ31とする。
下限値は符号語の上位7bitを読み込む。
まず、現在のレンジを頻度総数で割り、一個あたりの幅を算出する。
下限値を一個あたりの幅で割り、どの文字の区間に入るか判定する。
入力文字の下限値に一個あたりの幅を掛け、増加した分の下限値を算出し、現在の下限値から減算する。(出力文字の影響排除)
入力文字の頻度に一個あたりの幅を掛け、新たなレンジを算出する。
幅が精度を確保できなくなった場合、レンジ拡大する。
符号化時と同様に2bit左シフトするが、この時lowの下位2bitに符号語の次の2bitを読み込む。
以上を繰り返す。
上で符号化した00001000100101010について復号化を下表に示す。
R拡大 | 区間算出 | 出力 | 入力 | L算出 | low | R算出 | range | ||||||||||||
R/総数 | L/R | 文字 | 2bit | L-R*入力のL | 7 | 6 | 5 | 4 | 3 | 2 | 1 | R*入力のR | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
初期値 | 初期値 7bit | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 初期値 31 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | |||
31/7=4 | 4/4=1 | a | 4-4*0=4 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 4*3=12 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | |
12/7=1 | 4/1=4 | b | 4-1*3=1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1*2=2 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | |
Rを拡大 | 01 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | ||||
8/7=1 | 5/1=5 | c | 5-1*5=0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1*1=1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | |
Rを拡大 | 00 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | ||||
Rを拡大 | 10 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | ||||
16/7=2 | 2/2=1 | a | 2-2*0=2 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 2*3=6 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | |
Rを拡大 | 10 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | ||||
24/7=3 | 10/3=3 | b | 10-3*3=1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 3*2=6 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | |
Rを拡大 | 10 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | ||||
24/7=3 | 6/3=2 | a | 6-3*0=6 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 3*3=9 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | |
9/7=1 | 6/1=6 | EOF |
よってabcabaが復号できた。
(当然であるが)符号化と復号化では幅とレンジ拡大のタイミングがおなじである。