/* $Id: ztscan_dec.c,v 1.47 1998/03/16 20:36:01 hatrack Exp $ */
/****************************************************************************/
/*   MPEG4 Visual Texture Coding (VTC) Mode Software                        */
/*                                                                          */
/*   This software was developed by                                         */
/*   Sarnoff Coporation                   and    Texas Instruments          */
/*   Iraj Sodagar   (iraj@sarnoff.com)           Jie Liang (liang@ti.com)   */
/*   Hung-Ju Lee    (hjlee@sarnoff.com)                                     */
/*   Paul Hatrack   (hatrack@sarnoff.com)                                   */
/*   Shipeng Li     (shipeng@sarnoff.com)                                   */
/*   Bing-Bing Chai (bchai@sarnoff.com)                                     */
/*                                                                          */
/* In the course of development of the MPEG-4 standard. This software       */
/* module is an implementation of a part of one or more MPEG-4 tools as     */
/* specified by the MPEG-4 standard.                                        */
/*                                                                          */
/* The copyright of this software belongs to ISO/IEC. ISO/IEC gives use     */
/* of the MPEG-4 standard free license to use this  software module or      */
/* modifications thereof for hardware or software products claiming         */
/* conformance to the MPEG-4 standard.                                      */
/*                                                                          */
/* Those intending to use this software module in hardware or software      */
/* products are advised that use may infringe existing  patents. The        */
/* original developers of this software module and their companies, the     */
/* subsequent editors and their companies, and ISO/IEC have no liability    */
/* and ISO/IEC have no liability for use of this software module or         */
/* modification thereof in an implementation.                               */
/*                                                                          */
/* Permission is granted to MPEG memebers to use, copy, modify,             */
/* and distribute the software modules ( or portions thereof )              */
/* for standardization activity within ISO/IEC JTC1/SC29/WG11.              */
/*                                                                          */
/* Copyright (C) 1998  Sarnoff Coporation and Texas Instruments             */ 
/****************************************************************************/

/************************************************************/
/*     Sarnoff Very Low Bit Rate Still Image Coder          */
/*     Copyright 1995, 1996, 1997, 1998 Sarnoff Corporation */
/************************************************************/

/************************************************************/
/*  Filename: ztscan_dec.c                                  */
/*  Author: Bing-Bing CHai                                  */
/*  Date: Dec. 17, 1997                                     */
/*                                                          */
/*  Descriptions:                                           */
/*    This file contains the routines that performs         */
/*    zero tree scanning and entropy decoding.              */
/*                                                          */
/************************************************************/

#include <stdio.h>
#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <ctype.h>
#include <string.h>
#include <math.h>


#include "dataStruct.h"
#include "states.h"
#include "globals.h"
#include "errorHandler.h"
#include "ac.h" 
#include "bitpack.h"
#include "Utils.h"
#include "startcode.h"

#include "context.h" 
#include "ztscan.h"

static COEFFINFO **coeffinfo;
static color;

/* definations related to arithmetic coding */
#define NUMCHAR_TYPE 4
#define NUMCHAR_SKIP_TYPE 2
#define ADAPT 1

/* Zeroth Order Model Filter - send NULL if first order (no zeroth order part)
 */
#define ZOMF(x) (mzte_codec.acm_order!=AC_MODEL_FIRST ? (x) : NULL)

/* arithmetic models related variables, refer to syntax for meaning */
static ac_decoder acd;
static ac_model acm_type, acm_vz, acm_vnz, acm_res, acm_root, acm_sign;
static ac_context acc_type, acc_vz, acc_vnz, acc_res, acc_root, acc_sign;

#ifdef _IMPLIED_SKIP_IZ_
static ac_model acm_skip_type;
static ac_context acc_skip_type;
#endif

static Int height,width;

#ifdef _CHECK_HI_LO_
File *acfp;
#endif


/* functions defined */
static Void callc_decode();
static Void cachb_decode_SQ(SNR_IMAGE *snr_img);
static Void decode_pixel_SQ(Int h,Int w);
static Void  mag_sign_decode_SQ(Int h,Int w);
static Void cachb_decode_MQ(SNR_IMAGE *snr_image);
static Void decode_pixel_MQ(Int h,Int w);
static Void mark_ZTR_D(Int h,Int w);
static Void mag_sign_decode_MQ(Int h,Int w);


/* The following functions assume that mzte_codec is a global variable */
extern WVT_CODEC mzte_codec;


