File: jdlhuff.c

package info (click to toggle)
dcmtk 3.6.0-12
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 32,976 kB
  • sloc: cpp: 193,852; ansic: 46,292; sh: 4,020; makefile: 3,969; perl: 3,278; lex: 94
file content (291 lines) | stat: -rw-r--r-- 9,658 bytes parent folder | download | duplicates (7)
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
/*
 * jdlhuff.c
 *
 * Copyright (C) 1991-1998, Thomas G. Lane.
 * This file is part of the Independent JPEG Group's software.
 * For conditions of distribution and use, see the accompanying README file.
 *
 * This file contains Huffman entropy decoding routines for lossless JPEG.
 *
 * Much of the complexity here has to do with supporting input suspension.
 * If the data source module demands suspension, we want to be able to back
 * up to the start of the current MCU.  To do this, we copy state variables
 * into local working storage, and update them back to the permanent
 * storage only upon successful completion of an MCU.
 */

#define JPEG_INTERNALS
#include "jinclude8.h"
#include "jpeglib8.h"
#include "jlossls8.h"		/* Private declarations for lossless codec */
#include "jdhuff8.h"		/* Declarations shared with jd*huff.c */


#ifdef D_LOSSLESS_SUPPORTED

typedef struct {
  int ci, yoffset, MCU_width;
} lhd_output_ptr_info;

/*
 * Private entropy decoder object for lossless Huffman decoding.
 */

typedef struct {
  huffd_common_fields;		/* Fields shared with other entropy decoders */

  /* Pointers to derived tables (these workspaces have image lifespan) */
  d_derived_tbl * derived_tbls[NUM_HUFF_TBLS];

  /* Precalculated info set up by start_pass for use in decode_mcus: */

  /* Pointers to derived tables to be used for each data unit within an MCU */
  d_derived_tbl * cur_tbls[D_MAX_DATA_UNITS_IN_MCU];

  /* Pointers to the proper output difference row for each group of data units
   * within an MCU.  For each component, there are Vi groups of Hi data units.
   */
  JDIFFROW output_ptr[D_MAX_DATA_UNITS_IN_MCU];

  /* Number of output pointers in use for the current MCU.  This is the sum
   * of all Vi in the MCU.
   */
  int num_output_ptrs;

  /* Information used for positioning the output pointers within the output
   * difference rows.
   */
  lhd_output_ptr_info output_ptr_info[D_MAX_DATA_UNITS_IN_MCU];

  /* Index of the proper output pointer for each data unit within an MCU */
  int output_ptr_index[D_MAX_DATA_UNITS_IN_MCU];

} lhuff_entropy_decoder;

typedef lhuff_entropy_decoder * lhuff_entropy_ptr;


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

METHODDEF(void)
start_pass_lhuff_decoder (j_decompress_ptr cinfo)
{
  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
  int ci, dctbl, sampn, ptrn, yoffset, xoffset;
  jpeg_component_info * compptr;

  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
    compptr = cinfo->cur_comp_info[ci];
    dctbl = compptr->dc_tbl_no;
    /* Make sure requested tables are present */
    if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS ||
	cinfo->dc_huff_tbl_ptrs[dctbl] == NULL)
      ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
    /* Compute derived values for Huffman tables */
    /* We may do this more than once for a table, but it's not expensive */
    jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl,
			    & entropy->derived_tbls[dctbl]);
  }

  /* Precalculate decoding info for each sample in an MCU of this scan */
  for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) {
    compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]];
    ci = compptr->component_index;
    for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) {
      /* Precalculate the setup info for each output pointer */
      entropy->output_ptr_info[ptrn].ci = ci;
      entropy->output_ptr_info[ptrn].yoffset = yoffset;
      entropy->output_ptr_info[ptrn].MCU_width = compptr->MCU_width;
      for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) {
	/* Precalculate the output pointer index for each sample */
	entropy->output_ptr_index[sampn] = ptrn;
	/* Precalculate which table to use for each sample */
	entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no];
      }
    }
  }
  entropy->num_output_ptrs = ptrn;

  /* Initialize bitread state variables */
  entropy->bitstate.bits_left = 0;
  entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
  entropy->insufficient_data = FALSE;
}


/*
 * Figure F.12: extend sign bit.
 * On some machines, a shift and add will be faster than a table lookup.
 */

#ifdef AVOID_TABLES

#define HUFF_EXTEND(x,s)  ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))

#else

#define HUFF_EXTEND(x,s)  ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))

