1
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
2
/// Under the MIT License, details: License.txt.
4
// Partially derives from a Java encoder, JpegEncoder.java by James R Weeks.
5
// Implements Baseline JPEG Encoding http://www.opennet.ru/docs/formats/jpeg.txt
9
using FluxJpeg.Core.IO;
11
using System.Collections.Generic;
13
namespace FluxJpeg.Core
15
internal class HuffmanTable
17
public static int HUFFMAN_MAX_TABLES = 4;
19
private short[] huffcode = new short[256];
20
private short[] huffsize = new short[256];
21
private short[] valptr = new short[16];
22
private short[] mincode = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1,-1};
23
private short[] maxcode = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
25
private short[] huffval;
28
int bufferPutBits, bufferPutBuffer;
29
internal int ImageHeight;
30
internal int ImageWidth;
31
internal int[,] DC_matrix0;
32
internal int[,] AC_matrix0;
33
internal int[,] DC_matrix1;
34
internal int[,] AC_matrix1;
35
internal int[][,] DC_matrix;
36
internal int[][,] AC_matrix;
37
internal int NumOfDCTables;
38
internal int NumOfACTables;
40
public List<short[]> bitsList;
41
public List<short[]> val;
44
public static byte JPEG_DC_TABLE = 0;
45
public static byte JPEG_AC_TABLE = 1;
47
private short lastk = 0;
49
internal HuffmanTable(JpegHuffmanTable table)
53
huffval = table.Values;
58
GenerateDecoderTables();
62
// Encode initialization
64
bitsList = new List<short[]>();
65
bitsList.Add(JpegHuffmanTable.StdDCLuminance.Lengths);
66
bitsList.Add(JpegHuffmanTable.StdACLuminance.Lengths);
67
bitsList.Add(JpegHuffmanTable.StdDCChrominance.Lengths);
68
bitsList.Add(JpegHuffmanTable.StdACChrominance.Lengths);
70
val = new List<short[]>();
71
val.Add(JpegHuffmanTable.StdDCLuminance.Values);
72
val.Add(JpegHuffmanTable.StdACLuminance.Values);
73
val.Add(JpegHuffmanTable.StdDCChrominance.Values);
74
val.Add(JpegHuffmanTable.StdACChrominance.Values);
80
/// <summary>See Figure C.1</summary>
81
private void GenerateSizeTable()
84
for (short i = 0; i < bits.Length; i++)
86
for (short j = 0; j < bits[i]; j++)
88
huffsize[index] = (short)(i + 1);
95
/// <summary>See Figure C.2</summary>
96
private void GenerateCodeTable()
99
short si = huffsize[0];
101
for (short i = 0; i < huffsize.Length; i++)
103
while (huffsize[k] == si)
114
/// <summary>See figure F.15</summary>
115
private void GenerateDecoderTables()
118
for (int i = 0; i < 16; i++)
121
valptr[i] = bitcount;
122
for (int j = 0; j < bits[i]; j++)
124
if (huffcode[j + bitcount] < mincode[i] || mincode[i] == -1)
125
mincode[i] = huffcode[j + bitcount];
127
if (huffcode[j + bitcount] > maxcode[i])
128
maxcode[i] = huffcode[j + bitcount];
130
if (mincode[i] != -1)
131
valptr[i] = (short)(valptr[i] - mincode[i]);
136
/// <summary>Figure F.12</summary>
137
public static int Extend(int diff, int t)
139
// here we use bitshift to implement 2^ ...
140
// NOTE: Math.Pow returns 0 for negative powers, which occassionally happen here!
143
// WAS: int Vt = (int)Math.Pow(2, (t - 1));
153
/// <summary>Figure F.16 - Reads the huffman code bit-by-bit.</summary>
154
/*public int Decode(JPEGBinaryReader JPEGStream)
157
short code = (short)JPEGStream.ReadBits(1);
158
while (code > maxcode[i])
162
code |= (short)JPEGStream.ReadBits(1);
164
int val = huffval[code + (valptr[i])];
171
/// HuffmanBlockEncoder run length encodes and Huffman encodes the quantized data.
173
internal void HuffmanBlockEncoder(Stream outStream, int[] zigzag, int prec, int DCcode, int ACcode)
175
int temp, temp2, nbits, k, r, i;
182
temp = temp2 = zigzag[0] - prec;
194
// if (nbits > 11) nbits = 11;
196
DC_matrix[DCcode][nbits, 0],
197
DC_matrix[DCcode][nbits, 1]);
199
// The arguments in bufferIt are code and size.
202
bufferIt(outStream, temp2, nbits);
209
for (k = 1; k < 64; k++)
211
if ((temp = zigzag[ ZigZag.ZigZagMap[k] ]) == 0)
220
AC_matrix[ACcode][0xF0, 0],
221
AC_matrix[ACcode][0xF0, 1]);
232
while ((temp >>= 1) != 0)
236
i = (r << 4) + nbits;
238
AC_matrix[ACcode][i, 0],
239
AC_matrix[ACcode][i, 1]);
240
bufferIt(outStream, temp2, nbits);
249
AC_matrix[ACcode][0, 0],
250
AC_matrix[ACcode][0, 1]);
255
/// Uses an integer long (32 bits) buffer to store the Huffman encoded bits
256
/// and sends them to outStream by the byte.
258
void bufferIt(Stream outStream, int code, int size)
260
int PutBuffer = code;
261
int PutBits = bufferPutBits;
263
PutBuffer &= (1 << size) - 1;
265
PutBuffer <<= 24 - PutBits;
266
PutBuffer |= bufferPutBuffer;
270
int c = ((PutBuffer >> 16) & 0xFF);
271
outStream.WriteByte((byte)c);
273
// FF must be escaped
274
if (c == 0xFF) outStream.WriteByte(0);
279
bufferPutBuffer = PutBuffer;
280
bufferPutBits = PutBits;
284
public void FlushBuffer(Stream outStream)
286
int PutBuffer = bufferPutBuffer;
287
int PutBits = bufferPutBits;
290
int c = ((PutBuffer >> 16) & 0xFF);
291
outStream.WriteByte((byte)c);
293
// FF must be escaped
294
if (c == 0xFF) outStream.WriteByte(0);
301
int c = ((PutBuffer >> 16) & 0xFF);
302
outStream.WriteByte((byte)c);
308
/// Initialisation of the Huffman codes for Luminance and Chrominance.
309
/// This code results in the same tables created in the IJG Jpeg-6a
312
public void initHuf()
314
DC_matrix0 = new int[12, 2];
315
DC_matrix1 = new int[12, 2];
316
AC_matrix0 = new int[255, 2];
317
AC_matrix1 = new int[255, 2];
318
DC_matrix = new int[2][,];
319
AC_matrix = new int[2][,];
320
int p, l, i, lastp, si, code;
321
int[] huffsize = new int[257];
322
int[] huffcode = new int[257];
324
short[] bitsDCchrominance = JpegHuffmanTable.StdDCChrominance.Lengths;
325
short[] bitsACchrominance = JpegHuffmanTable.StdACChrominance.Lengths;
326
short[] bitsDCluminance = JpegHuffmanTable.StdDCLuminance.Lengths;
327
short[] bitsACluminance = JpegHuffmanTable.StdACLuminance.Lengths;
330
short[] valDCchrominance = JpegHuffmanTable.StdDCChrominance.Values;
331
short[] valACchrominance = JpegHuffmanTable.StdACChrominance.Values;
332
short[] valDCluminance = JpegHuffmanTable.StdDCLuminance.Values;
333
short[] valACluminance = JpegHuffmanTable.StdACLuminance.Values;
337
* init of the DC values for the chrominance
338
* [,0] is the code [,1] is the number of bit
342
for (l = 0; l < 16; l++)
344
for (i = 1; i <= bitsDCchrominance[l]; i++)
356
while (huffsize[p] != 0)
358
while (huffsize[p] == si)
360
huffcode[p++] = code;
367
for (p = 0; p < lastp; p++)
369
DC_matrix1[valDCchrominance[p], 0] = huffcode[p];
370
DC_matrix1[valDCchrominance[p], 1] = huffsize[p];
374
* Init of the AC hufmann code for the chrominance
375
* matrix [,,0] is the code & matrix[,,1] is the number of bit needed
379
for (l = 0; l < 16; l++)
381
for (i = 1; i <= bitsACchrominance[l]; i++)
392
while (huffsize[p] != 0)
394
while (huffsize[p] == si)
396
huffcode[p++] = code;
403
for (p = 0; p < lastp; p++)
405
AC_matrix1[valACchrominance[p], 0] = huffcode[p];
406
AC_matrix1[valACchrominance[p], 1] = huffsize[p];
410
* init of the DC values for the luminance
411
* [,0] is the code [,1] is the number of bit
414
for (l = 0; l < 16; l++)
416
for (i = 1; i <= bitsDCluminance[l]; i++)
427
while (huffsize[p] != 0)
429
while (huffsize[p] == si)
431
huffcode[p++] = code;
438
for (p = 0; p < lastp; p++)
440
DC_matrix0[valDCluminance[p], 0] = huffcode[p];
441
DC_matrix0[valDCluminance[p], 1] = huffsize[p];
445
* Init of the AC hufmann code for luminance
446
* matrix [,,0] is the code & matrix[,,1] is the number of bit
450
for (l = 0; l < 16; l++)
452
for (i = 1; i <= bitsACluminance[l]; i++)
463
while (huffsize[p] != 0)
465
while (huffsize[p] == si)
467
huffcode[p++] = code;
473
for (int q = 0; q < lastp; q++)
475
AC_matrix0[valACluminance[q], 0] = huffcode[q];
476
AC_matrix0[valACluminance[q], 1] = huffsize[q];
479
DC_matrix[0] = DC_matrix0;
480
DC_matrix[1] = DC_matrix1;
481
AC_matrix[0] = AC_matrix0;
482
AC_matrix[1] = AC_matrix1;