/****************************************************************************/
/*   MPEG4 Visual Texture Coding (VTC) Mode Software                        */
/*                                                                          */
/*   This software was jointly 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)                                     */
/*                                                                          */
/*   and                                                                    */
/*                                                                          */
/*   Oki Electric Industry Co., Ltd.                                        */
/*   Zhixiong Wu    (sgo@hlabs.oki.co.jp)                                   */
/*   Yoshihiro Ueda (yueda@hlabs.oki.co.jp)                                 */
/*   Toshifumi Kanamaru (kanamaru@hlabs.oki.co.jp)                          */
/*                                                                          */
/* 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            */ 
/****************************************************************************/

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

/* utilities for belevel coding and decoding
   Jie Liang (Texas Instruments)  liang@ti.com                */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "globals.h"
#include "msg.h"
#include "bitpack.h"
#include "startcode.h"
#include "errorHandler.h"
#include "wvtPEZW.h"
#include "PEZW_zerotree.h"


/* this funciton is to create and initiate the data structure
   used for bilevel image coding */

PEZW_SPATIAL_LAYER *Init_PEZWdata (Int color, Int levels, Int w, Int h)
{
  PEZW_SPATIAL_LAYER *SPlayer;
  Int x,y;
  Int i;

  mzte_codec.SNR_start_code_enable = 1;

  /* generate the Spatial Layer Structure */
  SPlayer = (PEZW_SPATIAL_LAYER *)calloc (levels, sizeof(PEZW_SPATIAL_LAYER));
  for (i=0; i<levels; i++)
     SPlayer[i].SNRlayer = calloc(MAXSNRLAYERS, sizeof(PEZW_SNR_LAYER));
     

  /* the original wavelet coefficients are in 
     SPlayer[0].SNRlayer[0].snr_image   */
  SPlayer[0].SNRlayer[0].snr_image.height = h;
  SPlayer[0].SNRlayer[0].snr_image.width = w;
  if ((SPlayer[0].SNRlayer[0].snr_image.data = calloc(h*w, sizeof(WINT)))
      == NULL){
    noteError ("Can not allocate memory in Init_PEZWdata()");
    exit(-1);
  }

  /* allocate memory for mask */
  if ((SPlayer[0].SNRlayer[0].snr_image.mask = calloc(h*w, sizeof(UChar)))
	  == NULL){
	  noteError ("Can not allocate memory in Init_PEZWdata()");
	  exit(-1);
  }
 
  
  /* copy the wavelet coefficients into SPlayer structure */
  for (y=0;y<h;y++)
    for (x=0;x<w;x++)
      ((WINT *)(SPlayer[0].SNRlayer[0].snr_image.data))[y*w+x] = (WINT) 
	  (mzte_codec.SPlayer[color].coeffinfo[y][x].wvt_coeff);

  /* copy the mask into SPlayer structure */	
  for (y=0;y<h;y++)
    for (x=0;x<w;x++)
		((UChar *)(SPlayer[0].SNRlayer[0].snr_image.mask))[y*w+x] = (UChar) 
		(mzte_codec.SPlayer[color].coeffinfo[y][x].mask);

  return (SPlayer);  

}

/* put the restored wavelet coefficients back to the data structure */
Void restore_PEZWdata (PEZW_SPATIAL_LAYER **SPlayer)
{
  Int x,y;
  Int col;
  Int h,w;
  Int dch, dcw;
  Int levels;

  for(col=0;col<mzte_codec.colors;col++){
    h = SPlayer[col][0].SNRlayer[0].snr_image.height;
    w = SPlayer[col][0].SNRlayer[0].snr_image.width;    
    
    if(col==0)
      levels=mzte_codec.wvtDecompLev;
    else
      levels=mzte_codec.wvtDecompLev-1;

    dch = h/(1<<levels);
    dcw = w/(1<<levels);

    /* copy the wavelet coefficients into data structure */
    for (y=0;y<h;y++)
      for (x=0;x<w;x++){
	if((x>=dcw) || (y>=dch))
	  mzte_codec.SPlayer[col].coeffinfo[y][x].rec_coeff = 	
	    ((WINT *)(SPlayer[col][0].SNRlayer[0].snr_image.data))[y*w+x]; 
      }
  }

  return;

}