static const int extend_test[16] =   /* entry n is 2**(n-1) */
  { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
    0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };

static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
  { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
    ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
    ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
    ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };

#endif /* AVOID_TABLES */


/*
 * Check for a restart marker & resynchronize decoder.
 * Returns FALSE if must suspend.
 */

METHODDEF(boolean)
process_restart (j_decompress_ptr cinfo)
{
  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
  /* int ci; */

  /* Throw away any unused bits remaining in bit buffer; */
  /* include any full bytes in next_marker's count of discarded bytes */
  cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
  entropy->bitstate.bits_left = 0;

  /* Advance past the RSTn marker */
  if (! (*cinfo->marker->read_restart_marker) (cinfo))
    return FALSE;

  /* Reset out-of-data flag, unless read_restart_marker left us smack up
   * against a marker.  In that case we will end up treating the next data
   * segment as empty, and we can avoid producing bogus output pixels by
   * leaving the flag set.
   */
  if (cinfo->unread_marker == 0)
    entropy->insufficient_data = FALSE;

  return TRUE;
}


/*
 * Decode and return nMCU's worth of Huffman-compressed differences.
 * Each MCU is also disassembled and placed accordingly in diff_buf.
 *
 * MCU_col_num specifies the column of the first MCU being requested within
 * the MCU-row.  This tells us where to position the output row pointers in
 * diff_buf.
 *
 * Returns the number of MCUs decoded.  This may be less than nMCU if data
 * source requested suspension.  In that case no changes have been made to
 * permanent state.  (Exception: some output differences may already have
 * been assigned.  This is harmless for this module, since we'll just
 * re-assign them on the next call.)
 */

METHODDEF(JDIMENSION)
decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf,
	     JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU)
{
  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
  unsigned int mcu_num;
  int sampn, ci, yoffset, MCU_width, ptrn;
  BITREAD_STATE_VARS;

  /* Set output pointer locations based on MCU_col_num */
  for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) {
    ci = entropy->output_ptr_info[ptrn].ci;
    yoffset = entropy->output_ptr_info[ptrn].yoffset;
    MCU_width = entropy->output_ptr_info[ptrn].MCU_width;
    entropy->output_ptr[ptrn] =
      diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width);
  }

  /*
   * If we've run out of data, zero out the buffers and return.
   * By resetting the undifferencer, the output samples will be CENTERJSAMPLE.
   *
   * NB: We should find a way to do this without interacting with the
   * undifferencer module directly.
   */
  if (entropy->insufficient_data) {
    for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++)
      jzero_far((void FAR *) entropy->output_ptr[ptrn],
		nMCU * entropy->output_ptr_info[ptrn].MCU_width * SIZEOF(JDIFF));

    (*losslsd->predict_process_restart) (cinfo);
  }

  else {

    /* Load up working state */
    BITREAD_LOAD_STATE(cinfo,entropy->bitstate);

    /* Outer loop handles the number of MCU requested */

    for (mcu_num = 0; mcu_num < nMCU; mcu_num++) {

      /* Inner loop handles the samples in the MCU */
      for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) {
	d_derived_tbl * dctbl = entropy->cur_tbls[sampn];
	register int s, r;

	/* Section H.2.2: decode the sample difference */
	HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1);
	if (s) {
	  if (s == 16)	/* special case: always output 32768 */
	    s = 32768;
	  else {	/* normal case: fetch subsequent bits */
	    CHECK_BIT_BUFFER(br_state, s, return mcu_num);
	    r = GET_BITS(s);
	    s = HUFF_EXTEND(r, s);
	  }
	}

	/* Output the sample difference */
	*entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF) s;
      }

      /* Completed MCU, so update state */
      BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
    }
  }

 return nMCU;
}


/*
 * Module initialization routine for lossless Huffman entropy decoding.
 */

GLOBAL(void)
jinit_lhuff_decoder (j_decompress_ptr cinfo)
{
  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
  lhuff_entropy_ptr entropy;
  int i;

  entropy = (lhuff_entropy_ptr)
    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
				SIZEOF(lhuff_entropy_decoder));
  losslsd->entropy_private = (void *) entropy;
  losslsd->entropy_start_pass = start_pass_lhuff_decoder;
  losslsd->entropy_process_restart = process_restart;
  losslsd->entropy_decode_mcus = decode_mcus;

  /* Mark tables unallocated */
  for (i = 0; i < NUM_HUFF_TBLS; i++) {
    entropy->derived_tbls[i] = NULL;
  }
}

#endif /* D_LOSSLESS_SUPPORTED */