All-About調査室 Annex

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

ハフマン変換をLUTにする の続き

2018-04-01 23:59:51 | 4:4:4 Jpeg保存dll作成

お次はハフマンコードを探すLUTで、
前回同様に可変ビット長データを左寄せ16bitにして
16進表現したファイルと
取り出すbit数を記述したファイルを
Jpegヘッダの雛形を作成した時に確保しておいた
DC用とAC用のDHTのデータファイルを利用して作る。

まずはDC成分から
Excel VBAで


'構造体定義
Private Type DHT_Head    'DHT Segヘッダ
    ID(1) As Byte
    Length(1) As Byte
    Type As Byte
End Type

'---------------------------------------
Sub HuffToFile()

    Dim DHT_Spec As DHT_Head
    Dim D_Bits() As Byte
    Dim H_Bits(15) As Byte
    Dim HV As Long
    Dim K, M, N, K_Huff As Integer
    Dim ZRL, DB As Integer
    Dim Huffman() As String
    Dim HuffmanCB() As Integer
    Dim Temp As String

    DHT_File$ = "E:\DHT_DC.dat"   ' DC用DHTファイルを指定
'   DHT_File$ = "E:\DHT_AC.dat"   ' AC用DHTファイルを指定

    Open DHT_File$ For Binary As #1
    Get #1, , DHT_Spec
    If DHT_Spec.ID(0) <> 255 Or DHT_Spec.ID(1) <> 196 Then
        MsgBox "Not DHT"
        Exit Sub
    End If
    If DHT_Spec.Type < 16 Then
        D_Type$ = "DC"
    Else
        D_Type$ = "AC"
    End If
    MsgBox D_Type$ & " #" & (DHT_Spec.Type Mod 16)
    Get #1, , H_Bits()
    K_Huff = DHT_Spec.Length(0) * 256 + DHT_Spec.Length(1) – 20
    ReDim D_Bits(K_Huff)
    Get #1, , D_Bits()
    Close #1

    ZRL = 0
    DB = 0
    For N = 0 To K_Huff
        If D_Bits(N) \ 16 > ZRL Then ZRL = D_Bits(N) \ 16
        If D_Bits(N) Mod 16 > DB Then DB = D_Bits(N) Mod 16
    Next N
    ReDim Huffman(DB, ZRL)
    ReDim HuffmanCB(DB, ZRL)

    M = 0
    HV = 0
    For N = 0 To 15
        K = H_Bits(N)
        While K > 0
            Temp = Right("000000000000000" _
                & Application.WorksheetFunction.Dec2Bin(HV \ 256) _
                & Application.WorksheetFunction.Dec2Bin(HV Mod 256), N + 1)
            Temp = Left(Temp & "000000000000000", 16)
            Temp = Application.WorksheetFunction.Bin2Hex(Left(Temp, 4)) _
                & Application.WorksheetFunction.Bin2Hex(Mid(Temp, 5, 4)) _
                & Application.WorksheetFunction.Bin2Hex(Mid(Temp, 9, 4)) _
                & Application.WorksheetFunction.Bin2Hex(Right(Temp, 4))
            Huffman(D_Bits(M) Mod 16, D_Bits(M) \ 16) = Temp
            HuffmanCB(D_Bits(M) Mod 16, D_Bits(M) \ 16) = N + 1
            HV = HV + 1
            M = M + 1
            K = K – 1
        Wend
        HV = HV * 2
    Next N

    Open "E:\HuffTBL_" & D_Type$ & ".txt" For Output As #1   'ハフマンコードのFile
    Open "E:\HuffBits_" & D_Type$ & ".txt" For Output As #2  '有効bit数のFile
    For M = 0 To ZRL
        For N = 0 To DB
            If N = 0 And 0 < M And M < ZRL Then
                Print #1, "0x0000, ";
                Print #2, "0, ";
            ElseIf N <> DB Then
                Print #1, "0x" & Huffman(N, M) & ", ";
                Print #2, HuffmanCB(N, M) & ", ";
            Else
                Print #1, "0x" & Huffman(N, M) & ", "
                Print #2, HuffmanCB(N, M) & ", "
            End If
        Next N
    Next M
    Close #1
    Close #2

End Sub


を実行すると、中身が

0x0000, 0x4000, 0x6000,・・・(中略)・・・, 0xFC00, 0xFE00, 0xFF00,



2, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9,


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

やはり、双方とも一番最後の「,」(コンマ)はいらないのでエディタで削除する。

これらファイルの意味合いをまとめると、こんなカンジ



それぞれのファイルには上表のHexとEffective BitsがData Bits順に並んでいるので
これらをInitialize Variable Arrayセクションに

static unsigned short L_DCc[12] = {
    //LUT for DC Huffman Code

    0x0000, 0x4000, 0x6000, 0x8000,
    0xA000, 0xC000, 0xE000, 0xF000,
    0xF800, 0xFC00, 0xFE00, 0xFF00
};



static char L_DCb[12] = {
    // LUT for DC Huffman Bits

    2, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9
};

としてソースにコピペして、配列に初期化する。
コレによりデータ値NのDCハフマンコードは
まずL_Db[N]によりデータのビット長を得て、
それをL_DCcやL_DCbに適用することで得る。
つまりL_DCc[L_Db[N]]のビット列の左からL_DCb[L_Db[N]]個抽出する。


AC成分はDCと同じVBAプログラムで

    DHT_File$ = "E:\DHT_DC.dat"   ' DC用DHTファイルを指定
'   DHT_File$ = "E:\DHT_AC.dat"   ' AC用DHTファイルを指定

の部分のコメントアウト行を相互に切り替えて

入力ファイル指定をAC用DHTファイルに指定して実行すれば、
中身が

0xA000, 0x0000, 0x4000,・・・(かなり中略)・・・, 0xFFFC, 0xFFFD, 0xFFFE,



4, 2, 2, 3, ・・・(かなり中略)・・・, 16, 16, 16, 16,


となっている2つのtxtファイルが得られる。

双方とも一番最後の「,」(コンマ)を先と同様に削除する。

これらファイルの意味合いは



のように、Data BitsZero Run Lengthのマトリックスの形式で
16bit
左詰にしたハフマンコード(上表の416進数)と、
そこから抽出すべきビット数(上表ピンク文字)が並んでいる。
ただし、左端列の(DB,ZRL)=(0,1)(0,14)はハフマン変換に使用しない部分なので
上表では空欄にしているが、
ファイル上にはコード0x0000、抽出ビット数0が入っている。
コレはLUTとして配列に初期化するためのダミー値である。
なお(DB,ZRL)=(0,0)EOB(DB,ZRL)=(0,15)ZRLに相当する。

やはりコピペでInitialize Variable Arrayセクションに

static unsigned short L_ACc[16][11] = {
    //LUT for AC Huffman Code [ZeroRunLength] [DataBits]
    0xA000, 0x0000, 0x4000,
・・・(かなり中略)・・・, 0xFFFC, 0xFFFD, 0xFFFE
};



static char L_ACb[16][11] = {
    //AC Huffman Bits [ZeroRunLength] [DataBits]
    4, 2, 2, 3,
・・・(かなり中略)・・・, 16, 16, 16, 16
};

を作る。

使い方はカウントしたゼロ・ランレングス値もLUT検索に使うほかは
DC
の時と基本的に同じ。

- つづく -



最新の画像もっと見る

コメントを投稿

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