/* this function pack the bitstream and write to file */
Void PEZW_bitpack (PEZW_SPATIAL_LAYER **SPlayer)
{
  Int levels = mzte_codec.wvtDecompLev;
  Int levels_UV;
  Int Quant[NCOLOR], q;
  Int texture_spatial_layer_id;

  Int lev;
  Int col;
  Int snr_scalability_levels=0;
  Int snr_lev;

  Int all_zero;
  Int i,n;

  UChar *data;
  LInt len;

  Int spalev;
  Int snroffset=0;
  Int flag;

  /* scan order */
  if (mzte_codec.spatial_scalability_levels==1)
    mzte_codec.scan_order = 0;
  else
    mzte_codec.scan_order = 1;
  
  levels_UV = levels-1;  /* this should depend on the color format 
			    mzte_codec.color_format */

  /* get quantization information */
  for (col=0;col<mzte_codec.colors; col++)
    Quant[col] = mzte_codec.Qinfo[col]->Quant[0];
  
  if(mzte_codec.scan_order==1){
    for (lev=0;lev<levels;lev++){   /* spatial scalability level */
      /*------- AC: Write header info to bitstream file -------*/
      flush_bits1();
      emit_bits(TEXTURE_SPATIAL_LAYER_START_CODE >> 16, 16);
      emit_bits(TEXTURE_SPATIAL_LAYER_START_CODE, 16);
      texture_spatial_layer_id = lev;
      emit_bits(texture_spatial_layer_id, 5);
      

      /* output quant for each color component */
      for (col=0;col<mzte_codec.colors; col++){
	q = Quant[col];
	flag=0;
	for(i=3;i>=0;i--)
	  {
	    q = Quant[col] & (0x7F << (i*7));
	    q >>= 7*i;
	    if (q>0) flag = 1;
	    if (flag){
	      if (i>0) 
		emit_bits(128+q,8);
	      else
		emit_bits(q,8);
	    }
	  }
      }
      
      /* output snr_scalability_levels: choose the maximum
	 snr_scalability_levels to put here for all color components */
      if (lev>0){
	snr_scalability_levels = SPlayer[0][lev].SNR_scalability_levels;
	for (col=1;col<mzte_codec.colors; col++){
	  if (snr_scalability_levels < SPlayer[col][lev-1].SNR_scalability_levels)
	    snr_scalability_levels = SPlayer[col][lev-1].SNR_scalability_levels;
	}
      }
      else  /* only luminance component at this level */
        snr_scalability_levels = SPlayer[0][lev].SNR_scalability_levels;
      
      emit_bits(snr_scalability_levels, 5);
      
      for (snr_lev=0;snr_lev<snr_scalability_levels;snr_lev++){
	
	/* output the SNR_START_CODE if enabled */
	if (mzte_codec.SNR_start_code_enable)
	  {
	    flush_bits1();
	    emit_bits(texture_snr_layer_start_code >> 16, 16);
	    emit_bits(texture_snr_layer_start_code, 16);
	    emit_bits(snr_lev,5);
	  }
	
	emit_bits_checksc_init();
	
	for (col=0;col<mzte_codec.colors; col++){ /* for each color compoent */
	  
	  if(col>0)  
	    spalev = lev-1;
	  else	   
	    spalev = lev;
	  
	  if(spalev>=0)
	    snroffset = snr_scalability_levels-SPlayer[col][spalev].SNR_scalability_levels;
	  
	  /* output SNR_ALL_ZERO flag */
	  if((lev==0)&&(col>0))
	    all_zero = 1;
	  else if (snr_lev < snroffset)   /* no color bits when lev>levels_UV */
	    all_zero = 1;
	  else
	    all_zero = 0;
	  
	  emit_bits_checksc (all_zero,1); 
	  
	  /* send the bitstream for this snr layer if not all_zero */
	  if (!all_zero){
	    data = (Char *)SPlayer[col][spalev].SNRlayer[snr_lev-snroffset].snr_bitstream.data;
	    len = SPlayer[col][spalev].SNRlayer[snr_lev-snroffset].snr_bitstream.length;
	    
	    /* output the bitstream */
	    for (n=0;n<len;n++){
	      emit_bits_checksc (data[n],8);
	      if (DEBUG_BS_DETAIL)
		fprintf(stdout,"%d ", data[n]);
	    }
	    
	    
	  } /* end of !all_zero */
	} /* end of color plane */      
      }	/* end of snr_scalability */
    }  /* end of spatial scalability */
  }
  else  /* scan_order == 0 */
  {
    /* output quant for each color component */
    for (col=0;col<mzte_codec.colors; col++){
      q = Quant[col];
      flag=0;
      for(i=3;i>=0;i--)
	{
	  q = Quant[col] & (0x7F << (i*7));
	  q >>= 7*i;
	  if (q>0) flag = 1;
	  if (flag){
	    if (i>0) 
	      emit_bits(128+q,8);
	    else
	      emit_bits(q,8);
	  }
	}
    }
    
    /* figure out snr scalability levels */
    snr_scalability_levels = 0;
    for(lev=0;lev<mzte_codec.wvtDecompLev;lev++){
      if(snr_scalability_levels < SPlayer[0][lev].SNR_scalability_levels)
	snr_scalability_levels = SPlayer[0][lev].SNR_scalability_levels;
      if (lev>0){
	for (col=1;col<mzte_codec.colors; col++){
	  if (snr_scalability_levels < SPlayer[col][lev-1].SNR_scalability_levels)
	    snr_scalability_levels = SPlayer[col][lev-1].SNR_scalability_levels;
	}
      }
    }
    emit_bits_checksc (snr_scalability_levels,5);
    
    /* package the bitstream */
    for (snr_lev=0;snr_lev<snr_scalability_levels;snr_lev++)
      {
	/* output the SNR_START_CODE if enabled */
	if (mzte_codec.SNR_start_code_enable)
	  {
	    flush_bits1();
	    emit_bits(texture_snr_layer_start_code >> 16, 16);
	    emit_bits(texture_snr_layer_start_code, 16);
	    emit_bits(snr_lev,5);
	  }	
	
	/* output the spatial levels */
	for (lev=0;lev<levels;lev++){   /* spatial scalability level */
	  if (mzte_codec.SNR_start_code_enable)
	    {
	      flush_bits1();
	      emit_bits(TEXTURE_SPATIAL_LAYER_START_CODE >> 16, 16);
	      emit_bits(TEXTURE_SPATIAL_LAYER_START_CODE, 16);
	      texture_spatial_layer_id = lev;
	      emit_bits(texture_spatial_layer_id, 5);
	      
	      
	    }
	  
	   /* for each color compoent */
	  for (col=0;col<mzte_codec.colors; col++){
	    if(col>0)  
	      spalev = lev-1;
	    else
	      spalev = lev;
	    
	    snroffset = snr_scalability_levels-SPlayer[col][spalev].SNR_scalability_levels;
	    
	    /* output SNR_ALL_ZERO flag */
	    if((lev==0)&&(col>0))
	      all_zero = 1;
	    else if (snr_lev < snroffset)  
	      all_zero = 1;
	    else
	      all_zero = 0;
	    
	    emit_bits_checksc (all_zero,1); 
	    
	    /* send the bitstream for this snr layer if not all_zero */
	    if (!all_zero){
	      data = (Char *)SPlayer[col][spalev].SNRlayer[snr_lev-snroffset].snr_bitstream.data;
	      len = SPlayer[col][spalev].SNRlayer[snr_lev-snroffset].snr_bitstream.length;
	      
	      /* output the bitstream */
	      for (n=0;n<len;n++){
		emit_bits_checksc (data[n],8);
		if (DEBUG_BS_DETAIL)
		  fprintf(stdout,"%d ", data[n]);
	      }
	      
	      
	    } /* end of !all_zero */
	  } /* end of color plane */      
	  
	} /* end of spatial level */
      }
  }  /* end of else scan_order */
}