/*********************************************
  Initialize max frequency for each ac model
*********************************************/
Void init_acm_maxf_dec(){
  if(mzte_codec.acm_max_freq_chg ==0){
    acm_type.Max_frequency=acm_vz.Max_frequency=
      acm_vnz.Max_frequency=acm_res.Max_frequency=
      acm_root.Max_frequency=acm_sign.Max_frequency=16383;

#ifdef _IMPLIED_SKIP_IZ_
    acm_skip_type.Max_frequency=16383;
#endif

    return;
  }

  acm_type.Max_frequency=mzte_codec.acm_maxf[0];
#ifdef _IMPLIED_SKIP_IZ_
  acm_skip_type.Max_frequency=mzte_codec.acm_maxf[0];
#endif
  acm_vz.Max_frequency=mzte_codec.acm_maxf[1];
  acm_vnz.Max_frequency=mzte_codec.acm_maxf[2];
  acm_res.Max_frequency=mzte_codec.acm_maxf[3];
  acm_root.Max_frequency=mzte_codec.acm_maxf[4];
  acm_sign.Max_frequency=mzte_codec.acm_maxf[5];
}


/******************************************************************/
/****************************  DC  ********************************/
/******************************************************************/

/*******************************************************/
/**************  Inverse DC Prediction  ****************/
/*******************************************************/

/********************************************************
  Function Name
  -------------
  static DATA iDC_pred_pix(Int i, Int j)

  Arguments
  ---------
  int i, int j: Index of wavelet coefficient (row, col)
  
  Description
  -----------
  Inverse DPCM prediction for a DC coefficient, refer 
  to syntax for algorithm. 

  Functions Called
  ----------------
  None.

  Return Value
  ------------
    inverse prediction for coeffinfo[i][j].quantized_value
********************************************************/ 
static DATA  iDC_pred_pix(Int i, Int j)
{
  /*  modified by Z. Wu @ OKI */

  Int pred_i, pred_j, pred_d;

  if ( i==0 || coeffinfo[i-1][j].mask == 0 )	
    pred_i = 0;
  else
    pred_i = coeffinfo[i-1][j].quantized_value;

  if ( j==0 || coeffinfo[i][j-1].mask == 0 )	
    pred_j = 0;
  else 
    pred_j = coeffinfo[i][j-1].quantized_value;

  if ( i==0 || j== 0 || coeffinfo[i-1][j-1].mask == 0 )	
    pred_d = 0;
  else	
    pred_d = coeffinfo[i-1][j-1].quantized_value;

  if ( abs(pred_d-pred_j) < abs(pred_d-pred_i))	
    return(pred_i);
  else
    return(pred_j);
}



/*****************************************************
  Function Name
  -------------
  Void iDC_predict()

  Arguments
  ---------
  None
  
  Description
  -----------
  control program for inverse DC prediction

  Functions Called
  ----------------
  iDC_pred_pix(i,j).

  Return Value
  ------------
  none
******************************************************/
static Void iDC_predict(Int color)
{
  Int i,j,dc_h,dc_w,offset_dc;

  dc_h=mzte_codec.dcHeight;
  dc_w=mzte_codec.dcWidth;
 
  coeffinfo=mzte_codec.SPlayer[color].coeffinfo;
  offset_dc=mzte_codec.offset_dc;

  for(i=0;i<dc_h;i++)
    for(j=0;j<dc_w;j++)
      if (coeffinfo[i][j].mask != 0)
	coeffinfo[i][j].quantized_value += offset_dc;

  for(i=0;i<dc_h;i++)
    for(j=0;j<dc_w;j++)
      if (coeffinfo[i][j].mask != 0)
	coeffinfo[i][j].quantized_value+=iDC_pred_pix(i,j);
}




/********************************************************
  Function Name
  -------------
  Void wavelet_dc_decode(Int c)


  Arguments
  ---------
  Int c - color component.
  
  Description
  -----------
  Control program for decode DC information for one 
  color component.

  Functions Called
  ----------------
  None.
  iDC_predict()
  get_param()
  cacll_decode()
  
  Return Value
  ------------
  None.

********************************************************/ 
Void wavelet_dc_decode(Int c)
{
  noteDetail("Decoding DC (wavelet_dc_decode)....");
  color=c;

  mzte_codec.mean[color] = get_X_bits(8);
  /* mzte_codec.Qdc[color]  = get_X_bits(8); */
  mzte_codec.Qdc[color]  = get_param(7);

  mzte_codec.offset_dc=-get_param(7);
  /* mzte_codec.max_dc=get_param(7); */
  mzte_codec.max_dc=get_param(7)-mzte_codec.offset_dc; /* hjlee */

#ifdef _CHECK_HI_LO_
  acfp=fopen("decode_hl.dat","w");
#endif

  callc_decode();
  iDC_predict(color);
  noteDetail("Completed decoding DC.");

#ifdef _CHECK_HI_LO_
  fclose(acfp);
#endif


}



