/* $Id: main.c,v 1.51 1998/03/16 16:49:25 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 */
/************************************************************/

/****************************************************************************/
/*     Texas Instruments Predictive Embedded Zerotree (PEZW) Image Codec    */
/*     Copyright 1996, 1997, 1998 Texas Instruments	      		    */
/****************************************************************************/

#include <stdio.h>
#include <math.h>
#include "vm_config.h"  /* new */

#define DEFINE_GLOBALS

#include "dataStruct.h"
#include "globals.h"
#include "states.h"
#include "Utils.h"
#include "QMInit.h"
#include "QMUtils.h"
#include "encQM.h"
#include "decQM.h"
#include "errorHandler.h"
#include "startcode.h"
#include "seg.h"

#include "bitpack.h"
#include "ac.h"

#include "dwt.h"
#include "default.h"
#include "download_filter.h"

#include "main.h"
#include "ShapeCodec.h"

#include "ztscan.h"
#include "wavelet.h"
#include "read_control_file.h"
#include "read_image.h"

/* added for bilevel quantization mode */
#include "wvtPEZW.h"

#ifdef _CHECK_BITS_
File *fpe;
#endif

#ifdef _CHECK_HI_LO_
extern File *acfp;
#endif

Int  decoder;  /* new */

/* Argument variables - set defaults */
static Char *statsFileDef     = "stat";
static Char *decRecImgFileDef = "decRec.yuv";
static Char *encRecImgFileDef = "encRec.yuv";

static Char *statsFile;
static Char *decRecImgFile;
static Char *encRecImgFile;
static Char *recImgFile;

static Char *bitFile;
static Char *bitFileAC;
static Int singleBitFile;
Int  decoder;  /* new */


/*******************************************************/
/*  Flush buffer and close file. Only and must be used */
/*   by encoder to close bitstream file                */
/*******************************************************/
static Void flush_buffer_file()
{
  flush_bits();
  flush_bytes();
}

static Void close_buffer_file(File *fp)
{
  flush_buffer_file();
  fclose(fp);
}



static Void zeroACBand(Int c)
{
  Int x, y;

  noteDetail("Zeroing out AC coefficients....");
  for (x = 0; x < mzte_codec.SPlayer[c].width; ++x)
    for (y = 0; y < mzte_codec.SPlayer[c].height; ++y)
      if (x >= mzte_codec.dcWidth || y >= mzte_codec.dcHeight)
	COEFF_VAL(x,y,c) = 0;
  noteDetail("Completed zeroing out AC coefficients.");

}


/*************************************/
/* Encode SNR layer in seperate file */
/*************************************/  
static Void TextureSNRLayerMQ_encode(Int spa_lev, Int snr_lev, File *fp)
{
  SNR_IMAGE *snr_image;
  Int col;
  Int texture_snr_layer_id=0;

#ifdef _CHECK_HI_LO_
  acfp=fopen("encode_hl.dat","a");
#endif

  if(snrStartCode){
    noteProgress("Encoding Multi-Quant Mode Layer with SNR start code....");
    /* header */  
    emit_bits((UShort)texture_snr_layer_start_code>>16,16);
    emit_bits((UShort)texture_snr_layer_start_code,16);
    emit_bits((UShort)texture_snr_layer_id,5);
  }
  else
    noteProgress("Encoding Multi-Quant Mode Layer without SNR start code....");

  for(col=0;col<mzte_codec.colors;col++)
  {
    noteProgress("Multi-Quant Mode - Spatial %d, SNR %d, Color %d",
                 spa_lev,snr_lev,col);
    noteDetail("width=%d  height=%d",mzte_codec.SPlayer[col].width,
	      mzte_codec.SPlayer[col].height);    
    /* Set global color variable */
    mzte_codec.curColor = col;
    
    /* Set quant value and write to bitstream */
    snr_image=&(mzte_codec.SPlayer[col].SNRlayer.snr_image);
    snr_image->quant = mzte_codec.Qinfo[col][spa_lev].Quant[snr_lev];
    noteDebug("AC quant=%d", 
               mzte_codec.Qinfo[col][spa_lev].Quant[snr_lev]);
    
    /* initialization of spatial dimensions for each color component */
    if (snr_lev==0) 
      setSpatialLevelAndDimensions(spa_lev, col);
    
#ifdef _WRITE_ORV_MAP_
    dumpACORVMap(mapFileEnc, col, 0);
#endif /*_WRITE_ORV_MAP_*/

    /* get maximum residual value - this one is derived from user Q inputs not 
       actual values. Also assign skip modes. */
    updateResidMaxAndAssignSkips(col);

    /* quantize and mark zerotree structure for AC coefficients */
    if (encQuantizeAndMarkAC(col))
      errorHandler("encQuantizeAndMarkAC");

    noteDebug("max_root=%d max_valz=%d max_valnz=%d max_resi=%d",
               ROOT_MAX(col),VALZ_MAX(col),VALNZ_MAX(col),
               RESID_MAX(col));


    /* Write quant value and all zero flag to bitstream */
    /* emit_bits(snr_image->quant,8); */
    put_param(snr_image->quant,7);
    emit_bits(snr_image->allzero,1);

    if(snr_image->allzero==0)
      wavelet_higher_bands_encode_MQ(snr_image,col);
    
#ifdef _WRITE_COEFF_MAP_
    /* Write out coeffinfo stuff to file. */
    dumpACMap(mapFileEnc, col);
#endif /*_WRITE_COEFF_MAP_*/

    /* Update states of AC coefficients */
    if (encUpdateStateAC(mzte_codec.curColor))
      errorHandler("encUpdateStateAC");

    /*    writeStats(); */
 }
  
#ifdef _CHECK_HI_LO_
  fclose(acfp);
#endif
}