/* unpacke the bitstream into Spatial and SNR layer bitstreams 
   SPlayer data structure will be created here  */

Void PEZW_bit_unpack (PEZW_SPATIAL_LAYER **SPlayer)
{
   Int splev, snrlev;
   Int spatial_id, snr_id;
   Int color;
   Int Quant[3]={0,0,0}, q;
   Int snr_scalability_levels;
   Int texture_spatial_layer_start_code;
   Int snr_layer_start_code;
   UChar buffer[MAXSIZE];
   LInt len;
   Int h,w;
   Int n, all_zero;
   Int Snrlevels;
   Int i, j;

   /* scan order */
   if (mzte_codec.spatial_scalability_levels==1)
     mzte_codec.scan_order = 0;
   else
     mzte_codec.scan_order = 1;
   
   /* initialize data structure */
   h=mzte_codec.height;
   w=mzte_codec.width;
   for (color=0;color<mzte_codec.colors;color++)
     SPlayer[color] = (PEZW_SPATIAL_LAYER *)calloc (mzte_codec.wvtDecompLev,
						    sizeof(PEZW_SPATIAL_LAYER));
   
   
   if(mzte_codec.scan_order==1){
     for (splev=0;splev<mzte_codec.wvtDecompLev;splev++)
       {
	 /* check start code */
	 
	 align_byte1();
	 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.");
	 spatial_id = get_X_bits(5);
	 
	 /* get the quantization step sizes */
	 for (color=0;color<mzte_codec.colors;color++){
	   do {
	     q = get_X_bits(8);
	     Quant[color] <<= 7;
	     Quant[color] += q%128;
	   } while (q>=128);
	 }
	 
	 /* get the snr scalability levels 
	    this is the maximum level for all three color components,
	    it will be adjusted later on according to all_zero flag */
	 
	 snr_scalability_levels = get_X_bits(5);
	 
	 for (color=0;color<mzte_codec.colors;color++){
	   SPlayer[color][splev].SNR_scalability_levels = snr_scalability_levels;
	   
	   /* allocate SNR data structure */
	   SPlayer[color][splev].SNRlayer = (PEZW_SNR_LAYER *)
	     calloc(snr_scalability_levels, sizeof(PEZW_SNR_LAYER));
	   SPlayer[color][splev].SNRlayer[0].Quant = Quant[color];
	   
	   if (color==0){
	     SPlayer[color][0].SNRlayer[0].snr_image.height = h;
	     SPlayer[color][0].SNRlayer[0].snr_image.width =  w;
	   }
	   else{
	     SPlayer[color][0].SNRlayer[0].snr_image.height = h/2;
	     SPlayer[color][0].SNRlayer[0].snr_image.width =  w/2;
	   }
	 } /* end of color */
	 
	 /* get the snr layer */
	 if (mzte_codec.SNR_start_code_enable)
	   Snrlevels=snr_scalability_levels;
	 else
	   Snrlevels=1;
	 
	 for (snrlev=0;snrlev<Snrlevels;snrlev++)
	 {
	   if (mzte_codec.SNR_start_code_enable)
	     {
	       align_byte1();
	       snr_layer_start_code = get_X_bits(32);
	       if (snr_layer_start_code != texture_snr_layer_start_code)
		 errorHandler("Wrong texture_snr_layer_start_code.");
	       snr_id = get_X_bits(5);
	     }
	   
	   len=0;
	   
	   get_X_bits_checksc_init();
	   
	   /* the all_zero flag for luminance */
	   all_zero=get_X_bits_checksc(1);
	   
	   /* first put all the data in SPlayer[0] */
	   /* the separation of the color components bitstreams will
	      be done by the decoding process */
	   
	   if ((splev==mzte_codec.wvtDecompLev-1)&&
	       (snrlev == Snrlevels-1))
	     len=get_allbits_checksc(buffer);
	   
	   else{
	     if ((!mzte_codec.SNR_start_code_enable) /* only one bitstream */
		 || (snrlev==Snrlevels-1))
	       {
		 /* look for the next spatial layer start code */
		 while(1){
		   /* chekc for the next start code*/
		   if(!Is_startcode(TEXTURE_SPATIAL_LAYER_START_CODE)){
		     buffer[len] = get_X_bits_checksc(8);
		     len++;
		   }
		   else{
		     buffer[len++]=align_byte_checksc();
		     break; /* start code found */
		   }
		 } /* end of while */
	       }
	     else{
	       while(1){
		 /* chekc for the next start code*/
		 if(!Is_startcode(texture_snr_layer_start_code)){
		   buffer[len] = get_X_bits_checksc(8);
		   len++;
		 }
		 else{
		   buffer[len++]=align_byte_checksc();
		   break; /* start code found */
		 }
	       } /* end of while(1) */
	     } /* end of if(!mzte_...) */
	   } /* end of if(splev== ...) */
	   
	   SPlayer[0][splev].SNRlayer[snrlev].snr_bitstream.length = len;
	   SPlayer[0][splev].SNRlayer[snrlev].snr_bitstream.data =
	     (Char *)calloc(len+2,sizeof(Char));
	   
	   memcpy(SPlayer[0][splev].SNRlayer[snrlev].snr_bitstream.data,
		  buffer,len);
	   
	   if(DEBUG_BS_DETAIL)
	     for(n=0;n<len;n++)
	       fprintf(stdout,"%d ", 
		       ((UChar *)SPlayer[0][splev].SNRlayer[snrlev].snr_bitstream.data)[n]);
	   
	   
	 }  /* snr levels */       
       }  /* spatial levels */
     
     for(color=0;color<mzte_codec.colors;color++) {
       h = SPlayer[color][0].SNRlayer[0].snr_image.height;
       w = SPlayer[color][0].SNRlayer[0].snr_image.width;    
       
       if ((SPlayer[color][0].SNRlayer[0].snr_image.data = calloc(h*w, sizeof(WINT)))
	   == NULL){
	 noteError ("Can not allocate memory in Init_PEZWdata()");
	 exit(-1);
       }
       
       /*  malloc and set mask */
       if ((SPlayer[color][0].SNRlayer[0].snr_image.mask = calloc(h*w, sizeof(UChar)))
	   == NULL)
	 {
	   noteError ("Can not allocate memory in Init_PEZWdata()");
	   exit(-1);  
	 }
       for( i = 0 ; i < h ; i++ ) 
	 for( j = 0 ; j < w ; j++ ) 
	   SPlayer[color][0].SNRlayer[0].snr_image.mask[i*w+j] 
	     = mzte_codec.SPlayer[color].coeffinfo[i][j].mask;
     }
   }
   else /* scan_order == 0 */
     {
       /* get the quantization step sizes */
       for (color=0;color<mzte_codec.colors;color++){
	 do {
	   q = get_X_bits(8);
	   Quant[color] <<= 7;
	   Quant[color] += q%128;
	 } while (q>=128);
       }
       
       /* get the snr scalability levels 
	  this is the maximum level for all three color components,
	  it will be adjusted later on according to all_zero flag */
       
       snr_scalability_levels = get_X_bits(5);
       
       /* get the snr layer */
       if (mzte_codec.SNR_start_code_enable)
	 Snrlevels=snr_scalability_levels;
       else
	 Snrlevels=1;
       
       for (color=0;color<mzte_codec.colors;color++){
	 /* allocate SNR data structure */
	 for (splev=0;splev<mzte_codec.wvtDecompLev;splev++)
	   {
	     SPlayer[color][splev].SNR_scalability_levels = snr_scalability_levels;
	     
	     SPlayer[color][splev].SNRlayer = (PEZW_SNR_LAYER *)
	       calloc(snr_scalability_levels, sizeof(PEZW_SNR_LAYER));
	     SPlayer[color][splev].SNRlayer[0].Quant = Quant[color];
	     
	     if (color==0){
	       SPlayer[color][0].SNRlayer[0].snr_image.height = h;
	       SPlayer[color][0].SNRlayer[0].snr_image.width =  w;
	     }
	     else{
	       SPlayer[color][0].SNRlayer[0].snr_image.height = h/2;
	       SPlayer[color][0].SNRlayer[0].snr_image.width =  w/2;
	     }
	   }
       } /* end of color */
       
       
       for (snrlev=0;snrlev<Snrlevels;snrlev++) 
	 {
	   /* check start code */      
	   align_byte1();
	   snr_layer_start_code = get_X_bits(32);
	   if (snr_layer_start_code != texture_snr_layer_start_code)
	     errorHandler("Wrong texture_snr_layer_start_code.");
	   snr_id = get_X_bits(5);
	   
	   for (splev=0;splev<mzte_codec.wvtDecompLev;splev++)
	     {
	       if (mzte_codec.SNR_start_code_enable)
		 {
		   align_byte1();
		   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.");
		   spatial_id = get_X_bits(5);
		 }
	       len=0;
	       
	       get_X_bits_checksc_init();
	       
	       /* the all_zero flag for luminance */
	       all_zero=get_X_bits_checksc(1);
	       
	       /* first put all the data in SPlayer[0] */
	       /* the separation of the color components bitstreams will
		  be done by the decoding process */
	       
	       if ((splev==mzte_codec.wvtDecompLev-1)&&
		   (snrlev == Snrlevels-1))
		 len=get_allbits_checksc(buffer);
	       else{
		 if ((!mzte_codec.SNR_start_code_enable) /* only one bitstream */
		     || (splev==mzte_codec.wvtDecompLev-1))
		   {
		     /* look for the next spatial layer start code */
		     while(1){
		       /* chekc for the next start code*/
		       if(!Is_startcode(texture_snr_layer_start_code)){
			 buffer[len] = get_X_bits_checksc(8);
			 len++;
		       }
		       else{
			 buffer[len++]=align_byte_checksc();
			 break; /* start code found */
		       }
		     } /* end of while */
		   }
		 else{
		   while(1){
		     /* chekc for the next start code*/
		     if(!Is_startcode(TEXTURE_SPATIAL_LAYER_START_CODE)){
		       buffer[len] = get_X_bits_checksc(8);
		       len++;
		     }
		     else{
		       buffer[len++]=align_byte_checksc();
		       break; /* start code found */
		     }
		   } /* end of while(1) */
		 } /* end of if(!mzte_...) */
	       } /* end of if(splev== ...) */
	       
	       SPlayer[0][splev].SNRlayer[snrlev].snr_bitstream.length = len;
	       
	       SPlayer[0][splev].SNRlayer[snrlev].snr_bitstream.data =
		 (Char *)calloc(len+2,sizeof(Char));
	       
	       memcpy(SPlayer[0][splev].SNRlayer[snrlev].snr_bitstream.data,
		      buffer,len);
	       
	       if(DEBUG_BS_DETAIL)
		 for(n=0;n<len;n++)
		   fprintf(stdout,"%d ", 
			   ((UChar *)SPlayer[0][splev].SNRlayer[snrlev].snr_bitstream.data)[n]);
	       
	     }  /* spatial levels */       
	 }  /* snr levels */
       
       for(color=0;color<mzte_codec.colors;color++) {
	 h = SPlayer[color][0].SNRlayer[0].snr_image.height;
	 w = SPlayer[color][0].SNRlayer[0].snr_image.width;    
	 
	 if ((SPlayer[color][0].SNRlayer[0].snr_image.data = calloc(h*w, sizeof(WINT)))
	     == NULL){
	   noteError ("Can not allocate memory in Init_PEZWdata()");
	   exit(-1);
	 }
	 
	 /*  malloc and set mask */
	 if ((SPlayer[color][0].SNRlayer[0].snr_image.mask = calloc(h*w, sizeof(UChar)))
	     == NULL){
	   noteError ("Can not allocate memory in Init_PEZWdata()");
	   exit(-1);
		  
	 }
	 for( i = 0 ; i < h ; i++ ) 
	   for( j = 0 ; j < w ; j++ ) 
				SPlayer[color][0].SNRlayer[0].snr_image.mask[i*w+j] 
				  = mzte_codec.SPlayer[color].coeffinfo[i][j].mask;
       }
       
     } /* end of else scan_order */
}