/********************************************************
  Function Name
  -------------
  static Void cacll_decode()

  Arguments
  ---------
  None.

  
  Description
  -----------
  Decode DC information for one color component.

  Functions Called
  ----------------
  ac_decoder_init()
  ac_model_init()
  ac_decode_symbol()
  ac_model_done()
  ac_decoder_done()

  Return Value
  ------------
  None.

********************************************************/ 
static Void callc_decode()
{
  Int dc_h, dc_w,i,j;

  dc_w=mzte_codec.dcWidth;
  dc_h=mzte_codec.dcHeight;

  /* init arithmetic model */
  /* ac_decoder_open(acd,NULL); */
  ac_decoder_init(&acd,NULL,NULL);

  if (mzte_codec.acm_order!=AC_MODEL_FIRST)
    ac_model_init(&acm_vz,mzte_codec.max_dc+1,NULL,ADAPT,1);
  if (mzte_codec.acm_order!=AC_MODEL_ZEROTH)
    initContext_VZ(&acc_vz, mzte_codec.max_dc+1);

  coeffinfo=mzte_codec.SPlayer[color].coeffinfo;
  for(i=0;i<dc_h;i++)
    for(j=0;j<dc_w;j++){

#ifdef _CHECK_HI_LO_
      fprintf(acfp,"%3d, %3d: %7d %7d\n",i,j,acd.high,acd.low);
#endif

      if( coeffinfo[i][j].mask == 1) 
      {
	coeffinfo[i][j].quantized_value=
	  ac_decode_symbol(&acd,ZOMF(&acm_vz),contextToModel_VZ(&acc_vz));
	updateContext_VZ(&acc_vz, coeffinfo[i][j].quantized_value);
      }
      else 
	coeffinfo[i][j].quantized_value=-mzte_codec.offset_dc;
    }

  /* close arithmetic coder */
  if (mzte_codec.acm_order!=AC_MODEL_FIRST)
    ac_model_done(&acm_vz);
  if (mzte_codec.acm_order!=AC_MODEL_ZEROTH)
    freeContext_VZ(&acc_vz);

  ac_decoder_done(&acd);
}



/*********************************************************************/
/*****************************  AC  **********************************/
/*************************  Single quant  ****************************/
/*********************************************************************/

/********************************************************
  Function Name
  -------------
  Void wavelet_higher_bands_decode_SQ(int c)

  Arguments
  ---------
  int c - color component.
  
  Description
  -----------
  Control program for decoding AC information for one 
  color component. Single quant mode.

  Functions Called
  ----------------
  get_param()
  cachb_decode_SQ()

  Return Value
  ------------
  None.

********************************************************/ 
Void wavelet_higher_bands_decode_SQ(Int c)
{
  SNR_IMAGE *snr_image;
  Int marker_bit;

  noteDetail("Decoding AC band (wavelet_higher_bands_decode_SQ)....");
  color = c;
  snr_image=&(mzte_codec.SPlayer[color].SNRlayer.snr_image);

  /* header info */
  snr_image->root_max=get_param(7);
  marker_bit = get_X_bits(1);
  snr_image->valz_max=get_param(7);
  snr_image->valnz_max=get_param(7);

  cachb_decode_SQ(snr_image);
  noteDetail("Completed decoding AC band.");
}