static Void TextureObjectLayer_enc(FILTER *wvtfilter,SOL_PARAMETERS *vm_param)
{
  File *bitfile;
  Int  texture_object_id=0;
  Int  texture_object_layer_shape=vm_param->sa_dwt;
  Int  wavelet_stuffing = 0x0f;
  Int  wavelet_upload;
  Int  texture_spatial_layer_id=0;
  Int  spa_lev,snr_lev=0,col=0;
  Char fname[100];
  Int  err;
  Int snr_scalability_levels;

  /*-------------------------------------------------*/
  /*--------- DC (and overall header info) ----------*/
  /*-------------------------------------------------*/

  /*------- DC: Open and initialize bitstream file -------*/
  if ((bitfile=fopen(bitFile,"wb"))==NULL)
    errorHandler("Can't open file '%s' for writing.",bitFile);

  /* initialize variables */
  init_bit_packing_fp(bitfile,1);


  /*------- DC: Write header info to bitstream file -------*/
  noteProgress("Encoding DC coefficients....");


  emit_bits((UShort)(STILL_TEXTURE_OBJECT_START_CODE>>16), 16);
  emit_bits((UShort)STILL_TEXTURE_OBJECT_START_CODE, 16);
  emit_bits((UShort)texture_object_id, 16);
  emit_bits((UShort)MARKER_BIT, 1);
  emit_bits((UShort)wvtfilter->Type, 1);
  wavelet_upload=vm_param->wvtType>1?1:0;
  emit_bits((UShort)wavelet_upload, 1);
  if (wavelet_upload == 1) {
    upload_wavelet_filters(wvtfilter);
  }
  emit_bits((UShort)mzte_codec.wvtDecompLev, 8);
  emit_bits((UShort)texture_object_layer_shape, 2);
  emit_bits((UShort)wavelet_stuffing, 3);
  if (texture_object_layer_shape == 0x00) {
    emit_bits((UShort)mzte_codec.real_width, 15);
    emit_bits((UShort)MARKER_BIT, 1);
    emit_bits((UShort)mzte_codec.real_height, 15);
    emit_bits((UShort)MARKER_BIT, 1);
  }
  else { /* Arbitrary shape info, SL */
    /*horizontal_ref */
    emit_bits((UShort)mzte_codec.origin_x, 15);
    /* marker_bit */
    emit_bits((UShort)MARKER_BIT, 1);
    /*vertical_ref */
    emit_bits((UShort)mzte_codec.origin_y, 15);
    /* marker_bit */
    emit_bits((UShort)MARKER_BIT, 1);
    /* object_width */
    emit_bits((UShort)mzte_codec.width, 15);
     /* marker_bit */
    emit_bits((UShort)MARKER_BIT, 1);
    /* object_height */
    emit_bits((UShort)mzte_codec.height, 15);
    /* marker_bit */
    emit_bits((UShort)MARKER_BIT, 1);
    /* merge shape bitstream into the main bitstream */
    noteProgress("Merge Shape Bitstream ....");
    MergeShapeBitstream();
  }
  emit_bits((UShort)mzte_codec.spatial_scalability_levels, 5);
  emit_bits((UShort)mzte_codec.quantization_type, 2);
  emit_bits((UShort)mzte_codec.SNR_start_code_enable, 1);

  /*------- DC: Quantize and encode all color components -------*/
  for (col=0; col<mzte_codec.colors; col++) 
  {
    /* Set global color variable */
    mzte_codec.curColor=col;

    /* initialize DC coefficient info */
    if ((err=ztqInitDC(0, col)))
      errorHandler("ztqInitDC");

#ifdef _WRITE_ORV_MAP_
    dumpDCORVMap(mapFileEnc, col, 0);
#endif /*_WRITE_ORV_MAP_*/

    /* quantize DC coefficients */
    if ((err=encQuantizeDC(col)))
      errorHandler("encQuantizeDC");

#ifdef _WRITE_COEFF_MAP_
    /* Write out coeffinfo stuff to file. */
    dumpDCMap(mapFileEnc, col);
#endif /*_WRITE_COEFF_MAP_*/

    /* losslessly encoding DC coefficients */
    wavelet_dc_encode(col);

    /* writeStats();  */
  }  


  /*------- DC: Close bitstream file -------*/
  if (singleBitFile) 
    flush_buffer_file(); 
  else  
    close_buffer_file(bitfile); 

  noteProgress("Completed encoding DC coefficients.");

  /*-------------------------------------------------*/
  /*--------------------- AC ------------------------*/
  /*-------------------------------------------------*/

  /*------- AC: Initialize QList Structure -------*/
  if ((err=ztqQListInit()))
    errorHandler("Allocating memory for QList information.");


  /*------- AC: SINGLE-QUANT MODE -------*/
  if (mzte_codec.quantization_type == SINGLE_Q)
  {
    /*------- AC: Set spatial and SNR levels to zero -------*/
    mzte_codec.curSpatialLev = 0;
    mzte_codec.curSNRLev = 0;


    /*------- AC: Open and initialize bitstream file -------*/
    if (singleBitFile==0)
    {
      sprintf(fname,bitFileAC,
	      mzte_codec.curSNRLev,mzte_codec.curSpatialLev);
      if ((bitfile=fopen(fname,"wb"))==NULL)
	errorHandler("Can't open file '%s' for writing.",fname);
    }

    /* initialize the buffer */
    init_bit_packing_fp(bitfile,1);
    

    /*------- AC: Write header info to bitstream file -------*/
    emit_bits((UShort)TEXTURE_SPATIAL_LAYER_START_CODE >> 16, 16);
    emit_bits((UShort)TEXTURE_SPATIAL_LAYER_START_CODE, 16);
    emit_bits((UShort)texture_spatial_layer_id, 5);
    

    /*------- AC: Quantize and encode all color components -------*/
    for (col=0; col<mzte_codec.colors; col++)
    {       
      noteProgress("Single-Quant Mode - Color %d",col);
      
      /* Set global color variable */
      mzte_codec.curColor = col;

      /* Set quant value and write to bitstream */
      if (texture_spatial_layer_id == 0) {
        mzte_codec.SPlayer[col].SNRlayer.snr_image.quant =
          mzte_codec.Qinfo[col][0].Quant[0];
        /* emit_bits(mzte_codec.Qinfo[col][0].Quant[0], 8); */
        put_param(mzte_codec.Qinfo[col][0].Quant[0], 7);
        noteDebug("AC quant=%d", mzte_codec.Qinfo[col][0].Quant[0]);
      }

      /* initialization of spatial dimensions for each color component */
      setSpatialLevelAndDimensions(mzte_codec.curSpatialLev, col);
      
      /* initialize AC coefficient info for each color component */
      if ((err=ztqInitAC(0, col)))
        errorHandler("ztqInitAC");

#ifdef _WRITE_ORV_MAP_
    dumpACORVMap(mapFileEnc, col, 0);
#endif /*_WRITE_ORV_MAP_*/

      /* quantize and mark zerotree structure for AC coefficients */
      if ((err=encQuantizeAndMarkAC(col)))
        errorHandler("encQuantizeAndMarkAC");
      
      /* output maximums used by different prob. models */
      noteDebug("max_root=%d, max_valz=%d, max_valnz=%d, max_resid=%d",
                 ROOT_MAX(col),VALZ_MAX(col),VALNZ_MAX(col),
                 RESID_MAX(col));

      /* losslessly encoding AC coefficients */
      wavelet_higher_bands_encode_SQ(col);
      
#ifdef _WRITE_COEFF_MAP_
      /* Write out coeffinfo stuff to file. */
      dumpACMap(mapFileEnc, col);
#endif /*_WRITE_COEFF_MAP_*/
      
      /* writeStats(); */
    }



    /*------- AC: Close bitstream file -------*/
    if (singleBitFile)
      flush_buffer_file();
    else
      close_buffer_file(bitfile);

    /* store the max snr_lev and spa_lev so that the decoder can
       decode the bitstream up to the max level. */ 
    mzte_codec.target_spatial_levels = 1;
    mzte_codec.target_snr_levels = 1;
  }
 

  /*------- AC: MULTI-QUANT MODE -------*/
  else if (mzte_codec.quantization_type == MULTIPLE_Q)
  {
    /* Initialize AC coefficients for all colors based on spatial level 0 */
    for (col=0; col<mzte_codec.colors; col++) 
    {
      setSpatialLevelAndDimensions(0, col);
      if ((err=ztqInitAC(0, col)))
        errorHandler("ztqInitAC");
    }

    /* Loop through spatial layers */
    for (spa_lev=0; spa_lev<mzte_codec.spatial_scalability_levels; 
         spa_lev++)
    {
      /*----- AC: Set global spatial layer and SNR scalability level. -----*/
      /* Assumes all three color components have the same number of SNR 
         levels */
      mzte_codec.curSpatialLev = spa_lev;
      mzte_codec.SPlayer[0].SNR_scalability_levels = 
        mzte_codec.Qinfo[0][spa_lev].SNR_scalability_levels;
      snr_scalability_levels = mzte_codec.SPlayer[0].SNR_scalability_levels;

      /* Update spatial level coeff info if changing spatial levels.
         Do this for all color components */
      if (spa_lev != 0)
      {
        for (mzte_codec.curColor = 0; mzte_codec.curColor<mzte_codec.colors;
             mzte_codec.curColor++) 
        {
          setSpatialLevelAndDimensions(mzte_codec.curSpatialLev, 
                                       mzte_codec.curColor);
          spatialLayerChangeUpdate(mzte_codec.curColor);
        }
      }

      if (!snrStartCode)
      {
        /*------- AC: Open and initialize bitstream file -------*/
	if (singleBitFile==0)
	{
	  sprintf(fname,bitFileAC, mzte_codec.curSpatialLev);
	  if ((bitfile=fopen(fname,"wb"))==NULL)
	    errorHandler("Can't open file '%s' for writing.",fname);
	}

	/* initialize the buffer */
        init_bit_packing_fp(bitfile,1);


        /*------- AC: Write header info to bitstream file -------*/
        emit_bits(TEXTURE_SPATIAL_LAYER_START_CODE >> 16, 16);
        emit_bits(TEXTURE_SPATIAL_LAYER_START_CODE, 16);
        emit_bits(spa_lev, 5);
        emit_bits(snr_scalability_levels, 5);
      }


      /* Loop through SNR layers */      
      for (snr_lev=0; snr_lev<snr_scalability_levels; snr_lev++) 
      {
        /*----- AC: Set global SNR layer -----*/
        mzte_codec.curSNRLev = snr_lev;
        
        if (snrStartCode)
        {
          /*------- AC: Open and initialize bitstream file -------*/
	  if (singleBitFile==0)
	  {
	    sprintf(fname,bitFileAC,
		    mzte_codec.curSpatialLev, mzte_codec.curSNRLev);
	    if ((bitfile=fopen(fname,"wb"))==NULL)
	      errorHandler("Can't open file '%s' for writing.",fname);
	  }

          /* initialize the buffer */
          init_bit_packing_fp(bitfile,1);

          if (snr_lev==0) {
            /*------- AC: Write header info to bitstream file -------*/
            emit_bits(TEXTURE_SPATIAL_LAYER_START_CODE >> 16, 16);
            emit_bits(TEXTURE_SPATIAL_LAYER_START_CODE, 16);
            emit_bits(spa_lev, 5);
            emit_bits(snr_scalability_levels, 5);
            flush_bits();     /* byte alignment before start code */
          }

        }

        /*------- AC: Quantize and encode all color components -------*/
        TextureSNRLayerMQ_encode(spa_lev, snr_lev, bitfile);
        if (snrStartCode)
	{
	  if (singleBitFile)
	    flush_buffer_file();
	  else
	    close_buffer_file(bitfile);
	}


      } /* snr_lev */
      
      if (!snrStartCode)
      {
	if (singleBitFile)
	  flush_buffer_file();
	else
	  close_buffer_file(bitfile);
      }

    }  /* spa_lev */

    /* store the max snr_lev and spa_lev so that the decoder can
       decode the bitstream up to the max level. */ 
    mzte_codec.target_spatial_levels = spa_lev;
    mzte_codec.target_snr_levels = snr_lev;

  } /* multi-quant mode */

  /*------- AC: BILEVEL-QUANT MODE -------*/
  else if (mzte_codec.quantization_type == BILEVEL_Q)
    {
      PEZW_SPATIAL_LAYER *SPlayer[NCOLOR];
      Int h,w;
      Int Quant[NCOLOR];
      Int levels;

      /*------- AC: Open and initialize bitstream file -------*/
      if (singleBitFile==0)
        {
          sprintf(fname,bitFileAC,
                  mzte_codec.curSNRLev,mzte_codec.curSpatialLev);
          if ((bitfile=fopen(fname,"wb"))==NULL)
            errorHandler("Can't open file '%s' for writing.",fname);
        }
      
      /* initialize the buffer */
      init_bit_packing_fp(bitfile,1);
    

      /*------- AC: encode all color components -------*/
      for (col=0; col<mzte_codec.colors; col++)
        { 
          noteProgress("Bilevel-Quant Mode - Color %d",col);

          if (col ==0)  /* Lum */
            {
              h = mzte_codec.height;
              w = mzte_codec.width;
              levels = mzte_codec.wvtDecompLev;
            }
          else { /* should depend on mzte_codec.color_format;
                    not implemented yet, only support 4:2:0  */
            h = mzte_codec.height/2;
            w = mzte_codec.width/2;
            levels = mzte_codec.wvtDecompLev-1;
          }

          /* initialize data */
          SPlayer[col] = (PEZW_SPATIAL_LAYER *)Init_PEZWdata (col,levels,w,h);

          /* get quantization information */
          Quant[col] = mzte_codec.Qinfo[col]->Quant[0];

          /* encode this color componenet */
          WvtPEZW_Spatial_SNR (levels, SPlayer[col], Quant[col],1);
            
        }        

      /* package the bitstream and write to bitfile */
      PEZW_bitpack (SPlayer);

      /* free memory */
      PEZW_freeEnc (SPlayer);

      if (singleBitFile)
        flush_buffer_file();
      else
        close_buffer_file(bitfile);
      
    } /* bilevel-quant mode */


  if (singleBitFile)
    fclose(bitfile);

  /*------- AC: Free Qlist structure -------*/
  ztqQListExit();
}