/* left shift a stream by N<8 bits */

Int lshift_by_NBit (UChar *data, Int len, Int N)
{
  Int n;
  Char mask=0;
  Int output;
  
  if(len==0)
    return 1;
  
  output = data[0]>>(8-N);
  
  for(n=0;n<N;n++)
    mask = (mask<<1) | 0x01;
  
  for (n=0;n<len-1;n++)
    data[n] = (data[n]<<N) | ((data[n+1]>>(8-N)) & mask);
  
  data[len-1] <<= N;
  
  return output;
}


/* free up memory at the encoder */
Void PEZW_freeEnc (PEZW_SPATIAL_LAYER **SPlayer)
{
  Int levels;
  Int col, l;
  Int snrlev;
  
  for (col=0; col<mzte_codec.colors; col++)
    {
      /* free the image buffer */
      free(SPlayer[col][0].SNRlayer[0].snr_image.data);
      
      /* free the mask buffer */
      free(SPlayer[col]->SNRlayer[0].snr_image.mask);	
      
      if (col ==0) 
	levels = mzte_codec.wvtDecompLev;
      else
	levels = mzte_codec.wvtDecompLev-1;
      
      /* free the SNR layer */
      for(l=0;l<levels;l++){
	for (snrlev=0;snrlev<SPlayer[col][l].SNR_scalability_levels;
	     snrlev++)
	  if(SPlayer[col][l].SNRlayer[snrlev].snr_bitstream.data!=NULL)
	    free(SPlayer[col][l].SNRlayer[snrlev].snr_bitstream.data);
	
	free(SPlayer[col][l].SNRlayer);
      }
      
      /* free SPlayer */
      free(SPlayer[col]);
    }
  
  /* parameters for inverse wvt */
  mzte_codec.spatial_scalability_levels = mzte_codec.target_spatial_levels;
}