/********************************************************
  Function Name
  -------------
  static Void cachb_decode_SQ(SNR_IMAGE *snr_img)

  Arguments
  ---------
  SNR_IMAGE *snr_img - structure containing one color
                       component of an SNR image
  Description
  -----------
  Decode AC information for one color component. 
  Single quant mode, tree-depth scan

  Functions Called
  ----------------
  ac_decoder_init()
  ac_model_init()
  decode_pixel_SQ()
  ac_model_done()
  ac_decoder_done()

  Return Value
  ------------
  None.

********************************************************/ 
static Void cachb_decode_SQ(SNR_IMAGE *snr_img)
{
  Int h,w,dc_h,dc_w,dc_h2,dc_w2;

  dc_h=mzte_codec.dcHeight;
  dc_w=mzte_codec.dcWidth;
  dc_h2=dc_h<<1;
  dc_w2=dc_w<<1;
  height=mzte_codec.SPlayer[color].height;
  width=mzte_codec.SPlayer[color].width;

  /* init arithmetic coder */
  ac_decoder_init(&acd,NULL,NULL);

  if (mzte_codec.acm_order!=AC_MODEL_FIRST)
  {
    ac_model_init(&acm_type,NUMCHAR_TYPE,NULL,ADAPT,1);
    if (snr_img->root_max)
      ac_model_init(&acm_root,snr_img->root_max,NULL,ADAPT,1);
    ac_model_init(&acm_vz,snr_img->valz_max+1,NULL,ADAPT,1);
    if (snr_img->valnz_max)
      ac_model_init(&acm_vnz,snr_img->valnz_max,NULL,ADAPT,1);
    ac_model_init(&acm_sign,2,NULL,ADAPT,1);
  }
  if (mzte_codec.acm_order!=AC_MODEL_ZEROTH)
  {
    initContext_Type(&acc_type, NUMCHAR_TYPE);
    if (snr_img->root_max)
      initContext_Root(&acc_root, snr_img->root_max);
    initContext_VZ(&acc_vz, snr_img->valz_max+1);
    if (snr_img->valnz_max)
      initContext_VNZ(&acc_vnz, snr_img->valnz_max);
    initContext_Sign(&acc_sign, 2);
  }

  coeffinfo=mzte_codec.SPlayer[color].coeffinfo;

  /* LH */
  for(h=0;h<dc_h;h++)
    for(w=dc_w;w<dc_w2;w++){
      decode_pixel_SQ(h,w);           /* LH */
      decode_pixel_SQ(h+dc_h,w-dc_w); /* HL */
      decode_pixel_SQ(h+dc_h,w);      /* HH */
    }

  /* close arithmetic coder */
  if (mzte_codec.acm_order!=AC_MODEL_FIRST)
  {
    ac_model_done(&acm_type);
    if (snr_img->root_max)
      ac_model_done(&acm_root);
    ac_model_done(&acm_vz);
    if (snr_img->valnz_max)
      ac_model_done(&acm_vnz);
    ac_model_done(&acm_sign);
  }
  if (mzte_codec.acm_order!=AC_MODEL_ZEROTH)
  {
    freeContext_Type(&acc_type);
    if (snr_img->root_max)
      freeContext_Root(&acc_root);
    freeContext_VZ(&acc_vz);
    if (snr_img->valnz_max)
      freeContext_VNZ(&acc_vnz);
    freeContext_Sign(&acc_sign);
  }

  ac_decoder_done(&acd);
}



/********************************************************
  Function Name
  -------------
  static Void decode_pixel_SQ(int h,int w)

  Arguments
  ---------
  int h,int w - position of a pixel in height and width
  
  Description
  -----------
  Decoding the type and/or value of a coefficient, a
  recursive function.

  Functions Called
  ----------------
  mag_sign_decode_SQ()
  ac_decode_symbol()
  decode_pixel_SQ()

  Return Value
  ------------
  None.

********************************************************/ 
static Void decode_pixel_SQ(Int h,Int w)
{
  Int i,j;
  UChar zt_type;

  /* decode leave coefficients, value only */

  
  if(coeffinfo[h][w].state == S_LEAF){ /* zero value. no sign */
#ifdef _SHAPE_
    if(coeffinfo[h][w].mask==1)
#endif      
      mag_sign_decode_SQ(h,w);
#ifdef _SHAPE_
    else 
      coeffinfo[h][w].quantized_value = 0;
#endif      
#ifdef _WRITE_COEFF_MAP_
    if (coeffinfo[h][w].state == S_LEAF)
      coeffinfo[h][w].type = (coeffinfo[h][w].quantized_value) ? VLEAF : ZLEAF;
#endif
      
      return;
  }
  
  
  /* decode zero tree symbols */
#ifdef _SHAPE_
  if(coeffinfo[h][w].mask==1)
#endif
  {
    coeffinfo[h][w].type=zt_type=
      ac_decode_symbol(&acd,ZOMF(&acm_type),contextToModel_Type(&acc_type));  
    updateContext_Type(&acc_type, zt_type);
  }
    
#ifdef _SHAPE_
  else
    coeffinfo[h][w].type=zt_type = IZ;
#endif
  /* code magnitude and sign */
  switch(zt_type){
    case IZ :
      break;
    case VZTR:
     mag_sign_decode_SQ(h,w);
    case ZTR:
#ifdef _WRITE_COEFF_MAP_
      mark_ZTR_D(h,w);  /* not necessary, only for checking purpose */
#endif /*_WRITE_COEFF_MAP_*/
      return;
    case VAL:
      mag_sign_decode_SQ(h,w);
      break;
    default: 
      errorHandler("Invalid zerotree symbol in single quant decode");
  }
  

  /* scan children */
  i=h<<1; j=w<<1;
  decode_pixel_SQ(i,j);
  decode_pixel_SQ(i,j+1);
  decode_pixel_SQ(i+1,j);
  decode_pixel_SQ(i+1,j+1);
}


     
/********************************************************
  Function Name
  -------------
  static Void  mag_sign_decode_SQ(int h,int w)

  Arguments
  ---------
  int h,int w - position of a pixel

  Description
  -----------
  Decode the value of a coefficient.

  Functions Called
  ----------------
  ac_decode_symbol()

  Return Value
  ------------
  None.

********************************************************/ 
static Void  mag_sign_decode_SQ(Int h,Int w)
{
  Int value=0,v_sign;

  switch(stateToProbModel[coeffinfo[h][w].state]){    
    case ACM_ROOT:
      value=ac_decode_symbol(&acd,ZOMF(&acm_root),
			     contextToModel_Root(&acc_root))+1;
      updateContext_Root(&acc_root, value-1);
      break;
    case ACM_VALNZ:
      value=ac_decode_symbol(&acd,ZOMF(&acm_vnz),
			     contextToModel_VNZ(&acc_vnz))+1;
      updateContext_VNZ(&acc_vnz, value-1);
      break;
    case ACM_VALZ:  /* leaf */
      value=ac_decode_symbol(&acd,ZOMF(&acm_vz),contextToModel_VZ(&acc_vz));
      updateContext_VZ(&acc_vz, value);
      if (value==0)
      {
        coeffinfo[h][w].quantized_value=value;
        return;
      }
      break;
    default:
      errorHandler("not a valid magnitude type in encode_pixel_SQ");
  }
  v_sign=ac_decode_symbol(&acd,ZOMF(&acm_sign),contextToModel_Sign(&acc_sign));
  updateContext_Sign(&acc_sign, v_sign);
  coeffinfo[h][w].quantized_value=(v_sign==0) ? value : -value;
}



