summaryrefslogtreecommitdiffstats
path: root/src/d_huffman.c
blob: 7431f98b8aef247b65794a49af845a8a2d483c5b (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
#include <stdlib.h>
#include <stdio.h>

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

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

#include "d_huffman.h"


/*
 * Out-of-line code for bit fetching (shared with jdphuff.c).
 * See jdhuff.h for info about usage.
 * Note: current values of get_buffer and bits_left are passed as parameters,
 * but are returned in the corresponding fields of the state struct.
 *
 * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
 * of get_buffer to be used.  (On machines with wider words, an even larger
 * buffer could be used.)  However, on some machines 32-bit shifts are
 * quite slow and take time proportional to the number of places shifted.
 * (This is true with most PC compilers, for instance.)  In this case it may
 * be a win to set MIN_GET_BITS to the minimum value of 15.  This reduces the
 * average shift distance at the cost of more calls to jpeg_fill_bit_buffer.
 */

#ifdef SLOW_SHIFT_32
#define MIN_GET_BITS  15	/* minimum allowable value */
#else
#define MIN_GET_BITS  (BIT_BUF_SIZE-7)
#endif

/* Load up the bit buffer to a depth of at least nbits */
boolean jpeg_fill_bit_buffer(bitread_working_state *state, register bit_buf_type get_buffer, register int bits_left, int nbits) {
	/* Copy heavily used state fields into locals (hopefully registers) */
	register const JOCTET * next_input_byte = state->next_input_byte;
	register size_t bytes_in_buffer = state->bytes_in_buffer;
	j_decompress_ptr cinfo = state->cinfo;

	/* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
	/* (It is assumed that no request will be for more than that many bits.) */
	/* We fail to do so only if we hit a marker or are forced to suspend. */

	if (cinfo->unread_marker == 0) {	/* cannot advance past a marker */
		while (bits_left < MIN_GET_BITS) {
			register int c;

			/* Attempt to read a byte */
			if (bytes_in_buffer == 0) {
				if (! (*cinfo->src->fill_input_buffer) (cinfo)) {
					return FALSE;
				}
				next_input_byte = cinfo->src->next_input_byte;
				bytes_in_buffer = cinfo->src->bytes_in_buffer;
			}
			bytes_in_buffer--;
			c = GETJOCTET(*next_input_byte++);

			/* If it's 0xFF, check and discard stuffed zero byte */
			if (c == 0xFF) {
				/* Loop here to discard any padding FF's on terminating marker,
				 * so that we can save a valid unread_marker value.  NOTE: we will
				 * accept multiple FF's followed by a 0 as meaning a single FF data
				 * byte.  This data pattern is not valid according to the standard.
				 */
				do {
					if (bytes_in_buffer == 0) {
						if (! (*cinfo->src->fill_input_buffer) (cinfo)) {
							return FALSE;
						}
						next_input_byte = cinfo->src->next_input_byte;
						bytes_in_buffer = cinfo->src->bytes_in_buffer;
					}
					bytes_in_buffer--;
					c = GETJOCTET(*next_input_byte++);
				} while (c == 0xFF);

				if (c == 0) {
				/* Found FF/00, which represents an FF data byte */
					c = 0xFF;
				} else {
					/* Oops, it's actually a marker indicating end of compressed data.
					 * Save the marker code for later use.
					 * Fine point: it might appear that we should save the marker into
					 * bitread working state, not straight into permanent state.  But
		 			 * once we have hit a marker, we cannot need to suspend within the
					 * current MCU, because we will read no more bytes from the data
					 * source.  So it is OK to update permanent state right away.
					 */
					cinfo->unread_marker = c;
					/* See if we need to insert some fake zero bits. */
					goto no_more_bytes;
				}
			}

			/* OK, load c into get_buffer */
			get_buffer = (get_buffer << 8) | c;
			bits_left += 8;
		} /* end while */
	} else {
		no_more_bytes:
		/* We get here if we've read the marker that terminates the compressed
		 * data segment.  There should be enough bits in the buffer register
		 * to satisfy the request; if so, no problem.
		 */
		if (nbits > bits_left) {
			/* Uh-oh.  Report corrupted data to user and stuff zeroes into
			 * the data stream, so that we can produce some kind of image.
			 * We use a nonvolatile flag to ensure that only one warning message
			 * appears per data segment.
			 */
			if (!cinfo->entropy->insufficient_data) {
				perror("Corrupt JPEG data: premature end of data segment");
				/* WARNMS(cinfo, JWRN_HIT_MARKER); */
				cinfo->entropy->insufficient_data = TRUE;
			}
			/* Fill the buffer with zero bits */
			get_buffer <<= MIN_GET_BITS - bits_left;
			bits_left = MIN_GET_BITS;
		}
	}

	/* Unload the local registers */
	state->next_input_byte = next_input_byte;
	state->bytes_in_buffer = bytes_in_buffer;
	state->get_buffer = get_buffer;
	state->bits_left = bits_left;

	return TRUE;
}


/*
 * Out-of-line code for Huffman code decoding.
 * See jdhuff.h for info about usage.
 */

int jpeg_huff_decode(bitread_working_state *state, register bit_buf_type get_buffer, register int bits_left, d_derived_tbl *htbl, int min_bits) {
	register int l = min_bits;
	register INT32 code;

	/* HUFF_DECODE has determined that the code is at least min_bits */
	/* bits long, so fetch that many bits in one swoop. */

	CHECK_BIT_BUFFER(*state, l, return -1);
	code = GET_BITS(l);

	/* Collect the rest of the Huffman code one bit at a time. */
	/* This is per Figure F.16 in the JPEG spec. */

	while (code > htbl->maxcode[l]) {
		code <<= 1;
		CHECK_BIT_BUFFER(*state, 1, return -1);
		code |= GET_BITS(1);
		l++;
	}

	/* Unload the local registers */
	state->get_buffer = get_buffer;
	state->bits_left = bits_left;

	/* With garbage input we may reach the sentinel value l = 17. */

	if (l > 16) {
		perror("Corrupt JPEG data: bad Huffman code");
/*		WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); */
		return 0;			/* fake a zero as the safest result */
	}

	return htbl->pub->huffval[ (int)(code + htbl->valoffset[l]) ];
}