/*************************************/
/* Decode SNR layer in separete file */
/*************************************/  
static Void TextureSNRLayerMQ_decode(Int spa_lev, Int snr_lev,File *fp)
{
  SNR_IMAGE *snr_image;
  Int col;
  Int texture_snr_layer_id;

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

  if(snrStartCode){
    noteProgress("Decoding Multi-Quant Mode Layer with SNR start code....");
    /* header info */
    if(get_X_bits(32) != texture_snr_layer_start_code)
      errorHandler("Error in decoding texture_snr_layer_start_code");
    texture_snr_layer_id=get_X_bits(5);
  }
  else 
    noteProgress("Decoding Multi-Quant Mode Layer without SNR start code....");


  for(col=0;col<mzte_codec.colors;col++){  
    
    noteProgress("Multi-Quant Mode - Spatial %d, SNR %d, Color %d",
                 spa_lev,snr_lev,col);
    
    /* Set global color variable */
    mzte_codec.curColor = col;
    
    /* initialization of spatial dimensions for each color component  */
    setSpatialLevelAndDimensions(mzte_codec.curSpatialLev, col);
    
    snr_image=&(mzte_codec.SPlayer[col].SNRlayer.snr_image);
    snr_image->quant=get_param(7);
    /* snr_image->quant=get_X_bits(8); */
    noteDebug("AC quant=%d", snr_image->quant);
    
    updateResidMaxAndAssignSkips(col);
    noteDebug("resid_max=%d\n",snr_image->residual_max);

    if((snr_image->allzero=get_X_bits(1))==0)
      wavelet_higher_bands_decode_MQ(snr_image,col);
    else
    {
      noteProgress("Note: Current AC band has all zero condition.");
      /* put zeros in all AC coefficients */
      zeroACBand(col);
      decMarkAC(col);
    }
    
#ifdef _WRITE_COEFF_MAP_
    /* Write out coeffinfo stuff to file. */
    dumpACMap(mapFileDec, col);
#endif /*_WRITE_COEFF_MAP_*/
    
    /* quantize and mark zerotree structure for AC coefficients */
    if (decIQuantizeAC(col))
      errorHandler("decQuantizeAndMarkAC");
    noteDebug("max_root=%d max_valz=%d max_valnz=%d max_resi=%d",
               ROOT_MAX(col),VALZ_MAX(col),VALNZ_MAX(col),
               RESID_MAX(col));
 
    /* Update states of ac coefficients */
    if (decUpdateStateAC(col))
      errorHandler("decUpdateStateAC");

#ifdef _WRITE_ORV_MAP_
    dumpACORVMap(mapFileDec, col, 0);
#endif /*_WRITE_ORV_MAP_*/
  } /* col */

#ifdef _CHECK_HI_LO_
  fclose(acfp);
#endif
}