/*********************************************************************/
/******************************  AC  *********************************/
/**************************  Multi quant  ****************************/
/*********************************************************************/

/********************************************************
  Function Name
  -------------
  Void wavelet_higher_bands_decode_MQ(SNR_IMAGE *snr_image,int c)

  Arguments
  ---------
  SNR_IMAGE *snr_image - structure containing one color
                         component of an SNR image
  int c - color component.
  
  Description
  -----------
  Control program for decoding AC information for one 
  color component. Multi quant mode.

  Functions Called
  ----------------
  get_param()
  cachb_decode_MQ()

  Return Value
  ------------
  None.

********************************************************/ 
Void wavelet_higher_bands_decode_MQ(SNR_IMAGE *snr_image, Int c)
{
  Int marker_bit;

  noteDetail("Decoding AC band (wavelet_higher_bands_decode_MQ)....");
  /* header info */
  snr_image->root_max=get_param(7);
  marker_bit = get_X_bits(1);
  snr_image->valz_max=get_param(7);
  snr_image->valnz_max=get_param(7);
  color=c;
  coeffinfo=mzte_codec.SPlayer[color].coeffinfo;

  noteDebug("root=%d, valz=%d, valnz=%d",snr_image->root_max,
	     snr_image->valz_max,snr_image->valnz_max);

  cachb_decode_MQ(snr_image);
}