Void PEZW_freeDec (PEZW_SPATIAL_LAYER **SPlayer)
{
  Int levels;
  Int col, l;
  Int snrlev;
  
  for (col=0; col<mzte_codec.colors; col++)
    {
      /* free the image buffer */
      free(SPlayer[col][0].SNRlayer[0].snr_image.data);
      
      /* free the mask buffer */
	  free(SPlayer[col][0].SNRlayer[0].snr_image.mask );
	  
	  if (col ==0) 
	    levels = mzte_codec.wvtDecompLev;
	  else
	    levels = mzte_codec.wvtDecompLev-1;
      
	  /* free the SNR layer */
	  for(l=0;l<levels;l++){
	    if (!mzte_codec.SNR_start_code_enable)
	      free(SPlayer[col][l].SNRlayer[0].snr_bitstream.data);
	    else {
	      if (col==0){
		for (snrlev=0;snrlev<SPlayer[col][l].SNR_scalability_levels;
		     snrlev++)
		  if(SPlayer[col][l].SNRlayer[snrlev].snr_bitstream.data!=NULL)
		    free(SPlayer[col][l].SNRlayer[snrlev].snr_bitstream.data);
	      }
	    }
	  }
    }
  
  
  /* free SNRlayer */
  levels = mzte_codec.wvtDecompLev;
  for (col=0; col<mzte_codec.colors; col++)
    for(l=0;l<levels;l++)
      free(SPlayer[col][l].SNRlayer);
  
  /* free SPlayer */
  for (col=0; col<mzte_codec.colors; col++)
    free(SPlayer[col]);
}