static Void TextureObjectLayer_dec(SOL_PARAMETERS_DEC *vm_param_dec,
				   Int  target_spatial_levels,
				   Int  target_snr_levels, FILTER *wvtfilter)
{
  File *bitfile;
  Int  texture_spatial_layer_start_code;
  Int  texture_object_id;
  Int  marker_bit;
  Int  wavelet_download;
  Int  texture_object_layer_shape;
  Int  wavelet_stuffing;
  Int  texture_spatial_layer_id;
  Int  spa_lev,snr_lev,col;
  Char fname[100];
  Int  err;
  Int  snr_scalability_levels=0;
  Int   still_texture_object_start_code;
  Int  x,y,w,h,k;
  Int  decoder_done=0;

  UChar *inmask[3], *outmask[3];
  Int nLevels[3], ret;
  Int Width[3], Height[3];
  Int Nx[3], Ny[3];
  Int usemask;
  Int useint=1;
  PICTURE *Image;

  PEZW_SPATIAL_LAYER **SPlayer;
  WINT *output;
  Int hsize, vsize;
  Int Resol;
  Int bitplane;
  Int i,j;
  Int adj;
  Int all_zero;
  Int *lens;
  UChar *data;
  Int spalev, spalev1;  
  
  /*-------------------------------------------------*/
  /*--------- DC (and overall header info) ----------*/
  /*-------------------------------------------------*/

  /*------- DC: Open and initialize bitstream file -------*/
  if ((bitfile=fopen(bitFile,"rb"))==NULL)
    errorHandler("Can't open file '%s' for reading.",bitFile);

  /* initialize variables */
  init_bit_packing_fp(bitfile,1);


  /*------- DC: Read header info from bitstream file -------*/
  still_texture_object_start_code = get_X_bits(32);
  if (still_texture_object_start_code != STILL_TEXTURE_OBJECT_START_CODE)
    errorHandler("Wrong texture_object_layer_start_code.");

  texture_object_id = get_X_bits(16);
  marker_bit = get_X_bits(1);
  wvtfilter->Type = get_X_bits(1);
  wavelet_download = get_X_bits(1);
  if (wavelet_download == 1) {
    download_wavelet_filters(wvtfilter);
  }
  else if(wvtfilter->Type==INT_TYPE){
    mzte_codec.wvtType = 0;
    *wvtfilter=DefaultSynthesisFilterInt;
  }
  else{
    mzte_codec.wvtType = 1;
    *wvtfilter=DefaultSynthesisFilterDbl;
  }

  mzte_codec.wvtDecompLev = get_X_bits(8);
 
  texture_object_layer_shape = get_X_bits(2);
  wavelet_stuffing = get_X_bits(3);
  if (texture_object_layer_shape==0) {
    mzte_codec.sa_dwt       = 0; 
    mzte_codec.width = get_X_bits(15);
    marker_bit = get_X_bits(1);
    mzte_codec.height = get_X_bits(15);
    marker_bit = get_X_bits(1);
    vm_param_dec->width  = mzte_codec.width;  /* new */
    vm_param_dec->height = mzte_codec.height; /* new */
   }
  else { /* Arbitrary shape header */
    mzte_codec.sa_dwt       = 1; 
    mzte_codec.origin_x = get_X_bits(15);
    marker_bit = get_X_bits(1);
    mzte_codec.origin_y = get_X_bits(15);
    marker_bit = get_X_bits(1);
    mzte_codec.width = get_X_bits(15);
    marker_bit = get_X_bits(1);
    mzte_codec.height = get_X_bits(15);
    marker_bit = get_X_bits(1);
    mzte_codec.real_width = vm_param_dec->width;
    mzte_codec.real_height = vm_param_dec->height;
  }

  mzte_codec.colors=3;   /* new */
  mzte_codec.bit_depth=8;  /* new */
 /* decode the shape info from bitstream */
  if(mzte_codec.sa_dwt)
    noteProgress("Decoding Shape Information...");
  Image = (PICTURE *)malloc(sizeof(PICTURE)*3);
  
  get_virtual_mask(Image, mzte_codec.wvtDecompLev,
		   mzte_codec.width, mzte_codec.height, 
		   mzte_codec.sa_dwt, mzte_codec.colors);
  if (mzte_codec.sa_dwt)
    mzte_codec.SegImage  = vm_param_dec->SegImage;
  noteDetail("Creating and initializing data structures....");
  mzte_codec.colors=3;  /* hard code */
  for (col=0; col<mzte_codec.colors; col++) {

    h = mzte_codec.height >> (col>0);
    w  = mzte_codec.width  >> (col>0);

   /*--------- create coeffinfo structure ----------*/
    if ((mzte_codec.SPlayer[col].coeffinfo = 
	 (COEFFINFO **)calloc(h, sizeof(COEFFINFO *))) == NULL)
       errorHandler("Allocating memory for coefficient structure (I).");

    if ((mzte_codec.SPlayer[col].coeffinfo[0] = 
	 (COEFFINFO *)calloc(h*w, sizeof(COEFFINFO))) == NULL)
      errorHandler("Allocating memory for coefficient structure (II).");
   
    for (y = 1; y < h; ++y)
      mzte_codec.SPlayer[col].coeffinfo[y] = 
	mzte_codec.SPlayer[col].coeffinfo[y-1]+w;
  }
  noteDetail("Completed creating and initializing data structures.");

  mzte_codec.dcHeight  = mzte_codec.height >> mzte_codec.wvtDecompLev;
  mzte_codec.dcWidth   = mzte_codec.width >> mzte_codec.wvtDecompLev;

  mzte_codec.spatial_scalability_levels = get_X_bits(5);
  mzte_codec.quantization_type = get_X_bits(2);  
  mzte_codec.SNR_start_code_enable = get_X_bits(1); 
  mzte_codec.colors = 3;

  usemask = mzte_codec.sa_dwt;
  useint =1;
  /* copy over the inmask[0] */

  Width[0] = mzte_codec.width;
  Width[1] = Width[2] = (Width[0] >> 1);
  Height[0] = mzte_codec.height;
  Height[1] = Height[2] = (Height[0] >> 1);
  nLevels[0] = mzte_codec.wvtDecompLev ;
  nLevels[1] = nLevels[2] = nLevels[0]-1;
  
  Nx[0] = Ny[0]=2;
  for(col=1;col<mzte_codec.colors;col++) Nx[col]=Ny[col]=1;
  
  if (decoder==1)
    mzte_codec.Image = Image;
  for (col=0; col<mzte_codec.colors; col++) {
    inmask[col] = mzte_codec.Image[col].mask; 
    outmask[col] = (UChar *)malloc(sizeof(UChar)*
					   Width[col]*Height[col]);
    ret = do_DWTMask(inmask[col], outmask[col], 
		     Width[col], Height[col], 
		     nLevels[col], wvtfilter); 
    if (ret!= DWT_OK) 
      errorHandler("DWT Error Code %d\n", ret);
    
    for (k=0,y=0; y<Height[col]; y++)
      for (x=0; x<Width[col]; x++) 
	COEFF_MASK(x,y,col) = outmask[col][k++];
    free(outmask[col]);
    
  }

  
  if (target_spatial_levels<=0 || target_snr_levels<= 0)
    errorHandler("Neither target_spatial_levels nor target_snr_levels can be zero");

  if (target_spatial_levels > mzte_codec.spatial_scalability_levels) {
     target_spatial_levels = mzte_codec.spatial_scalability_levels;
     mzte_codec.target_spatial_levels = target_spatial_levels;
  }


  /*------- DC: Decode and inverse quantize all color components -------*/
  noteProgress("Decoding DC coefficients....");
  for (col=0; col<mzte_codec.colors; col++) 
  {
    /* initilize all wavelet coefficients */
    mzte_codec.curColor=col;
    err=ztqInitDC(1, col);

    /* losslessly decoding DC coefficients */
    wavelet_dc_decode(col);

#ifdef _WRITE_COEFF_MAP_
    /* Write out coeffinfo stuff to file. */
    dumpDCMap(mapFileDec, col);
#endif /*_WRITE_COEFF_MAP_*/

    /* dequantize DC coefficients */
    err=decIQuantizeDC(col);

#ifdef _WRITE_ORV_MAP_
    dumpDCORVMap(mapFileDec, col, 1);
#endif /*_WRITE_ORV_MAP_*/
  }  


  /*------- DC: Close bitstream file -------*/
  align_byte();
  if (singleBitFile==0)
    fclose(bitfile);

  noteProgress("Completed decoding of DC coefficients.");

  /*-------------------------------------------------*/
  /*--------------------- AC ------------------------*/
  /*-------------------------------------------------*/

  /*------- AC: Initialize QList Structure -------*/
  if ((err=ztqQListInit()))
    errorHandler("Allocating memory for QList information.");
  
  
  /*------- AC: SINGLE-QUANT MODE -------*/
  if (mzte_codec.quantization_type == SINGLE_Q) 
  {
    /*------- AC: Set spatial and SNR levels to zero -------*/
    mzte_codec.curSpatialLev = 0;
    mzte_codec.curSNRLev = 0;


    /*------- AC: Open and initialize bitstream file -------*/
    if (singleBitFile==0)
    {
      sprintf(fname,bitFileAC,
	      mzte_codec.curSNRLev,mzte_codec.curSpatialLev);
      if ((bitfile=fopen(fname,"rb"))==NULL)
	errorHandler("Can't open file '%s' for reading.",fname);
      init_bit_packing_fp(bitfile,1);
    }
    else
      init_bit_packing_fp(bitfile,0);
 
   
    /*------- AC: Read header info from bitstream file -------*/
    texture_spatial_layer_start_code = get_X_bits(32);
    if (texture_spatial_layer_start_code != TEXTURE_SPATIAL_LAYER_START_CODE)
      errorHandler("Wrong texture_spatial_layer_start_code1 %x.",
	texture_spatial_layer_start_code);
    
    texture_spatial_layer_id = get_X_bits(5);
    

    /*------- AC: Decode and inverse quantize all color components -------*/
    for (col=0; col<mzte_codec.colors; col++) 
    {  
      noteProgress("Single-Quant Mode - Color %d",col);
      
      /* Set global color variable */
      mzte_codec.curColor = col;
       
      /* Read quant value from bitstream */
      /* mzte_codec.SPlayer[col].SNRlayer.snr_image.quant = 
        get_X_bits(8); */
      mzte_codec.SPlayer[col].SNRlayer.snr_image.quant = 
        get_param(7);
      noteDebug("Quant=%d", mzte_codec.SPlayer[col].SNRlayer.snr_image.quant);

      /* initialization of spatial dimensions for each color component */
      setSpatialLevelAndDimensions(mzte_codec.curSpatialLev, col);

      /* initialize AC coefficient info */
      if ((err=ztqInitAC(1, col)))
        errorHandler("ztqInitAC");
 
      /* losslessly decoding AC coefficients */
      wavelet_higher_bands_decode_SQ( col);

#ifdef _WRITE_COEFF_MAP_
      /* Write out coeffinfo stuff to file. */
      dumpACMap(mapFileDec, col);
#endif /*_WRITE_COEFF_MAP_*/
      
      /* Inverse quantize AC coefficients */
      if ((err=decIQuantizeAC(col)))
        errorHandler("decIQuantizeAC");
        
      noteDebug("max_root=%d max_valz=%d max_valnz=%d max_resi=%d",
                 ROOT_MAX(col),VALZ_MAX(col),VALNZ_MAX(col),RESID_MAX(col));


#ifdef _WRITE_ORV_MAP_
    dumpACORVMap(mapFileDec, col, 1);
#endif /*_WRITE_ORV_MAP_*/
    
    /* writeStats(); */
 
    }
    
    /*------- AC: Close bitstream file -------*/
    if (singleBitFile==0)
      fclose(bitfile);
  }
  

  /*------- AC: MULTI-QUANT MODE -------*/
  else if (mzte_codec.quantization_type == MULTIPLE_Q)
  {
    /* Initialize AC coefficients for all colors based on spatial level 0 */
    for (col=0; col<mzte_codec.colors; col++) 
    {
      setSpatialLevelAndDimensions(0, col);
      if ((err=ztqInitAC(1, col)))
        errorHandler("ztqInitAC");
    }

    /* Loop through spatial layers */

    spa_lev = 0;
    do {

      /*----- AC: Set global spatial layer and SNR scalability level. -----*/
      /* Assumes all three color components have the same number of SNR 
         levels */
      mzte_codec.curSpatialLev = spa_lev;

      /* Update spatial level coeff info if changing spatial levels.
         Do this for all color components */
      if (spa_lev != 0)
      {
        for (mzte_codec.curColor = 0; mzte_codec.curColor<mzte_codec.colors;
             mzte_codec.curColor++) 
        {
          setSpatialLevelAndDimensions(mzte_codec.curSpatialLev, 
                                       mzte_codec.curColor);
          spatialLayerChangeUpdate(mzte_codec.curColor);
        }
      }

      if (!snrStartCode)
      {
	if (singleBitFile==0)
	{
	  /*------- AC: Open and initialize bitstream file -------*/
	  sprintf(fname,bitFileAC, mzte_codec.curSpatialLev);
	  if ((bitfile=fopen(fname,"rb"))==NULL)
	    errorHandler("Can't open file '%s' for reading.",fname);
 
	  /* initialize the buffer */
	  init_bit_packing_fp(bitfile,1);
	}
	else
	  init_bit_packing_fp(bitfile,0);

        /*------- AC: Read header info from bitstream file -------*/
        texture_spatial_layer_start_code = get_X_bits(32);
        if (texture_spatial_layer_start_code != 
	    TEXTURE_SPATIAL_LAYER_START_CODE)
          errorHandler("Wrong texture_spatial_layer_start_code %x.",
            texture_spatial_layer_start_code);

        texture_spatial_layer_id = get_X_bits(5);
	if (texture_spatial_layer_id != spa_lev)
	  errorHandler("Incorrect texture_spatial_layer_id");
        snr_scalability_levels = get_X_bits(5);  
        mzte_codec.SPlayer[0].SNR_scalability_levels = snr_scalability_levels;
 
      }

     /* Loop through SNR layers */  
      snr_lev=0;
      do {

        /*----- AC: Set global SNR layer -----*/
        mzte_codec.curSNRLev = snr_lev;

        if (snrStartCode)
        {
          /*------- AC: Open and initialize bitstream file -------*/
	  if (singleBitFile==0)
	  {
	    sprintf(fname,bitFileAC,
		    mzte_codec.curSpatialLev,mzte_codec.curSNRLev);
	    if ((bitfile=fopen(fname,"rb"))==NULL)
	      errorHandler("Can't open file '%s' for reading.",fname);
	
	    /* initialize the buffer */
	    init_bit_packing_fp(bitfile,1);
	  }
	  else
	    init_bit_packing_fp(bitfile,0);

          /*------- AC: Read header info from bitstream file -------*/
          if (snr_lev==0) {
            texture_spatial_layer_start_code = get_X_bits(32);
            if (texture_spatial_layer_start_code != 
                TEXTURE_SPATIAL_LAYER_START_CODE)
              errorHandler("Wrong texture_spatial_layer_start_code3 %x.",
                 texture_spatial_layer_start_code);
         
            texture_spatial_layer_id = get_X_bits(5);
	    if(texture_spatial_layer_id !=spa_lev)
	      errorHandler("Incorrect texture_spatial_layer_id");
            snr_scalability_levels = get_X_bits(5);  
            mzte_codec.SPlayer[0].SNR_scalability_levels = 
              snr_scalability_levels;
            align_byte();  /* byte alignment before start code */
          }

        }

        /*------- AC: Decode and inverse quantize all color components ------*/
        TextureSNRLayerMQ_decode(spa_lev, snr_lev, bitfile);
        if (snrStartCode){
	  align_byte();  /* byte alignment before start code */
	  if (singleBitFile==0)
	    fclose(bitfile);
	}

	if (spa_lev>=target_spatial_levels-1 && 
	    snr_lev>=target_snr_levels-1)
	   decoder_done = 1;

	perform_layer_IDWT(spa_lev, snr_lev, mzte_codec.sa_dwt,
			   mzte_codec.colors, mzte_codec.wvtDecompLev,  
			   wvtfilter, FULLSIZE, recImgFile);


        snr_lev++;
      } while (snr_lev<snr_scalability_levels && (!decoder_done)); 

      if (!snrStartCode){
	align_byte();  /* byte alignment before start code */
	if (singleBitFile==0)
	  fclose(bitfile);
      }
      spa_lev++;
    } while (spa_lev<target_spatial_levels && (!decoder_done));  /* spa_lev */

  } /* multi-quant mode */

  /*------- AC: BILEVEL-QUANT MODE -------*/
  else if (mzte_codec.quantization_type == BILEVEL_Q)
    {

      SPlayer = (PEZW_SPATIAL_LAYER **)calloc(mzte_codec.colors, sizeof(Void *))
;

      /*------- AC: Open and initialize bitstream file -------*/
      if (singleBitFile==0)
        {
          sprintf(fname,bitFileAC,
                  mzte_codec.curSNRLev,mzte_codec.curSpatialLev);
          if ((bitfile=fopen(fname,"rb"))==NULL)
            errorHandler("Can't open file '%s' for reading.",fname);
          init_bit_packing_fp(bitfile,1);
        }
      else
        init_bit_packing_fp(bitfile,0);
      
      
      /* parse the bitstreams into spatial and snr layers */
      PEZW_bit_unpack (SPlayer);

      /* decode the bitstream */
      snr_scalability_levels = SPlayer[0][0].SNR_scalability_levels;
      lens = calloc(snr_scalability_levels*mzte_codec.wvtDecompLev,
                    sizeof(Int));
      

      for(i=0;i<mzte_codec.wvtDecompLev;i++)
        for (j=0;j<snr_scalability_levels;j++)
          lens[i*snr_scalability_levels+j] = 
            SPlayer[0][i].SNRlayer[j].snr_bitstream.length;

      for (col=0;col<mzte_codec.colors;col++)
        {
          /* adjustment for decompositionlevels for different color */
          if(col==0) 
            adj=0;
          else 
            adj=1;

          /* target bitplane */
          bitplane = mzte_codec.target_snr_levels;
          if (bitplane>SPlayer[col][0].SNR_scalability_levels)
            bitplane = SPlayer[col][0].SNR_scalability_levels;

          /* target resolution */
          Resol = mzte_codec.wvtDecompLev-mzte_codec.target_spatial_levels;
          if (Resol<0) Resol=0;
          Resol=0;
          
          if(DEBUG_DEC_BS)
            fprintf(stdout, "\nResolution Off: %d \n", Resol);

          SPlayer[col][0].SNRlayer[0].Quant *= 1<<(SPlayer[col][0].SNR_scalability_levels-1);
          output = SPlayer[col][0].SNRlayer[0].snr_image.data;
          hsize = SPlayer[col][0].SNRlayer[0].snr_image.width;
          vsize = SPlayer[col][0].SNRlayer[0].snr_image.height;

          WvtDecodePEZW_Spatial_SNR (output,hsize,vsize,SPlayer[col], 
            mzte_codec.wvtDecompLev-adj,Resol,bitplane,mzte_codec.SNR_start_code_enable);

          /* parse the bitstream for the next color component */
          if (col<mzte_codec.colors-1){
            for(i=1;i<mzte_codec.wvtDecompLev;i++)
              for (j=0;j<snr_scalability_levels;j++){

                    if(col==0) 
                      spalev=i;
                    else                
                      spalev=i-1;
                        
                    spalev1=i-1;

                    lens[i*snr_scalability_levels+j] -= 
                      SPlayer[col][spalev].SNRlayer[j].snr_bitstream.length;

                    (Char *) SPlayer[col+1][spalev1].SNRlayer[j].snr_bitstream.data =
                      (Char *) SPlayer[col][spalev].SNRlayer[j].snr_bitstream.data +
                      
                      SPlayer[col][spalev].SNRlayer[j].snr_bitstream.length;
                    
                    /* shift the data to the left by one bit */
                    data = SPlayer[col+1][spalev1].SNRlayer[j].snr_bitstream.data;
                    all_zero = lshift_by_NBit(data,lens[i*snr_scalability_levels+j],
                                              1);
                    
                    if(all_zero)
                      SPlayer[col+1][spalev1].SNRlayer[j].allzero = 1;
                    else
                      SPlayer[col+1][spalev1].SNRlayer[j].allzero = 0;
                    
              } /* end of snr levels */
          }
        } /* end of color loop */



      /* put the decoded wavelet coefficients back into the data structure */
      restore_PEZWdata (SPlayer);

      /* free memory */
      PEZW_freeDec (SPlayer);
      free(SPlayer);
      free(lens);

    }  /* bilevel quantization */

  for(col=0; col< mzte_codec.colors; col++)
    free(Image[col].mask);
  free(Image);
  ztqQListExit();
} 



