summaryrefslogtreecommitdiffstats
path: root/src/c_huffman.c
blob: fceed82319a1c166d9f6f7be631efd4b86398060 (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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
#include <stdlib.h>
#include <stdio.h>

#include "config.h"
#include "morecfg.h"

#include "jpeglib.h"
#include "jpegint.h"

#include "c_huffman.h"

/* Expanded entropy encoder object for Huffman encoding.
 *
 * The savable_state subrecord contains fields that change within an MCU,
 * but must not be updated permanently until we complete the MCU.
 */
typedef struct {
  INT32 put_buffer;		/* current bit-accumulation buffer */
  int put_bits;			/* # of bits now in it */
  int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
} savable_state;

#define ASSIGN_STATE(dest,src)  ((dest) = (src))

typedef struct {
  struct jpeg_entropy_encoder pub; /* public fields */

  savable_state saved;		/* Bit buffer & DC state at start of MCU */

  /* These fields are NOT loaded into local working state. */
  unsigned int restarts_to_go;	/* MCUs left in this restart interval */
  int next_restart_num;		/* next restart number to write (0-7) */

  /* Pointers to derived tables (these workspaces have image lifespan) */
  c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
  c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];

#ifdef ENTROPY_OPT_SUPPORTED	/* Statistics tables for optimization */
  long * dc_count_ptrs[NUM_HUFF_TBLS];
  long * ac_count_ptrs[NUM_HUFF_TBLS];
#endif
} huff_entropy_encoder;

typedef huff_entropy_encoder * huff_entropy_ptr;


/* Working state while writing an MCU.
 * This struct contains all the fields that are needed by subroutines.
 */

typedef struct {
  JOCTET * next_output_byte;	/* => next byte to write in buffer */
  size_t free_in_buffer;	/* # of byte spaces remaining in buffer */
  savable_state cur;		/* Current bit buffer & DC state */
  j_compress_ptr cinfo;		/* dump_buffer needs access to this */
} working_state;


/* Forward declarations */
static boolean encode_mcu_huff JPP((j_compress_ptr cinfo, JBLOCKROW *MCU_data));
static void finish_pass_huff JPP((j_compress_ptr cinfo));

/* Outputting bytes to the file */

/* Emit a byte, taking 'action' if must suspend. */
#define emit_byte(state,val,action)  \
	{ *(state)->next_output_byte++ = (JOCTET) (val);  \
	  if (--(state)->free_in_buffer == 0)  \
	    if (! dump_buffer(state))  \
	      { action; } }


/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
static boolean dump_buffer(working_state * state) {
	struct jpeg_destination_mgr * dest = state->cinfo->dest;

	if (! (*dest->empty_output_buffer) (state->cinfo)) {
		return FALSE;
	}
	/* After a successful buffer dump, must reset buffer pointers */
	state->next_output_byte = dest->next_output_byte;
	state->free_in_buffer = dest->free_in_buffer;
	return TRUE;
}


/* Outputting bits to the file */

/* Only the right 24 bits of put_buffer are used; the valid bits are
 * left-justified in this part.  At most 16 bits can be passed to emit_bits
 * in one call, and we never retain more than 7 bits in put_buffer
 * between calls, so 24 bits are sufficient.
 */

/* Emit some bits; return TRUE if successful, FALSE if must suspend */
inline static boolean emit_bits(working_state * state, unsigned int code, int size) {
	/* This routine is heavily used, so it's worth coding tightly. */
	register INT32 put_buffer = (INT32) code;
	register int put_bits = state->cur.put_bits;

	/* if size is 0, caller used an invalid Huffman table entry */
	if (size == 0) {
		perror("Missing Huffman code table entry");
		exit(0);
		/* ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); */
	}

	put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
  
	put_bits += size;		/* new number of bits in buffer */
  
	put_buffer <<= 24 - put_bits; /* align incoming bits */

	put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */
  
	while (put_bits >= 8) {
		int c = (int) ((put_buffer >> 16) & 0xFF);
    		emit_byte(state, c, return FALSE);
		if (c == 0xFF) {		/* need to stuff a zero byte? */
			emit_byte(state, 0, return FALSE);
		}
		put_buffer <<= 8;
		put_bits -= 8;
	}

	state->cur.put_buffer = put_buffer; /* update state variables */
	state->cur.put_bits = put_bits;

	return TRUE;
}

