お次はハフマンコードを探す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 BitsとZero Run Lengthのマトリックスの形式で
16bit左詰にしたハフマンコード(上表の4桁16進数)と、
そこから抽出すべきビット数(上表ピンク文字)が並んでいる。
ただし、左端列の(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の時と基本的に同じ。
- つづく -