/***********************************************************************/
/***********************************************************************/
/*          ENCODING PARAMATERS                                        */
/***********************************************************************/
/***********************************************************************/

Void VTC_Encode(VTCConfig *vtc)
{
  Int col,y,i;
  Int width,height;
  FILTER *anafilter,*synfilter;
  SOL_PARAMETERS *vm_param;

  noteProgress("\n----- MPEG-4 Visual Texture Coding: Encoding -----\n");

  statsFile     = statsFileDef;
  encRecImgFile = encRecImgFileDef;
  decRecImgFile = decRecImgFileDef;
  recImgFile = decRecImgFile;

  /* read the control file */
  if ((vm_param = (SOL_PARAMETERS *)malloc(sizeof(SOL_PARAMETERS)*1)) == NULL)
    errorHandler("Allocating memory for parameters.");

  if ((vm_param->Image = 
       (PICTURE *)malloc(sizeof(PICTURE)*3)) == NULL)
    errorHandler("error allocating memory \n");

  if ((vm_param->SegImage = 
       (PICTURE *)malloc(sizeof(PICTURE)*1)) == NULL)
    errorHandler("error allocating memory \n");
  
  /* copy Momusys parameters to VM_PARAMETERS */
  vm_param->singleBitFile              = 1;   /* single file */
  vm_param->bitFile                    = vtc->bitstream;
  vm_param->id                         = vtc->id; 
  vm_param->Image[0].width             = vtc->width;
  vm_param->Image[0].height            = vtc->height;
  vm_param->ImagePath                  = vtc->image_file;
  vm_param->SegPath                    = vtc->shape_file;
  encRecImgFile                        = vtc->rec_file;
  recImgFile                           = encRecImgFile;
  vm_param->bit_depth                  = vtc->bit_depth;
  vm_param->colors                     = vtc->colors;
  vm_param->sa_dwt                     = vtc->sa_dwt;
  vm_param->wvtType                    = vtc->wvtType;
  vm_param->wvtDecompLev               = vtc->wvtDecompLev;
  vm_param->QdcY                       = vtc->QdcY;
  vm_param->QdcUV                      = vtc->QdcUV;
  vm_param->spatial_scalability_levels = vtc->spatial_scalability_levels;
  vm_param->quantization_type          = vtc->quantization_type;
  vm_param->SNR_start_code_enable      = vtc->SNR_start_code_enable;
  vm_param->target_bitrate             = vtc->target_bitrate;
  vm_param->target_spatial_levels      = vtc->target_spatial_levels;
  vm_param->target_snr_levels          = vtc->target_snr_levels;
  vm_param->deringWindowSize           = vtc->deringWindowSize;
  vm_param->deringThreshold            = vtc->deringThreshold;
  vm_param->alphaTH = vtc->alphaTH;
  vm_param->change_CR_disable=vtc->change_CR_disable;
  for (col=0; col<vm_param->colors; col++)
    vm_param->SPlayer[col]     = vtc->SPlayer[col];
  
  
  /* read the source image */
  noteProgress("Reading in image '%s'....", vm_param->ImagePath);
  read_image(vm_param->ImagePath, vm_param->Image[0].width, 
             vm_param->Image[0].height, vm_param->colors, 
             vm_param->bit_depth, vm_param->Image); 
  noteProgress("Completed reading in image.");

  /* read the segmentation map of the source image */
  if (vm_param->sa_dwt) {
    noteProgress("Reading in seg map '%s'....", vm_param->SegPath);
    (Void)read_segimage(vm_param->SegPath, 
			vm_param->Image[0].width, 
			vm_param->Image[0].height, vm_param->colors, 
			vm_param->bit_depth, vm_param->Image); 
    noteProgress("Completed reading in seg map.");
  }

  get_virtual_image(vm_param->Image, vm_param->wvtDecompLev, 
		    vm_param->sa_dwt, vm_param->colors, 
		    vm_param->alphaTH, vm_param->change_CR_disable);
 
    noteProgress("Completed getting virtual image.");
  /* fill in encoding/decoding parameters */
  mzte_codec.Image                      = vm_param->Image;
  mzte_codec.wvtDecompLev               = vm_param->wvtDecompLev; 
  mzte_codec.wvtType                    = vm_param->wvtType; 
  mzte_codec.sa_dwt                     = vm_param->sa_dwt; 
  if (mzte_codec.sa_dwt)
     mzte_codec.SegImage                = vm_param->SegImage;
  mzte_codec.spatial_scalability_levels = vm_param->spatial_scalability_levels;
  mzte_codec.quantization_type          = vm_param->quantization_type;
  mzte_codec.SNR_start_code_enable      = vm_param->SNR_start_code_enable;
  mzte_codec.colors                     = vm_param->colors;
  mzte_codec.bit_depth                  = vm_param->bit_depth;
  mzte_codec.deringWindowSize           = vm_param->deringWindowSize;
  mzte_codec.deringThreshold            = vm_param->deringThreshold;
  mzte_codec.target_spatial_levels      = vm_param->target_spatial_levels; 
  mzte_codec.target_snr_levels          = vm_param->target_snr_levels; 
  mzte_codec.Qdc[0]                     = vm_param->QdcY;
  if (vm_param->colors != MONO) {
    mzte_codec.Qdc[1]                   = vm_param->QdcUV;
    mzte_codec.Qdc[2]                   = vm_param->QdcUV;
  }
  for (col=0; col<vm_param->colors; col++)
    mzte_codec.Qinfo[col]      = vm_param->SPlayer[col];
  mzte_codec.dcHeight          = mzte_codec.height >> mzte_codec.wvtDecompLev;
  mzte_codec.dcWidth           = mzte_codec.width >> mzte_codec.wvtDecompLev;
  for (col=0; col<mzte_codec.colors; col++) {
    mzte_codec.Image[col].height = mzte_codec.height >> (col>0);
    mzte_codec.Image[col].width  = mzte_codec.width >> (col>0);
  }
  /* hard code here */
  mzte_codec.acm_order = vm_param->acm_order = 0;
  vm_param->acm_maxf=(Int *)malloc(6*sizeof(Int));
  for(i=0;i<6;i++)
    vm_param->acm_maxf[i] = 16383;
  mzte_codec.acm_maxf = vm_param->acm_maxf;
  init_acm_maxf_enc();

  singleBitFile = vm_param->singleBitFile;
  bitFile = vm_param->bitFile;
  bitFileAC = vm_param->bitFileAC;

  noteDetail("Completed creating and initializing data structures.");

  for (col=0; col<mzte_codec.colors; col++) {
    height = mzte_codec.Image[col].height; 
    width  = mzte_codec.Image[col].width;
    
    /*--------- create coeffinfo structure ----------*/
    if ((mzte_codec.SPlayer[col].coeffinfo = 
	 (COEFFINFO **)calloc(height, sizeof(COEFFINFO *))) == NULL)
      errorHandler("Allocating memory for coefficient structure (I).");

    if ((mzte_codec.SPlayer[col].coeffinfo[0] = 
	 (COEFFINFO *)calloc(height*width, sizeof(COEFFINFO))) == NULL)
      errorHandler("Allocating memory for coefficient structure (II).");
    
    for (y = 1; y < height; ++y)
      mzte_codec.SPlayer[col].coeffinfo[y] = 
	mzte_codec.SPlayer[col].coeffinfo[y-1]+width;
  }

  /***********************************************************************/
  /***********************************************************************/
  /*            DISCRETE WAVELET TRANSFORM                               */
  /***********************************************************************/
  /***********************************************************************/
  noteProgress("Wavelet Transform....");  
  choose_wavelet_filter(&anafilter,&synfilter,vm_param->wvtType);
  perform_DWT(anafilter);
  noteProgress("Completed wavelet transform.");
  

#ifdef _CHECK_BITS_
  fpe=fopen("encode_bits","wb");
#endif

  TextureObjectLayer_enc(synfilter,vm_param);  

#ifdef _CHECK_BITS_
  fclose(fpe);
#endif

                                                          
  /*  close statistics file */
  fclose(sfp);


  noteProgress("\n----- Encoding Completed. -----\n");

  /*   decoding part */
  {
    SOL_PARAMETERS_DEC *vm_param_dec;
    FILTER             wvtfilter;
    
    noteProgress("\n----- MPEG-4 Visual Texture Coding: Decoding -----\n");
    
    /* Read in decoding parameters */
    if ((vm_param_dec = 
	 (SOL_PARAMETERS_DEC *)malloc(sizeof(SOL_PARAMETERS_DEC)*1)) == NULL)
      errorHandler("Allocating memory for parameters.");
    
    vm_param_dec->height  = mzte_codec.height;
    vm_param_dec->width   = mzte_codec.width;
    vm_param_dec->wvtType = mzte_codec.wvtType;
    vm_param_dec->SegPath = vm_param->SegPath;
    vm_param_dec->width = mzte_codec.width;
    vm_param_dec->height = mzte_codec.height;
    vm_param_dec->colors = mzte_codec.colors=3;
    vm_param_dec->bit_depth =mzte_codec.bit_depth=8;
    vm_param_dec->wvtDecompLev = mzte_codec.wvtDecompLev;
    vm_param_dec->acm_order = mzte_codec.acm_order = 0;
    vm_param_dec->acm_maxf=(Int *)malloc(6*sizeof(Int));
    for(i=0;i<6;i++)
      vm_param_dec->acm_maxf[i] = 16383;
    
    singleBitFile = 1;
    bitFile = vm_param->bitFile;

    TextureObjectLayer_dec(vm_param_dec, mzte_codec.target_spatial_levels,
			   mzte_codec.target_snr_levels,&wvtfilter); 
    
    noteProgress("\nInverse Wavelet Transform....");
    perform_IDWT(vm_param_dec,&wvtfilter,  recImgFile);
    noteProgress("Completed inverse wavelet transform.");
    
   }
  


  /*----- free up coeff data structure -----*/
  noteDetail("Freeing up encoding data structures....");
  for (col=0; col<mzte_codec.colors; col++) {
    free(mzte_codec.SPlayer[col].coeffinfo[0]);
    free(mzte_codec.SPlayer[col].coeffinfo);
  }
  noteDetail("Completed freeing up encoding data structures.");

  noteProgress("\n----- Encoding Completed. -----\n");
  
  free_vm_param(vm_param);
}


