All-About調査室 Annex

ふと湧いた疑問や巷を漂うウワサを全部アバウト~に調査・検証
<OCNから漂着 流浪の調査室>

ハフマン変換をLUTにする

2018-03-31 22:43:22 | 4:4:4 Jpeg保存dll作成

さて、何か値が与えられた時に、
その値の2進表現の何桁が有効桁かを判断したり、
対応するハフマンコードをその都度ツリーを辿って探し出したり、
そもそも与えられた値が負だったら1の補数表現に直したり・・・
なんてコトをイチイチ処理していたら時間がかかる。
日の短い時分には日が暮れちまう、温気の時分には腐っちまうので
これらの変換の対応を取ったルックアップ・テーブル(LUT)を作ってしまおう。

なお、LUTに作るべきデータは本来なら可変ビット長なのだが、
さすがに可変ビット長では扱いようがない。
で、一旦16bitデータ形式の中に可変ビットデータを「左寄せ」で詰め込み
開いた右側はゼロで埋めたものを16進数表現で羅列したtxtファイルと、
その16bitデータ中の何bitを左から取り出すかの数値を羅列したtxtファイルを作る。

例によって、例のごとくExcel VBAを使って・・・
まずはデータ値を可変ビットに変換するLUT(負の場合は1の補数表現に直す)。

Sub DataBitsToFile()
    Dim DB, N As Integer
    Dim Data(4094) As String
    Dim Num(4094) As Integer
    DataFile$ = "E:\DB_Data.txt" ' 変換データのファイル
    NumFile$ = "E:\DB_Num.txt"   ' 有効Bit数のファイル

    For N = -2047 To 2047
        If N < 0 Then
            DB = -N
            Data(N + 2047) = Right("0000000000000000" _
                & Application.WorksheetFunction.Dec2Bin(Not (DB \ 256)) _
                & Right("00000000" _
                & Application.WorksheetFunction.Dec2Bin(Not (DB Mod 256)), 8), 16)
        Else
            DB = N
            Data(N + 2047) = Right("0000000000000000" _
                & Application.WorksheetFunction.Dec2Bin(DB \ 256) _
                & Right("00000000" _
                & Application.WorksheetFunction.Dec2Bin(DB Mod 256), 8), 16)
        End If

        If N = 0 Then
            Num(2047) = 0
        Else
            Num(N + 2047) = Int(0.0001 + Log(DB) / Log(2)) + 1
        End If

        Data(N + 2047) = Left(Right(Data(N + 2047), Num(N + 2047)) _
            & "0000000000000000", 16)
        Data(N + 2047) = Application.WorksheetFunction.Bin2Hex(Left(Data(N + 2047), 4)) _
            & Application.WorksheetFunction.Bin2Hex(Mid(Data(N + 2047), 5, 4)) _
            & Application.WorksheetFunction.Bin2Hex(Mid(Data(N + 2047), 9, 4)) _
            & Application.WorksheetFunction.Bin2Hex(Mid(Data(N + 2047), 13, 4))
    Next N

    Open DataFile$ For Output As #1
    For N = 0 To 4094
        If N Mod 8 <> 7 Then
            Print #1, "0x" & Data(N) & ", ";
        Else
            Print #1, "0x" & Data(N) & ", "
        End If
    Next N
    Close #1

    Open NumFile$ For Output As #2
    For N = 0 To 4094
        If N Mod 16 <> 15 Then
            Print #2, Num(N) & ", ";
        Else
            Print #2, Num(N) & ", "
        End If
    Next N
    Close #2
End Sub

を実行すると、中身が

0x0000, 0x0020, 0x0040,・・・(大幅に中略)・・・, 0xFFA0, 0xFFC0, 0xFFE0,



11, 11, 11, ・・・(これまた大幅に中略)・・・, 11, 11, 11,


となっている2つのtxtファイルが出来上がる。

双方とも一番最後の「,」(コンマ)はいらないのでテキストエディタで削除する。
いずれも-2047~+2047範囲のデータに対応するものになっている。

なお、ゼロ値は「値0x0000」で「bit0」として記述している。
データ値ゼロは前回述べたようにJpegハフマンでは記述しないが
処理を統一するためこのようにしておく。

コレをソースファイルのInitialize Variable Arrayセクションにコピペして

static unsigned short L_Dc[4095] = {
    // LUT for Data Code -2047~+2047

    0x0000, 0x0020, 0x0040,・・・(大幅に中略)・・・, 0xFFA0, 0xFFC0, 0xFFE0
};



static char L_Db[4095] = {
    // LUT for Data Bits -2047~+2047

    11, 11, 11, ・・・(これまた大幅に中略)・・・, 11, 11, 11
};

・・・とでもして配列に初期化する。

これでデータ値Nをハフマン変換処理用の可変ビット長変換したビット列は
L_Dc[N]の16bitのビット列の左からL_Db[N]個のビットを抜き出せば良い。
(厳密には、データ範囲は-2047~+2047なのでNを+2047オフセットさせて
配列から取り出す)

- つづく -



最新の画像もっと見る

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。