/********************************************************
  Function Name
  -------------
  static Void cachb_decode_MQ(SNR_IMAGE *snr_img)

  Arguments
  ---------
  SNR_IMAGE *snr_img - structure containing one color
                       component of an SNR image 
  Description
  -----------
  Decode AC information for one color component. 
  Multiple quant, bandwise scan.

  Functions Called
  ----------------
  ac_decoder_init()
  ac_model_init()
  clear_ZTR_D();
  decode_pixel_MQ()
  ac_model_done()
  ac_decoder_done()

  Return Value
  ------------
  None.

********************************************************/ 
static Void cachb_decode_MQ(SNR_IMAGE *snr_image)
{
  Int h,w,ac_h,ac_w,ac_h2,ac_w2;

  /* ac_h, ac_w init */
  ac_h=mzte_codec.dcHeight;
  ac_w=mzte_codec.dcWidth;
  ac_h2=ac_h<<1;
  ac_w2=ac_w<<1;
  height=mzte_codec.SPlayer[color].height;
  width=mzte_codec.SPlayer[color].width;

  /* init arithmetic coder */
  ac_decoder_init(&acd,NULL,NULL);
  
  if (mzte_codec.acm_order!=AC_MODEL_FIRST)
  {
    ac_model_init(&acm_type,NUMCHAR_TYPE,NULL,ADAPT,1);
#ifdef _IMPLIED_SKIP_IZ_
    ac_model_init(&acm_skip_type,NUMCHAR_SKIP_TYPE,NULL,ADAPT,1);
#endif

    if (snr_image->root_max)
      ac_model_init(&acm_root,snr_image->root_max,NULL,ADAPT,1);
    ac_model_init(&acm_vz,snr_image->valz_max+1,NULL,ADAPT,1);
    if (snr_image->valnz_max)
      ac_model_init(&acm_vnz,snr_image->valnz_max,NULL,ADAPT,1);
    ac_model_init(&acm_res,snr_image->residual_max+1,NULL,ADAPT,1);
    ac_model_init(&acm_sign,2,NULL,ADAPT,1);
  }
  if (mzte_codec.acm_order!=AC_MODEL_ZEROTH)
  {
    initContext_Type(&acc_type, NUMCHAR_TYPE);
#ifdef _IMPLIED_SKIP_IZ_
   initContext_SkipType(&acc_skip_type, NUMCHAR_SKIP_TYPE);
#endif
    if (snr_image->root_max)
      initContext_Root(&acc_root, snr_image->root_max);
    initContext_VZ(&acc_vz, snr_image->valz_max+1);
    if (snr_image->valnz_max)
      initContext_VNZ(&acc_vnz, snr_image->valnz_max);
    initContext_Res(&acc_res, snr_image->residual_max+1);
    initContext_Sign(&acc_sign, 2);
  }

  /* clear the ZTR_D type from the previous pass */
  clear_ZTR_D();

  /* scan each coefficients in the spatial layer */
  while(ac_h2<=height && ac_w2<=width){

    /* LH */
    for(h=0;h<ac_h;h++)
      for(w=ac_w;w<ac_w2;w++)
        decode_pixel_MQ(h,w);

    /* HL */
    for(h=ac_h;h<ac_h2;h++)
      for(w=0;w<ac_w;w++)
        decode_pixel_MQ(h,w);

    /* HH */
    for(h=ac_h;h<ac_h2;h++)
      for(w=ac_w;w<ac_w2;w++)
        decode_pixel_MQ(h,w);

    /* update ranges */
    ac_h=ac_h2;
    ac_w=ac_w2;
    ac_w2<<=1;
    ac_h2 <<=1;
  }

  /* close arithmetic coder */
  if (mzte_codec.acm_order!=AC_MODEL_FIRST)
  {
    ac_model_done(&acm_type);
#ifdef _IMPLIED_SKIP_IZ_
    ac_model_done(&acm_skip_type);
#endif
    if (snr_image->root_max)
      ac_model_done(&acm_root);
    ac_model_done(&acm_vz);
    if (snr_image->valnz_max)
      ac_model_done(&acm_vnz);
    ac_model_done(&acm_res);
    ac_model_done(&acm_sign);
  }
  if (mzte_codec.acm_order!=AC_MODEL_ZEROTH)
  {
    freeContext_Type(&acc_type);
#ifdef _IMPLIED_SKIP_IZ_
    freeContext_SkipType(&acc_skip_type);
#endif
    if (snr_image->root_max)
      freeContext_Root(&acc_root);
    freeContext_VZ(&acc_vz);
    if (snr_image->valnz_max)
      freeContext_VNZ(&acc_vnz);
    freeContext_Res(&acc_res);
    freeContext_Sign(&acc_sign);
  }

  ac_decoder_done(&acd);
}



/********************************************************
  Function Name
  -------------
  Void clear_ZTR_D()

  Arguments
  ---------
  None.

  
  Description
  -----------
  Clear the zerotree descendent marks in the entire image.

  Functions Called
  ----------------
  None.


  Return Value
  ------------
  None.

********************************************************/ 
Void clear_ZTR_D()
{
  register COEFFINFO **coeff;
  register i,j,dc_h2,dc_w2;

  coeff=coeffinfo;
  dc_h2=mzte_codec.dcHeight<<1;
  dc_w2=mzte_codec.dcWidth<<1;

  for(i=0;i<dc_h2;i++)
    for(j=dc_w2;j<width;j++)
      if(coeff[i][j].type == ZTR_D)
         coeff[i][j].type = UNTYPED;

  for(i=dc_h2;i<height;i++)
    for(j=0;j<width;j++)
      if(coeff[i][j].type == ZTR_D)
         coeff[i][j].type = UNTYPED;
}