/***********************************************************************/
/***********************************************************************/
/*                            DECODING                                 */
/***********************************************************************/
/***********************************************************************/

Void VTC_Decode(Char bitstream[],
           Char rec_filename[],
           Char shape_filename[],
	   Int  shape_width,
	   Int  shape_height,
           Int  target_bitrate, 
           Int  target_spatial_level, 
           Int  target_snr_level)
{
  Int col,i;
  SOL_PARAMETERS_DEC *vm_param_dec;
  FILTER wvtfilter;
  decoder=1;
  decRecImgFile = rec_filename;
  recImgFile    = decRecImgFile;

  noteProgress("\n----- MPEG-4 Visual Texture Coding: Decoding -----\n");

  /* Read in decoding parameters */
  if ((vm_param_dec = 
       (SOL_PARAMETERS_DEC *)malloc(sizeof(SOL_PARAMETERS_DEC)*1)) == NULL)
    errorHandler("Allocating memory for parameters.");



#ifdef _CHECK_BITS_
  fpe=fopen("decode_bits","wb");
#endif

  vm_param_dec->bitFile               = bitstream;
  vm_param_dec->SegPath               = shape_filename;
  vm_param_dec->width                 = shape_width;
  vm_param_dec->height                = shape_height;
  vm_param_dec->target_snr_levels     = target_snr_level;
  vm_param_dec->target_spatial_levels = target_spatial_level;
  vm_param_dec->target_bitrate        = target_bitrate;

  mzte_codec.target_spatial_levels   = vm_param_dec->target_spatial_levels;
  mzte_codec.target_snr_levels       = vm_param_dec->target_snr_levels;
  mzte_codec.acm_order = vm_param_dec->acm_order = 0;
  vm_param_dec->acm_maxf=(Int *)malloc(6*sizeof(Int));
  for(i=0;i<6;i++)
    vm_param_dec->acm_maxf[i] = 16383;
  mzte_codec.acm_maxf = vm_param_dec->acm_maxf;

  init_acm_maxf_dec();
  
  singleBitFile = 1;
  bitFile = vm_param_dec->bitFile;
  bitFileAC = vm_param_dec->bitFileAC;

  TextureObjectLayer_dec(vm_param_dec, mzte_codec.target_spatial_levels,
			 mzte_codec.target_snr_levels,&wvtfilter); 

#ifdef  _CHECK_BITS_
  fclose(fpe);
#endif


  /***********************************************************************/
  /***********************************************************************/
  /*            DISCRETE INVERSE WAVELET TRANSFORM                       */
  /***********************************************************************/
  /***********************************************************************/
  noteProgress("\nInverse Wavelet Transform....");
  perform_IDWT(vm_param_dec,&wvtfilter, recImgFile);
  noteProgress("Completed inverse wavelet transform.");
  
  noteDetail("Freeing up decoding data structures....");
  for (col=0; col<mzte_codec.colors; col++) {
    free(mzte_codec.SPlayer[col].coeffinfo[0]);
    free(mzte_codec.SPlayer[col].coeffinfo);
  }
  noteDetail("Completed freeing up decoding data structures.");

  noteProgress("\n----- Decoding Completed. -----\n");
  free_vm_param_dec(vm_param_dec);
}

