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 */
|