summaryrefslogtreecommitdiffstats
path: root/src/d_huffman.c.jpgdsrc
blob: 7005c915c1ff94e9e98d5a8a6fc46c0533458f3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*-------------------------------------------*/
/* File : huffman.c, utilities for jfif view */
/* Author : Pierre Guerrier, march 1998	     */
/*-------------------------------------------*/

#include <stdlib.h>
#include <stdio.h>


/*--------------------------------------*/
/* private huffman.c defines and macros */
/*--------------------------------------*/

#define HUFF_EOB		0x00
#define HUFF_ZRL		0xF0


#define DC_CLASS        0
#define AC_CLASS        1

/*------------------------------------------*/
/* some constants for on-the-fly IQ and IZZ */
/*------------------------------------------*/

static const int G_ZZ[] = {
   0,  1,  8, 16,  9,  2,  3, 10,
  17, 24, 32, 25, 18, 11,  4,  5,
  12, 19, 26, 33, 40, 48, 41, 34,
  27, 20, 13,  6,  7, 14, 21, 28,
  35, 42, 49, 56, 57, 50, 43, 36,
  29, 22, 15, 23, 30, 37, 44, 51,
  58, 59, 52, 45, 38, 31, 39, 46,
  53, 60, 61, 54, 47, 55, 62, 63
};

/* Memory size of HTables; */
#define MAX_SIZE(hclass)		((hclass)?162:14)

/*--------------------------------------*/
/* some static structures for storage */
/*--------------------------------------*/

static unsigned char	DC_Table0[MAX_SIZE(DC_CLASS)],
			DC_Table1[MAX_SIZE(DC_CLASS)];

static unsigned char	AC_Table0[MAX_SIZE(AC_CLASS)],
			AC_Table1[MAX_SIZE(AC_CLASS)];

static unsigned char   *HTable[4] = {
				      &DC_Table0[0], &DC_Table1[0],
				      &AC_Table0[0], &AC_Table1[0]
				    };

static int	MinCode[4][16];
static int	MaxCode[4][16];
static int	ValPtr[4][16];


typedef union {		/* block of frequency-space values */
  int block[8][8];
  int linear[64];
} FBlock;


/*-----------------------------------*/
/* extract a single symbol from file */
/* using specified huffman table ... */
/*-----------------------------------*/

unsigned char
get_symbol(FILE *fi, int select)
{
  long code = 0;
  int length;
  int index;

  for (length = 0; length < 16; length++) {
    code = (2*code) | get_one_bit(fi);
#ifdef SPY
    trace_bits(1, 0);
#endif
    if (code <= MaxCode[select][length]) break;
  }

  index = ValPtr[select][length] + code - MinCode[select][length];

#ifdef SPY
  trace_bits(0, 0);
#endif

  if (index < MAX_SIZE(select/2)) return HTable[select][index];

  fprintf(stderr, "%ld:\tWARNING:\tOverflowing symbol table !\n", ftell(fi));
  return 0;
}

/*-------------------------------------------------*/
/* here we unpack, predict, unquantify and reorder */
/* a complete 8*8 DCT block ...			   */
/*-------------------------------------------------*/

void
unpack_block(FILE *fi, FBlock *T, int select)
{
  unsigned int i, run, cat;
  int value;
  unsigned char	symbol;

  /* Init the block with 0's: */
  for (i=0; i<64; i++) T->linear[i] = 0;

  /* First get the DC coefficient: */
  symbol = get_symbol(fi, HUFF_ID(DC_CLASS, comp[select].DC_HT));
  value = reformat(get_bits(fi, symbol), symbol);

#ifdef SPY
  trace_bits(symbol, 1);
#endif

  value += comp[select].PRED;
  comp[select].PRED = value;
  T->linear[0] = value * QTable[comp[select].QT]->linear[0];

  /* Now get all 63 AC values: */
  for (i=1; i<64; i++) {
    symbol = get_symbol(fi, HUFF_ID(AC_CLASS, comp[select].AC_HT));
    if (symbol == HUFF_EOB) break;
    if (symbol == HUFF_ZRL) { i += 15; continue; }
    cat = symbol & 0x0F;
    run = (symbol>>4) & 0x0F;
    i += run;
    value = reformat(get_bits(fi, cat), cat);

#ifdef SPY
    trace_bits(cat, 1);
#endif

    /* Dequantify and ZigZag-reorder: */
    T->linear[G_ZZ[i]] = value * QTable[comp[select].QT]->linear[i];
  }
}

int main(void) {
	unpack_block(NULL, NULL, 0);
	return 0;
}