/********************************************************
  Function Name
  -------------
  static Void decode_pixel_MQ(int h,int w)

  Arguments
  ---------
  int h,int w - position of a pixel in height and width
  
  Description
  -----------
  Decoding the type and/or value of a coefficient, a
  recursive function, multi quant mode.

  Functions Called
  ----------------
  ac_decode_symbol()
  mark_ZTR_D()
  mag_sign_decode_MQ()

  Return Value
  ------------
  None.

********************************************************/ 

static Void decode_pixel_MQ(Int h,Int w)
{
  Int zt_type;

#ifdef _CHECK_HI_LO_
  fprintf(acfp,"%3d, %3d: %7d %7d\n",h,w,acd.high,acd.low);
#endif


  /* zerotree descendent */
  if(coeffinfo[h][w].type==ZTR_D)
    return;

  /* decode zero tree symbol */
  
  if (coeffinfo[h][w].state == S_LEAF || coeffinfo[h][w].state == S_RLEAF
      || (coeffinfo[h][w].state == S_RVAL && coeffinfo[h][w].skip==0))
  {
    zt_type=VAL; /* tmp assign. for next switch statement */
  }
  else
  {
#ifdef _SHAPE_
    if(coeffinfo[h][w].mask==1) 
#endif
    {

#ifdef _IMPLIED_SKIP_IZ_
      if (coeffinfo[h][w].skip==SKIP_IZ)
	zt_type=coeffinfo[h][w].type=IZ;
      else if (coeffinfo[h][w].skip)
      {
	zt_type=coeffinfo[h][w].type=
	  (ac_decode_symbol(&acd,ZOMF(&acm_skip_type),
			    contextToModel_SkipType(&acc_skip_type))==IZ) 
	  ? IZ : ZTR;
	updateContext_SkipType(&acc_skip_type, zt_type);
      }
      else
#endif
      {
	zt_type=coeffinfo[h][w].type=
	  ac_decode_symbol(&acd,ZOMF(&acm_type),
			   contextToModel_Type(&acc_type));
	updateContext_Type(&acc_type, zt_type);
      }
    }      

#ifdef _SHAPE_
    else { /* treat out-node as isolated zero for decoding purpose */
      zt_type = coeffinfo[h][w].type = IZ;
    }
  
#endif
  }
  /* mark ztr_d and decode magnitudes */
  switch(zt_type)
  {
    case ZTR:
      mark_ZTR_D(h,w);
    case IZ:
      coeffinfo[h][w].quantized_value=0;
      return;
    case VZTR:
      mark_ZTR_D(h,w);
    case VAL:
#ifdef _SHAPE_
      if(coeffinfo[h][w].mask==1) 
#endif
	mag_sign_decode_MQ(h,w);
      break;
    default:
      errorHandler("Invalid type in multi quant decoding.");     
  }


#ifdef _WRITE_COEFF_MAP_
  if (coeffinfo[h][w].state == S_LEAF || coeffinfo[h][w].state == S_RLEAF)
    coeffinfo[h][w].type = (coeffinfo[h][w].quantized_value) ? VLEAF : ZLEAF;
  else if (coeffinfo[h][w].state == S_RVAL && coeffinfo[h][w].skip==0) 
    coeffinfo[h][w].type = VAL;
#endif /*_WRITE_COEFF_MAP_*/
}


/********************************************************
  Function Name
  -------------
  static Void mark_ZTR_D(int h,int w)

  Arguments
  ---------
  int h,int w - position of a pixel

  
  Description
  -----------
  Mark the coefficient at (h,w) and its descendents as
  zerotree descendents. 

  Functions Called
  ----------------
  mark_ZTR_D()


  Return Value
  ------------
  None.

********************************************************/ 
static Void mark_ZTR_D(Int h,Int w)
{
  Int i,j;

  i=h<<1; j=w<<1;

  if(i<height && j<width)
  {
    coeffinfo[i][j].quantized_value     = 0;
    coeffinfo[i+1][j].quantized_value   = 0;
    coeffinfo[i][j+1].quantized_value   = 0;
    coeffinfo[i+1][j+1].quantized_value = 0;

    coeffinfo[i][j].type     = ZTR_D; 
    coeffinfo[i+1][j].type   = ZTR_D; 
    coeffinfo[i][j+1].type   = ZTR_D; 
    coeffinfo[i+1][j+1].type = ZTR_D; 

    mark_ZTR_D(i,j);
    mark_ZTR_D(i+1,j);
    mark_ZTR_D(i,j+1);
    mark_ZTR_D(i+1,j+1);
  }
}