/*
 * Initialize for a Huffman-compressed scan.
 */

static void start_pass_huff (j_compress_ptr cinfo) {
  huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;

  entropy->pub.encode_mcu = encode_mcu_huff;
  entropy->pub.finish_pass = finish_pass_huff;

  /* Initialize bit buffer to empty */
  entropy->saved.put_buffer = 0;
  entropy->saved.put_bits = 0;

  /* Initialize restart stuff */
  entropy->restarts_to_go = cinfo->restart_interval;
  entropy->next_restart_num = 0;
}

static boolean flush_bits (working_state * state) {
  if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */
    return FALSE;
  state->cur.put_buffer = 0;	/* and reset bit-buffer to empty */
  state->cur.put_bits = 0;
  return TRUE;
}


int encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, c_derived_tbl *dctbl, c_derived_tbl *actbl) {
	register int temp, temp2;
	register int nbits;
	register int k, r, i;

	/* Encode the DC coefficient difference per section F.1.2.1 */

	temp = temp2 = block[0] - last_dc_val;

		if (temp < 0) {
		temp = -temp;		/* temp is abs value of input */
		/* For a negative input, want temp2 = bitwise complement of abs(input) */
		/* This code assumes we are on a two's complement machine */
		temp2--;
	}
  
	/* Find the number of bits needed for the magnitude of the coefficient */
	nbits = 0;
	while (temp) {
		nbits++;
		temp >>= 1;
	}
	/* Check for out-of-range coefficient values.
	 * Since we're encoding a difference, the range limit is twice as much.
	 */
	if (nbits > MAX_COEF_BITS+1) {
		perror("DCT coefficient out of range");
		exit(0);
		/* ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); */
	}
	
	/* Emit the Huffman-coded symbol for the number of bits */
	if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) {
		return FALSE;
	}

	/* Emit that number of bits of the value, if positive, */
	/* or the complement of its magnitude, if negative. */
	if (nbits) {			/* emit_bits rejects calls with size 0 */
		if (! emit_bits(state, (unsigned int) temp2, nbits)) {
			return FALSE;
		}
	}

	/* Encode the AC coefficients per section F.1.2.2 */
  
	r = 0;			/* r = run length of zeros */
  
	for (k = 1; k < DCTSIZE2; k++) {
		if ((temp = block[jpeg_natural_order[k]]) == 0) {
			r++;
		} else {
			/* if run length > 15, must emit special run-length-16 codes (0xF0) */
			while (r > 15) {
				if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) {
					return FALSE;
				}
				r -= 16;
			}
			
			temp2 = temp;
			if (temp < 0) {
				temp = -temp;		/* temp is abs value of input */
				/* This code assumes we are on a two's complement machine */
				temp2--;
			}
      
			/* Find the number of bits needed for the magnitude of the coefficient */
			nbits = 1;		/* there must be at least one 1 bit */
			while ((temp >>= 1)) {
				nbits++;
			}
			/* Check for out-of-range coefficient values */
			if (nbits > MAX_COEF_BITS) {
				perror("DCT coefficient out of range");
				exit(0);
				/* ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); */
			}
      
			/* Emit Huffman symbol for run length / number of bits */
			i = (r << 4) + nbits;
			if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) {
				return FALSE;
			}

			/* Emit that number of bits of the value, if positive, */
			/* or the complement of its magnitude, if negative. */
			if (! emit_bits(state, (unsigned int) temp2, nbits)) {
				return FALSE;
			}
      
			r = 0;
		}
	}

	/* If the last coef(s) were zero, emit an end-of-block code */
	if (r > 0) {
		if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) {
		      return FALSE;
		}
	}
	return TRUE;
}

