/*
 * jdhuff.c
 *
 * Copyright (C) 1991, 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.
 * These routines are invoked via the methods entropy_decode
 * and entropy_decoder_init/term.
 */

#include "jinclude.h"


/* Static variables to avoid passing 'round extra parameters */

static decompress_info_ptr dcinfo;

static INT32 get_buffer;	/* current bit-extraction buffer */
static int bits_left;		/* # of unused bits in it */


LOCAL void
fix_huff_tbl (HUFF_TBL * htbl)
/* Compute derived values for a Huffman table */
{
  int p, i, l, lastp, si;
  char huffsize[257];
  UINT16 huffcode[257];
  UINT16 code;
  
  /* Figure 7.3.5.4.2.1: make table of Huffman code length for each symbol */
  /* Note that this is in code-length order. */

  p = 0;
  for (l = 1; l <= 16; l++) {
    for (i = 1; i <= (int) htbl->bits[l]; i++)
      huffsize[p++] = (char) l;
  }
  huffsize[p] = 0;
  lastp = p;
  
  /* Figure 7.3.5.4.2.2: generate the codes themselves */
  /* Note that this is in code-length order. */
  
  code = 0;
  si = huffsize[0];
  p = 0;
  while (huffsize[p]) {
    while (((int) huffsize[p]) == si) {
      huffcode[p++] = code;
      code++;
    }
    code <<= 1;
    si++;
  }
  
  /* Figure 7.3.5.4.2.3: generate encoding tables */
  /* These are code and size indexed by symbol value */

  for (p = 0; p < lastp; p++) {
    htbl->ehufco[htbl->huffval[p]] = huffcode[p];
    htbl->ehufsi[htbl->huffval[p]] = huffsize[p];
  }
  
  /* Figure 13.4.2.3.1: generate decoding tables */

  p = 0;
  for (l = 1; l <= 16; l++) {
    if (htbl->bits[l]) {
      htbl->valptr[l] = p;	/* huffval[] index of 1st sym of code len l */
      htbl->mincode[l] = huffcode[p]; /* minimum code of length l */
      p += htbl->bits[l];
      htbl->maxcode[l] = huffcode[p-1];	/* maximum code of length l */
    } else {
      htbl->maxcode[l] = -1;
    }
  }
  htbl->maxcode[17] = 0xFFFFFL;	/* ensures huff_DECODE terminates */
}


/* Extract the next N bits from the input stream (N <= 15) */

LOCAL int
get_bits (int nbits)
{
  int result;
  
  while (nbits > bits_left) {
    int c = JGETC(dcinfo);
    
    get_buffer <<= 8;
    get_buffer |= c;
    bits_left += 8;
    /* If it's 0xFF, check and discard stuffed zero byte */
    if (c == 0xff) {
      c = JGETC(dcinfo);  /* Byte stuffing */
      if (c != 0)
	ERREXIT1(dcinfo->emethods,
		 "Unexpected marker 0x%02x in compressed data", c);
    }
  }
  
  bits_left -= nbits;
  result = ((int) (get_buffer >> bits_left)) & ((1 << nbits) - 1);
  return result;
}

/* Macro to make things go at some speed! */

#define get_bit()	(bits_left ? \
			 ((int) (get_buffer >> (--bits_left))) & 1 : \
			 get_bits(1))


/* Figure 13.4.2.3.2: extract next coded symbol from input stream */
  
LOCAL int
huff_DECODE (HUFF_TBL * htbl)
{
  int l, p;
  INT32 code;
  
  code = get_bit();
  l = 1;
  while (code > htbl->maxcode[l]) {
    code = (code << 1) + get_bit();
    l++;
  }

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

  if (l > 16) {
    ERREXIT(dcinfo->emethods, "Corrupted data in JPEG file");
  }

  p = (int) (htbl->valptr[l] + (code - htbl->mincode[l]));
  
  return (int) htbl->huffval[p];
}


/* Figure 13.4.2.1.1: extend sign bit */

/* NB: on some compilers this will only work for s > 0 */

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


/* Decode a single block's worth of coefficients */
/* Note that only the difference is returned for the DC coefficient */