/********************************************************
  Function Name
  -------------
  static Void  mag_sign_decode_MQ(int h,int w)

  Arguments
  ---------
  int h,int w - position of a pixel

  Description
  -----------
  Decode the value of a coefficient.

  Functions Called
  ----------------
  ac_decode_symbol()

  Return Value
  ------------
  None.

********************************************************/ 
static Void mag_sign_decode_MQ(Int h,Int w)
{
  Int val=0,v_sign,ac_model;

  if(coeffinfo[h][w].skip)
  {
    coeffinfo[h][w].quantized_value=0;
    return;
  }

  ac_model=stateToProbModel[coeffinfo[h][w].state];

  /* decode magnitude */
  switch(ac_model){
    case ACM_ROOT:  /* smallest three AC bands */
      val=ac_decode_symbol(&acd,ZOMF(&acm_root),
			   contextToModel_Root(&acc_root))+1;
      updateContext_Root(&acc_root, val-1);
      break;
    case ACM_VALNZ:
      val=ac_decode_symbol(&acd,ZOMF(&acm_vnz),contextToModel_VNZ(&acc_vnz))+1;
      updateContext_VNZ(&acc_vnz, val-1);
      break;
    case ACM_VALZ:     /* leaf */
      val=ac_decode_symbol(&acd,ZOMF(&acm_vz),contextToModel_VZ(&acc_vz));
      updateContext_VZ(&acc_vz, val);
      if(val ==0){
        coeffinfo[h][w].quantized_value=0;
        return;
      }
      else
        break;
    case ACM_RESID:  /* refinement, no sign */
      coeffinfo[h][w].quantized_value=
	ac_decode_symbol(&acd,ZOMF(&acm_res),contextToModel_Res(&acc_res));
      updateContext_Res(&acc_res, coeffinfo[h][w].quantized_value);
      return;
    default:
      errorHandler("not a valid magnitude type in encode_pixel_MQ");
  }

  v_sign=ac_decode_symbol(&acd,ZOMF(&acm_sign),contextToModel_Sign(&acc_sign));
  updateContext_Sign(&acc_sign, v_sign);
  coeffinfo[h][w].quantized_value=(v_sign ==0) ? val: -val;
}



/********************************************************
  Function Name
  -------------
  Void write_coeff_to_file(char *fname,WVT_CODEC *mzte_codec)

  Arguments
  ---------
  char *fname - output file name
  WVT_CODEC *mzte_codec - structure for the mzte coder.

  
  Description
  -----------
  write coeff position, value, type, state, and ac_model to
  a file in the band-wise order.

  Functions Called
  ----------------
  None.


  Return Value
  ------------
  None.

********************************************************/ 
Void write_coeff_to_file(Char *fname,WVT_CODEC *mzte_codec)
{
  Int h,w,ac_h,ac_w,ac_h2,ac_w2;
  File *fp;
  COEFFINFO **coeffinfo;

  coeffinfo=mzte_codec->SPlayer[color].coeffinfo;
  fp=fopen(fname,"w");

  ac_h=mzte_codec->dcHeight;
  ac_w=mzte_codec->dcWidth;
  ac_h2=ac_h<<1; ac_w2=ac_w<<1;
  for(h=0;h<ac_h;h++)
    for(w=0;w<ac_w;w++)
      fprintf(fp,"%4d,%4d: %6d %3d %3d\n",h,w,
        coeffinfo[h][w].quantized_value,coeffinfo[h][w].type,
        coeffinfo[h][w].state);

  while(ac_h2<=mzte_codec->Image[0].height && 
        ac_w2<=mzte_codec->Image[0].width){
    /* LH */
    for(h=0;h<ac_h;h++)
      for(w=ac_w;w<ac_w2;w++)
      fprintf(fp,"%4d,%4d: %6d %3d %3d\n",h,w,
        coeffinfo[h][w].quantized_value,coeffinfo[h][w].type,
        coeffinfo[h][w].state);

    /* HL */
    for(h=ac_h;h<ac_h2;h++)
      for(w=0;w<ac_w;w++)
      fprintf(fp,"%4d,%4d: %6d %3d %3d\n",h,w,
        coeffinfo[h][w].quantized_value,coeffinfo[h][w].type,
        coeffinfo[h][w].state);

    /* HH */
    for(h=ac_h;h<ac_h2;h++)
      for(w=ac_w;w<ac_w2;w++)
      fprintf(fp,"%4d,%4d: %6d %3d %3d\n",h,w,
        coeffinfo[h][w].quantized_value,coeffinfo[h][w].type,
        coeffinfo[h][w].state);

    /* update ranges */
    ac_h=ac_h2;
    ac_w=ac_w2;
    ac_w2<<=1;
    ac_h2 <<=1;
  }
  fclose(fp);
}