/*
 * Emit a restart marker & resynchronize predictions.
 */

static boolean emit_restart (working_state * state, int restart_num) {
  int ci;

  if (! flush_bits(state))
    return FALSE;

  emit_byte(state, 0xFF, return FALSE);
  emit_byte(state, JPEG_RST0 + restart_num, return FALSE);

  /* Re-initialize DC predictions to 0 */
  for (ci = 0; ci < state->cinfo->comps_in_scan; ci++)
    state->cur.last_dc_val[ci] = 0;

  /* The restart counter is not updated until we successfully write the MCU. */

  return TRUE;
}


/*
 * Encode and output one MCU's worth of Huffman-compressed coefficients.
 */

static boolean encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) {
  huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
  working_state state;
  int blkn, ci;
  jpeg_component_info * compptr;

  /* Load up working state */
  state.next_output_byte = cinfo->dest->next_output_byte;
  state.free_in_buffer = cinfo->dest->free_in_buffer;
  ASSIGN_STATE(state.cur, entropy->saved);
  state.cinfo = cinfo;

  /* Emit restart marker if needed */
  if (cinfo->restart_interval) {
    if (entropy->restarts_to_go == 0)
      if (! emit_restart(&state, entropy->next_restart_num))
	return FALSE;
  }

  /* Encode the MCU data blocks */
  for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
    ci = cinfo->MCU_membership[blkn];
    compptr = cinfo->cur_comp_info[ci];
    if (! encode_one_block(&state,
			   MCU_data[blkn][0], state.cur.last_dc_val[ci],
			   entropy->dc_derived_tbls[compptr->dc_tbl_no],
			   entropy->ac_derived_tbls[compptr->ac_tbl_no]))
      return FALSE;
    /* Update last_dc_val */
    state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
  }

  /* Completed MCU, so update state */
  cinfo->dest->next_output_byte = state.next_output_byte;
  cinfo->dest->free_in_buffer = state.free_in_buffer;
  ASSIGN_STATE(entropy->saved, state.cur);

  /* Update restart-interval state too */
  if (cinfo->restart_interval) {
    if (entropy->restarts_to_go == 0) {
      entropy->restarts_to_go = cinfo->restart_interval;
      entropy->next_restart_num++;
      entropy->next_restart_num &= 7;
    }
    entropy->restarts_to_go--;
  }

  return TRUE;
}


/*
 * Finish up at the end of a Huffman-compressed scan.
 */

static void finish_pass_huff (j_compress_ptr cinfo) {
  huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
  working_state state;

  /* Load up working state ... flush_bits needs it */
  state.next_output_byte = cinfo->dest->next_output_byte;
  state.free_in_buffer = cinfo->dest->free_in_buffer;
  ASSIGN_STATE(state.cur, entropy->saved);
  state.cinfo = cinfo;

  /* Flush out the last data */
  if (! flush_bits(&state))
    perror("Suspension not allowed here");
    exit(0);
    /* ERREXIT(cinfo, JERR_CANT_SUSPEND); */

  /* Update state */
  cinfo->dest->next_output_byte = state.next_output_byte;
  cinfo->dest->free_in_buffer = state.free_in_buffer;
  ASSIGN_STATE(entropy->saved, state.cur);
}


/*
 * Module initialization routine for Huffman entropy encoding.
 */

void jinit_huff_encoder(j_compress_ptr cinfo) {
  huff_entropy_ptr entropy;
  int i;

  entropy = (huff_entropy_ptr) malloc((size_t) sizeof(huff_entropy_encoder));

  cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
  entropy->pub.start_pass = start_pass_huff;

  /* Mark tables unallocated */
  for (i = 0; i < NUM_HUFF_TBLS; i++) {
    entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
#ifdef ENTROPY_OPT_SUPPORTED
    entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL;
#endif
  }
}