LOCAL void
decode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
{
  int s, k, r, n;

  /* zero out the coefficient block */

  MEMZERO((void *) block, SIZEOF(JBLOCK));
  
  /* Section 13.4.2.1: decode the DC coefficient difference */

  s = huff_DECODE(dctbl);
  if (s) {
    r = get_bits(s);
    s = huff_EXTEND(r, s);
  }
  block[0] = s;

  /* Section 13.4.2.2: decode the AC coefficients */
  
  for (k = 1; k < DCTSIZE2; k++) {
    r = huff_DECODE(actbl);
    
    s = r & 15;
    n = r >> 4;
    
    if (s) {
      k += n;
      r = get_bits(s);
      block[k] = huff_EXTEND(r, s);
    } else {
      if (n != 15)
	break;
      k += 15;
    }
  }
}


/*
 * Initialize for a Huffman-compressed scan.
 * This is invoked after reading the SOS marker.
 */

METHODDEF void
huff_decoder_init (decompress_info_ptr cinfo)
{
  short ci;
  jpeg_component_info * compptr;

  /* Initialize static variables */
  dcinfo = cinfo;
  bits_left = 0;

  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
    compptr = cinfo->cur_comp_info[ci];
    /* Make sure requested tables are present */
    if (cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no] == NULL ||
	cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no] == NULL)
      ERREXIT(cinfo->emethods, "Use of undefined Huffman table");
    /* Compute derived values for Huffman tables */
    /* We may do this more than once for same table, but it's not a big deal */
    fix_huff_tbl(cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no]);
    fix_huff_tbl(cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]);
    /* Initialize DC predictions to 0 */
    cinfo->last_dc_val[ci] = 0;
  }

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


/*
 * Check for a restart marker & resynchronize decoder.
 */

LOCAL void
process_restart (decompress_info_ptr cinfo)
{
  int c, nbytes;
  short ci;

  /* Throw away any partial unread byte */
  bits_left = 0;

  /* Scan for next JPEG marker */
  nbytes = 0;
  do {
    do {			/* skip any non-FF bytes */
      nbytes++;
      c = JGETC(cinfo);
    } while (c != 0xFF);
    do {			/* skip any duplicate FFs */
      nbytes++;
      c = JGETC(cinfo);
    } while (c == 0xFF);
  } while (c == 0);		/* repeat if it was a stuffed FF/00 */

  if (c != (RST0 + cinfo->next_restart_num))
    ERREXIT2(cinfo->emethods, "Found 0x%02x marker instead of RST%d",
	     c, cinfo->next_restart_num);

  if (nbytes != 2)
    TRACEMS2(cinfo->emethods, 1, "Skipped %d bytes before RST%d",
	     nbytes-2, cinfo->next_restart_num);
  else
    TRACEMS1(cinfo->emethods, 2, "RST%d", cinfo->next_restart_num);

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

  /* Update restart state */
  cinfo->restarts_to_go = cinfo->restart_interval;
  cinfo->next_restart_num++;
  cinfo->next_restart_num &= 7;
}


/*
 * Decode and return one MCU's worth of Huffman-compressed coefficients.
 */

METHODDEF void
huff_decode (decompress_info_ptr cinfo, JBLOCK *MCU_data)
{
  short blkn, ci;
  jpeg_component_info * compptr;

  /* Account for restart interval, process restart marker if needed */
  if (cinfo->restart_interval) {
    if (cinfo->restarts_to_go == 0)
      process_restart(cinfo);
    cinfo->restarts_to_go--;
  }

  for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
    ci = cinfo->MCU_membership[blkn];
    compptr = cinfo->cur_comp_info[ci];
    decode_one_block(MCU_data[blkn],
		     cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no],
		     cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]);
    /* Convert DC difference to actual value, update last_dc_val */
    MCU_data[blkn][0] += cinfo->last_dc_val[ci];
    cinfo->last_dc_val[ci] = MCU_data[blkn][0];
  }
}


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

METHODDEF void
huff_decoder_term (decompress_info_ptr cinfo)
{
  /* No work needed */
}


/*
 * The method selection routine for Huffman entropy decoding.
 */

GLOBAL void
jseldhuffman (decompress_info_ptr cinfo)
{
  if (! cinfo->arith_code) {
    cinfo->methods->entropy_decoder_init = huff_decoder_init;
    cinfo->methods->entropy_decode = huff_decode;
    cinfo->methods->entropy_decoder_term = huff_decoder_term;
  }
}
