/****************************************************************************/
/*   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, 1998 Texas Instruments   		            */
/****************************************************************************/

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

#include "wvtPEZW.h"
#include "PEZW_zerotree.h"


Ac_model dom_pass, dom_pass2, sub_pass, end_pass;

/* model for dominant pass */
static Int freq_dom[No_of_symbols] = {1, 1, 1, 1, 0};


/* model for subordinate pass */
static Int freq_sub[No_of_symbols] = {1, 1, 0, 0, 0};

/* model for sending the EOF symbol */
static Int freq_end[No_of_symbols] = {0, 0, 0, 4, 1};


/* context models */

static Int freq_dom_IZER[No_of_symbols] =   {1, 1, 0, 0, 0};     
static Int freq_dom_ZTRZ[No_of_symbols] =   {1, 1, 1, 1, 0};     

/* model specific for last level of dominant pass encoding */
/* no zerotree possible */
static Int freq_dom2_IZER[No_of_symbols] =  {1, 1, 0, 0, 0};


Void WvtPEZW_Spatial_SNR (Int levels, PEZW_SPATIAL_LAYER *SPlayer, 
			  Int minthresh,   Int SNR_Len_Enable)
{
  WINT *input;
  UChar *labelimage;
  UChar *mask;			
  Short *valueimage;
  Int i,j,l, band;
  Short maxvalue, temp;
  Int currenthsize, currentvsize, xcorner, ycorner;
  Int ch; Int symbol;
  Int countIZER=0;
  Int countIVAL=0;
  Int countZTRZ=0;
  Int countZTRV=0;
  Int cIZ[No_of_contexts];
  Int cIS[No_of_contexts];
  Int cZTRZ[No_of_contexts];
  Int cZTRS[No_of_contexts];
 
  Int abovethresh;
  Int hsize, vsize;
  Int thresh, currthresh, maxsize;
  Int *sizes, *SPsizes;
  UChar **currbuff;
  UChar **outputstream;
  Int m,n,k,blocksize;
  Int SNR_levels=0;
  Int SNRlev;

  Ac_encoder *AC_encoder;
  Int IsStream = 1;
  Ac_model model, model_sign;
  Int nsym=No_of_symbols, adapt=1;
  Int Noadapt=0;

  Int FirstLevFlag = 1;
  
  UChar Label, *prev_labelimage;
  Ac_model *modelptr;
  Ac_model model_context[No_of_contexts];
  Ac_model model_sub, model_end;
  Int context, context1, context2, context3;
  Int *freq=NULL;

  AC_encoder = (Ac_encoder *)calloc(levels, sizeof(Ac_encoder));

  /* currbuff store the current pointer in buffer */
  currbuff = (UChar **) calloc(levels, sizeof (Char *));
  outputstream = (UChar **) calloc(levels, sizeof (Char *));
  sizes = (Int *) calloc(levels, sizeof(Int));
  SPsizes = (Int *) calloc(levels, sizeof(Int));
  for (i=0;i<levels;i++){
      currbuff[i]=(UChar *) 
	     calloc (MAXZTRBUFFER, sizeof(Char));
      outputstream[i]=currbuff[i];
  }

  maxsize =MAXSIZE;

  /* get the image size */
  input = SPlayer[0].SNRlayer[0].snr_image.data;
  mask  = SPlayer[0].SNRlayer[0].snr_image.mask;	
  hsize = SPlayer[0].SNRlayer[0].snr_image.width;
  vsize = SPlayer[0].SNRlayer[0].snr_image.height;

  if ((labelimage = (UChar *) calloc(hsize*vsize, sizeof(Char)))==NULL)
    {fprintf(stderr,"ERROR Unable to allocate labelimage in encode\n");
     exit(1);}
  if ((valueimage = (Short *) calloc(hsize*vsize, sizeof(Short)))==NULL)
    {fprintf(stderr,"ERROR Unable to allocate valueimage in encode\n");
     exit(1);}

  /* initialized the context image */
  if ((prev_labelimage = (UChar *) calloc(hsize*vsize, sizeof(Char)))==NULL)
    {fprintf(stderr,"ERROR Unable to allocate labelimage in encode\n");
     exit(1);}
  for (i=0; i<hsize*vsize; i++){
      prev_labelimage[i]=DZ;
      labelimage[i]= (mask[i]) ? Z : SKPZTR ;	
  }

  /* set up buffer for coding */
  /* initialization */
  Ac_model_init (&model, nsym, freq_dom, Max_frequency_TI, adapt);
  Ac_model_init (&model_sign, nsym, freq_sub, Max_frequency_TI, Noadapt);
  Ac_model_init (&model_sub, nsym,  freq_sub, Max_frequency_TI, adapt);
  Ac_model_init (&model_end, nsym,  freq_end, Max_frequency_TI, adapt);
                         
  /* initialize the arithmetic codec */
  for (j=levels;j>=1;j--)                   /* subband */
      for (i=0;i<No_of_states_context1;i++)         /* parent node */
	  for (l=0;l<No_of_states_context0;l++){    /* previous label */
	      context = (j-1)*No_of_states_context0*No_of_states_context1+i*No_of_states_context0+l;
	      if (j==1){
		      freq = freq_dom2_IZER;
		      adapt= 1;                   
	      }
	      else{
		  if (l==IZER){
		      freq = freq_dom_IZER;
		      adapt= 1;                   
		  }
		  else if (l==ZTRZ){
		      freq = freq_dom_ZTRZ;       
		      adapt= 1;
		  }
		  else if (l==DS){                
		      freq = freq_dom_ZTRZ;
		      adapt= 1;
		  }
		  else if (l==DZ){                
		      freq = freq_dom_ZTRZ;
		      adapt= 1;
		  }
	      }
		  
	      Ac_model_init (&model_context[context], nsym, freq, Max_frequency_TI, adapt);
	  }
  
  for (i=0;i<No_of_contexts;i++){
    cIZ[i]=0; cIS[i]=0; cZTRZ[i]=0; cZTRS[i]=0;
  }
  
  /* Find max value, determine initial threshold */
  maxvalue = 0; 
  for(i = 0; i < vsize; i++)
    for(j = 0; j < hsize; j++)
      if ((i>=(vsize/(1<<levels))) || (j>=(hsize/(1<<levels))))
	{
	  temp = ABS(input[i*hsize+j]);
	  if (temp > maxvalue)
	    maxvalue = temp;
	} 
  
  thresh = minthresh;
  while (maxvalue >= 2 * (thresh))
    thresh *= 2;
  
  currthresh = thresh;	
  
  for (i=0, abovethresh=0; i<hsize*vsize; i++)
    {
      if(ABS(input[i]) >= thresh)
	abovethresh++;
    }
  /* loop: 
     mark all non-SIG coeffs exceeding thresh with T 
     in scanning order, encode string of specifications 
     output extra bits for all significants 
     decrease threshold and repeat */
  
  while (currthresh >= minthresh)
    {
      /* DOMINANT PASS */
      
      /* all non-SIG (not POS or NEG) coeffs that exceed current */
      /* threshold are marked with T */
      for (i=0; i<hsize*vsize; i++)
	if ( (mask[i]) && (!valueimage[i]) &&	
	     (ABS(input[i]) >= currthresh))
	  {labelimage[i] = IVAL;}
      
      if (FirstLevFlag){
	for (i=0; i<levels; i++)
	  Ac_encoder_init (&AC_encoder[i], outputstream[i], IsStream);
      }
      
	FirstLevFlag = 0;
	
	/* next determine where the zero trees are */
	/* first look from high subbands to next lower subbands */
	for (l=1; l< levels; l++)
	  {
	    currenthsize = hsize/(1<<l);
	    currentvsize = vsize/(1<<l);
	    
	  for (band=0; band<3; band++)
	    {
	      if (band==0)	
		{ xcorner = currenthsize;       ycorner = 0;}
	      else if (band==1)	
		{ xcorner = 0; ycorner = currentvsize;}
	      else		
		{ xcorner = currenthsize; ycorner = currentvsize;}
	      for (i=ycorner; i<ycorner+currentvsize; i=i+2)
		for (j=xcorner; j<xcorner+currenthsize; j=j+2)
		  {
		    if (((labelimage[i*hsize+j] == Z) || 
			 (labelimage[i*hsize+j] == SKPZTR) ||	
			 (labelimage[i*hsize+j] == ZTRZ)) &&
			((labelimage[i*hsize+j+1] == Z) || 
			 (labelimage[i*hsize+j+1] == SKPZTR) ||	
			 (labelimage[i*hsize+j+1] == ZTRZ)) &&
			((labelimage[i*hsize+hsize+j] == Z) ||
			 (labelimage[i*hsize+hsize+j] == SKPZTR) ||	
			 (labelimage[i*hsize+hsize+j] == ZTRZ)) &&
			((labelimage[i*hsize+hsize+j+1] == Z) ||
			 (labelimage[i*hsize+hsize+j+1] == SKPZTR) ||	
  			 (labelimage[i*hsize+hsize+j+1] == ZTRZ)))
		      {
			if (labelimage[i/2*hsize+j/2] == Z)
			    labelimage[i/2*hsize+j/2] = ZTRZ;
			else if (labelimage[i/2*hsize+j/2] == IVAL)
			    labelimage[i/2*hsize+j/2] = ZTRV;
			else if (labelimage[i/2*hsize+j/2] == SKIP)
			    labelimage[i/2*hsize+j/2] = SKPZTR;

			if ((labelimage[i/2*hsize+j/2] == ZTRZ) || (labelimage[i/2*hsize+j/2] == ZTRV))  
			{
			    Label = (labelimage[i/2*hsize+j/2] == ZTRZ) ? DZ: DS;
				  
			    blocksize = 1;
			    for (m=l; m>=1; m--)
			      {
				blocksize += blocksize;	/* mult x 2 */
				for (k=0;k<blocksize;k++)
				  for (n=0; n<blocksize;n++)
				    if ( (labelimage[((i/2*blocksize)+k)*hsize+(j/2*blocksize)+n] != S) &&
						(labelimage[((i/2*blocksize)+k)*hsize+(j/2*blocksize)+n] != SKPZTR) )	
					labelimage[((i/2*blocksize)+k)*hsize+(j/2*blocksize)+n]=Label;
			      }	/* end for m */
			}
		      }

		      else if (labelimage[i/2*hsize+j/2] == Z)
			  labelimage[i/2*hsize+j/2] = IZER;
		      else if (labelimage[i/2*hsize+j/2] == S)
			  labelimage[i/2*hsize+j/2] = IS;
		      else if (labelimage[i/2*hsize+j/2] == SKPZTR)		
			  labelimage[i/2*hsize+j/2] = SKIP;
		  }
	    }
	}

      /* next go from lower high subbands to higher subbands */
      for (l=levels; l>=1; l--)
	{
	  currenthsize = hsize/(1<<l);
	  currentvsize = vsize/(1<<l);

	  for (band=0; band<3; band++)
	    {
	      if (band==0)	  /* horiz */
		{  xcorner = currenthsize;       ycorner = 0;}
	      else if (band==1)	/* vert */
		{  xcorner = 0; ycorner = currentvsize;	}
	      else		/* diag */
		{ xcorner = currenthsize; ycorner = currentvsize;}

	      for (i=ycorner; i<ycorner+currentvsize; i++)
		for (j=xcorner; j<xcorner+currenthsize; j++)
		  {
		      /* decide about the context */
		      context1 = prev_labelimage[i*hsize+j];	
		      context3 = l-1;
		      context2=0;
		      context =  context3*No_of_states_context0*No_of_states_context1+
			         context2*No_of_states_context0+context1;
		      modelptr = &model_context[context];

		      /* copy the current image to prev_labelimage[] */
		      prev_labelimage[i*hsize+j]=labelimage[i*hsize+j];   

		      if (labelimage[i*hsize+j] == IVAL) {
		      countIVAL++; cIS[context]++;
		      labelimage[i*hsize+j] = S; 
		      prev_labelimage[i*hsize+j]=IVAL;

		      if ((context1 != IZER)&&(context1 != ZTRZ)&&(context1 != DS)&&(context1 != DZ))
			  {
			      printf("error, context1= %d\n", context1);
			      exit(-1);
			  }

		      ch = IVAL; symbol = ch;
		      Ac_encode_symbol(&AC_encoder[l-1], modelptr, symbol); 
		      if (AC_encoder[l-1].stream-outputstream[l-1] >= maxsize) goto cleanup;

		      if (input[i*hsize+j] >= currthresh)
			{
			 valueimage[i*hsize+j] += currthresh;
			 valueimage[i*hsize+j] += currthresh/2;

			 ch = 1;    symbol = ch;
			 Ac_encode_symbol(&AC_encoder[l-1], &model_sign, symbol); 
			 if (AC_encoder[l-1].stream-outputstream[l-1] >= maxsize) goto cleanup;
			}
		      else 
			{
			 valueimage[i*hsize+j] -= currthresh;
			 valueimage[i*hsize+j] -= currthresh/2;

			 ch = 0;    symbol = ch;
			 Ac_encode_symbol(&AC_encoder[l-1], &model_sign, symbol); 
			 if (AC_encoder[l-1].stream-outputstream[l-1] >= maxsize) goto cleanup;
			}
		    }
  		    else if (labelimage[i*hsize+j] == ZTRV) {
		      countZTRV++; cZTRS[context]++;
		      labelimage[i*hsize+j] = S;  
		      prev_labelimage[i*hsize+j]=ZTRV;

		      if ((context1 != IZER)&&(context1 != ZTRZ)&&(context1 != DS)&&(context1 != DZ))
			  {
			      printf("error, context1= %d\n", context1);
			      exit(-1);
			  }

		      ch = ZTRV; symbol = ch;
		      Ac_encode_symbol(&AC_encoder[l-1], modelptr, symbol); 
		      if (AC_encoder[l-1].stream-outputstream[l-1] >= maxsize) goto cleanup;

		      if (input[i*hsize+j] >= currthresh){
			  valueimage[i*hsize+j] += currthresh;
			  valueimage[i*hsize+j] += currthresh/2;
			  ch = 1;    symbol = ch;
		      }
		      else {
			  valueimage[i*hsize+j] -= currthresh;
			  valueimage[i*hsize+j] -= currthresh/2;
			  ch = 0;    symbol = ch;
		      }

		      Ac_encode_symbol(&AC_encoder[l-1], &model_sign, symbol); 
		      if (AC_encoder[l-1].stream-outputstream[l-1] >= maxsize) goto cleanup;
		    }
		    else if ((labelimage[i*hsize+j] == ZTRZ))
		      {countZTRZ++; cZTRZ[context]++;
		       ch = ZTRZ; symbol = ch;

		      if ((context1 != IZER)&&(context1 != ZTRZ)&&(context1 != DS)&&(context1 != DZ))
			  {
			      printf("error, context1= %d\n", context1);
			      exit(-1);
			  }

		       labelimage[i*hsize+j] = Z; /* reinit for next loop */ 
		       prev_labelimage[i*hsize+j]=ZTRZ;

		       Ac_encode_symbol(&AC_encoder[l-1], modelptr, symbol); 
		       if (AC_encoder[l-1].stream-outputstream[l-1] >= maxsize) goto cleanup;}
		    else if ((labelimage[i*hsize+j] == IZER) ||
			     (labelimage[i*hsize+j] == Z) )
		      {ch = IZER; symbol = ch;

		      if ((context1 != IZER)&&(context1 != ZTRZ)&&(context1 != DS)&&(context1 != DZ))
			  {
			      printf("error, context1= %d\n", context1);
			      exit(-1);
			  }

		      countIZER++; cIZ[context]++;
		      labelimage[i*hsize+j] = Z; /* reinit for next loop */ 
		      prev_labelimage[i*hsize+j]=IZER;

		      Ac_encode_symbol(&AC_encoder[l-1], modelptr, symbol); 
		      if (AC_encoder[l-1].stream-outputstream[l-1] >= maxsize) goto cleanup;}

		      /* do nothing if not symbols needed to be sent to the decoder */
		      if(labelimage[i*hsize+j]==DZ)
			labelimage[i*hsize+j]=Z;
		      else if(labelimage[i*hsize+j]==DS)
			labelimage[i*hsize+j]=Z;
		      else if(labelimage[i*hsize+j]==IS)
			labelimage[i*hsize+j]=S;
		  }   
	    } /* for band */

	  /* reinitialize the models   */
	  AC_free_model (&model_sign);
	  Ac_model_init (&model_sign, nsym, freq_sub, Max_frequency_TI, Noadapt);


	} /* end for l */

     if (DEBUG_ZTR_CONTEXTS){
	printf("\n stats for this pass:");
	for (i=0;i<levels;i++)
	  for (l=0;l<No_of_states_context1;l++){
	    for (j=0; j<No_of_states_context0; j++){
	      context=i*No_of_states_context0*No_of_states_context1+l*No_of_states_context0+j;
	      printf("\n context %d: IZER %d IVAL %d ZTRZ %d ZTRV %d", context, cIZ[context], 
		     cIS[context], cZTRZ[context], cZTRS[context]);
	    }
	    printf("\n");
	  }
     }

     if (DEBUG_ZTR)
       printf("overrall ZEROTREE STAT: IZER %d IVAL %d ZTRZ %d ZTRV %d \n", 
	      countIZER, countIVAL, countZTRZ, countZTRV);
     
     currthresh /= 2;
     if (currthresh < minthresh){
	if (DEBUG_ZTR)
	  fprintf(stderr, "----EOF_symbol----- \n ");
	goto cleanup;
     }
     else{
       for (i=0;i<levels;i++){
	 /* set up the arithmetic coder */
	 AC_free_model (&model);
	 Ac_model_init (&model, nsym, freq_end,  Max_frequency_TI, adapt);
	      Ac_encode_symbol (&AC_encoder[i], &model, CONTINUE_symbol);   
       }
     }
     
     /* reach end of bitplane */
     if (SNR_Len_Enable){
       for (i=0;i<levels;i++){  
	 Ac_encoder_done (&AC_encoder[i]);
	 sizes[i] = (AC_encoder[i].stream - outputstream[i])*8;
	 SPsizes[i] += sizes[i];
	 if (DEBUG_ZTR_DETAILS)
	   fprintf(stderr, "\n SP Layer %d SNR layer %d: sizes- %d SPsizes- %d", i, SNR_levels, sizes[i], SPsizes[i]);
		}
     } 
     
     /* creat the SPlayer.SNRlayer data structure */
     SNR_levels++;
     if (SNR_Len_Enable){
       for (i=0;i<levels; i++){
			(SPlayer[levels-i-1].SNRlayer)[SNR_levels-1].snr_bitstream.length =
			  sizes[i]/8;
			
			(SPlayer[levels-i-1].SNRlayer)[SNR_levels-1].snr_bitstream.data =
			  calloc(sizes[i]/8,sizeof(Char));
			memcpy((SPlayer[levels-i-1].SNRlayer)[SNR_levels-1].snr_bitstream.data, outputstream[i],sizes[i]/8);	 
			
			SPlayer[levels-i-1].SNR_scalability_levels = SNR_levels;
       }
       
       /* reset the bitstream buffer */
		for (i=0; i<levels; i++)
		  Ac_encoder_init (&AC_encoder[i], outputstream[i], IsStream);
     }
     
     /* initialize the arithmetic codec */
	for (j=levels;j>=1;j--)                   /* subband */
	  for (i=0;i<No_of_states_context1;i++)         /* parent node */
	    for (l=0;l<No_of_states_context0;l++){    /* previous label */
	      context = (j-1)*No_of_states_context0*No_of_states_context1+i*No_of_states_context0+l;
	      if (j==1){
		freq = freq_dom2_IZER;
		adapt= 1;                   
	      }
	      else{
		if (l==IZER){
		  freq = freq_dom_IZER;
		  adapt= 1;                   
		}
		else if (l==ZTRZ){
		  freq = freq_dom_ZTRZ;       
		  adapt= 1;
		  }
		else if (l==DS){                
		  freq = freq_dom_ZTRZ;
		  adapt= 1;
		}
		else if (l==DZ){                
		  freq = freq_dom_ZTRZ;
		  adapt= 1;
		}
	      }
	      
	      AC_free_model (&model_context[context]);	
	      Ac_model_init (&model_context[context], nsym, freq, Max_frequency_TI, adapt);
	    }
	
	
      /* SUBORDINATE PASS */
      /* Now send bits for all significant numbers in scanning order*/
      /* unless currthresh is < 1*/

      if (currthresh >= 1)
	{
	  /* reset model since subordinate pass has different statistics */
	   AC_free_model (&model);
	   Ac_model_init (&model, nsym, freq_sub, Max_frequency_TI, adapt);
	  
	  /* next go from lower high subbands to higher subbands */
	  for (l=levels; l>=1; l--)
	    {
	      currenthsize = hsize/(1<<l);
	      currentvsize = vsize/(1<<l);

	      for (band=0; band<3; band++)
		{
		  if (band==0)	  /* horiz */
		    {  xcorner = currenthsize;       ycorner = 0;}
		  else if (band==1)	/* vert */
		    {  xcorner = 0; ycorner = currentvsize;	}
		  else		/* diag */
		    { xcorner = currenthsize; ycorner = currentvsize;}
		  
		  for (i=ycorner; i<ycorner+currentvsize; i++)
		    for (j=xcorner; j<xcorner+currenthsize; j++)
		    {
		      if (valueimage[i*hsize+j] > 0)
			{
			  if (input[i*hsize+j] >= valueimage[i*hsize+j])
			    { ch = 1;
			      valueimage[i*hsize+j] += currthresh/2; }
			  else
			    { ch = 0;
			      valueimage[i*hsize+j] -= currthresh/2; }
			  symbol = ch;
			  Ac_encode_symbol(&AC_encoder[l-1], &model, symbol);
			  if (AC_encoder[l-1].stream-outputstream[l-1] >= maxsize) goto cleanup;
			}
		      else if (valueimage[i*hsize+j] < 0)
			{
			  if ((input[i*hsize+j]) <= valueimage[i*hsize+j])
			    { ch = 1;
			      valueimage[i*hsize+j] -= currthresh/2; }
			  else
			    { ch = 0;
			      valueimage[i*hsize+j] += currthresh/2; }
			  symbol = ch;
			  Ac_encode_symbol(&AC_encoder[l-1], &model, symbol);
			  if (AC_encoder[l-1].stream-outputstream[l-1] >= maxsize) goto cleanup;
			}
		     }
		} /* end for band */
	      
	      sizes[l-1] = (AC_encoder[l-1].stream - outputstream[l-1])*8;
	      
	    } /* end for l */
	} /* end if currenthresh */
      
    } /* end threshold loop */
  
 cleanup:
  
  for (i=0;i<levels;i++){
    
    /* set up the arithmetic coder */
    AC_free_model (&model);
    Ac_model_init (&model, nsym, freq_end,  Max_frequency_TI, adapt);
    Ac_encode_symbol (&AC_encoder[i], &model, EOF_symbol);  
    Ac_encoder_done (&AC_encoder[i]);
      sizes[i] = (AC_encoder[i].stream - outputstream[i])*8;
      SPsizes[i] += sizes[i];
      
      if (DEBUG_ZTR_DETAILS)
	printf("SP Layer %d SNR layer %d: sizes- %d SPsizes- %d\n", i, 
	       SNR_levels, sizes[i],  SPsizes[i]);
  }
  
  /* creat the SPlayer.SNRlayer data structure */
  SNR_levels++;
  if (SNR_Len_Enable)
    SNRlev = SNR_levels;
  else
    SNRlev = 1;
  
  for (i=0;i<levels; i++){
    (SPlayer[levels-i-1].SNRlayer)[SNRlev-1].snr_bitstream.length =
      sizes[i]/8;

    (SPlayer[levels-i-1].SNRlayer)[SNR_levels-1].snr_bitstream.data =
      calloc(sizes[i]/8,sizeof(Char));
    memcpy((SPlayer[levels-i-1].SNRlayer)[SNR_levels-1].snr_bitstream.data, outputstream[i],sizes[i]/8);	 
    
    SPlayer[levels-i-1].SNR_scalability_levels = SNR_levels;
  }
  
  /* change values to output values */
  for(i = 0; i < vsize; i++){
    for(j = 0; j < hsize; j++)
      if ((i>=(vsize/(1<<levels))) || (j>=(hsize/(1<<levels))))
	{
	  if (valueimage[i*hsize+j] != 0)
	    input[i*hsize+j] = valueimage[i*hsize+j];
	  else
	    input[i*hsize+j] = 0;
	}
  }
  
  if (DEBUG_ZTR_DETAILS){
    fprintf(stderr, "\n After zerotree coding:\n");
    for(i = 0; i < vsize; i++){
      for(j = 0; j < hsize; j++)
	fprintf(stderr, "%3d ", input[i*hsize+j]);
      fprintf(stderr, "\n");
    }
    
    printf("\nSpatial scalability level: %d", levels);
    printf("\nStopped encoding with threshold = %d\n", currthresh);
    countIZER =0;
    for (l=0;l<levels;l++)
      countIZER += SPsizes[l];
    printf("\ntotal bits coded for this channel: %d\n", countIZER);
  }
  
  
  /* NEED TO FREE CALLOC SPACE */
  free(labelimage);
  free(prev_labelimage);
  free(valueimage);
  free(AC_encoder);
  
  for(i=0;i<levels;i++)
    free(currbuff[i]);
  
  free(outputstream);
  free(currbuff);

  
  AC_free_model(&model);
  AC_free_model(&model_sign);
  AC_free_model(&model_sub);
  AC_free_model(&model_end);
  for (j=levels;j>=1;j--)                   /* subband */
    for (i=0;i<No_of_states_context1;i++)         /* parent node */
      for (l=0;l<No_of_states_context0;l++){    /* previous label */
	context = (j-1)*No_of_states_context0*No_of_states_context1+i*No_of_states_context0+l;
	
	AC_free_model (&model_context[context]);
      }
  
  /* parameters */
  for (i=0; i<levels; i++){
    SPlayer[levels-i-1].SNRlayer->Quant                =  thresh;
    SPlayer[levels-i-1].spatial_bitstream_length       =  SPsizes[i]/8;
    SPlayer[levels-i-1].SNR_scalability_levels         =  SNR_levels;
  }
  
  if(DEBUG_ZTR)
    fprintf(stdout,"\nQuant: %d\n",thresh);
  
  free(SPsizes);
  free(sizes);

  return;
}

