/*****************************************************************************
 "This software module was originally developed by:

	Noboru Yamaguchi (TOSHIBA CORPORATION), 
	Takashi Ida (TOSHIBA CORPORATION) 

	and edited by:

 	Toshiaki Watanabe (TOSHIBA CORPORATION), 
	Yoshihiro Kikuchi (TOSHIBA CORPORATION), 
	Noel Brady (TELTEC IRELAND)

	in the course of development of the <MPEG-4 Video(ISO/IEC 14496-2)>. This
  software module is an implementation of a part of one or more <MPEG-4 Video
  (ISO/IEC 14496-2)> tools as specified by the <MPEG-4 Video(ISO/IEC 14496-2)
  >. ISO/IEC gives users of the <MPEG-4 Video(ISO/IEC 14496-2)> free license
  to this software module or modifications thereof for use in hardware or
  software products claiming conformance to the <MPEG-4 Video(ISO/IEC 14496-2
  )>. Those intending to use this software module in hardware or software
  products are advised that its use may infringe existing patents. The
  original developer of this software module and his/her company, the
  subsequent editors and their companies, and ISO/IEC have no liability for
  use of this software module or modifications thereof in an implementation.
  Copyright is not released for non <MPEG-4 Video(ISO/IEC 14496-2)>
  conforming products. TOSHIBA CORPORATION retains full right to use the code
  for his/her own purpose, assign or donate the code to a third party and to
  inhibit third parties from using the code for non <MPEG-4 Video(ISO/IEC
  14496-2)> conforming products. This copyright notice must be included in
  all copies or derivative works. Copyright (c)1996".
 *****************************************************************************/

/***********************************************************HeaderBegin*******
 *                                                                         
 * File:	alp_common_util.c
 *
 * Author:	TOSHIBA + Noel Brady (TELTEC) + Dae-Sung Cho (Samsung AIT)
 * Created:	11-04-97
 *                                                                         
 * Description: Contains utility functions required for encoding and
 *								decoding of binary shape as per VM8
 *
 * Modified: 
 *				10.11.97 Noel Brady: Changed filter table
 *                                 
 ***********************************************************HeaderEnd*********/


/********* include ********/

#include<stdio.h>

#ifndef WIN32
#include<values.h>
#endif

#include <string.h>
#include "momusys.h"
#include "alp_common_def.h" 
#include "alp_common_util.h"
#include "upsampling_th.h" /* SAIT */

#define LIMADRS(adrs,min,max)   ((adrs)<(min))?(min):(((adrs)>=(max))?((max)-1):(adrs))

/* SAIT begin */
/*** comment out
#define WEIGHT(a,b,c,d,e,f,g,h,i,j,k,l,t) ( (( 4*(a) + 2*((b)+(c)+(d)) + (e)+(f)+(g)+(h)+(i)+(j)+(k)+(l) )>(t))?1:0 )
***************/
#define WEIGHT(a,b,c,d,other,t) (((((a)<<2)+(((b)+(c)+(d))<<1)+(other))>(t))?1:0)
/* SAIT end */


Void StreamOut( UChar *stream, Int *total, Int *max_stream,
	       UChar *string)
{
  Int i;

  i = strlen(string);
  if (*total + i > *max_stream) {
    *max_stream += i;
    if ((stream = (UChar*)realloc(stream, (U_Int)(*max_stream)))
	== NULL)
      fprintf(stderr, "Cannot allocate memory 4 ...");
  }
  for (i = 0; i < strlen(string); i++)
    stream[*total + i] = string[i] - OFFSET;

  *total += strlen(string);
}

/***********************************************************CommentBegin******
 *
 * -- MedianFilterBAB -- implements the median filtering for 
 *												BAB upsampling
 *
 * Author :		
 *	Noel Brady Teltec Irl.
 *
 * Created :		
 *	11-04-97
 * 
 * Arguments In: 	
 *					vop - the reconstructed binary alpha map
 *					x,y - the top-left pixel coordinate of the BAB
 *
 * Arguments In/Out:
 *					alpha_mb - the upsampled BAB on input/
 *											median filtered on output
 *
 * Arguments Out:
 *
 * Return values :
 *
 * Side effects :	
 *	-
 *
 * Description : As per VM7
 *
 * See also :
 *
 ***********************************************************CommentEnd********/
Void MedianFilterBAB( Image *alpha, Int x, Int y, UChar *alpha_mb)
{
	UChar mb_in[(MB_SIZE+2)*(MB_SIZE+2)];
	Int i,j,k,l,
			size = MB_SIZE+2,
			xy_size = size*size;
	SInt *p;
	Image *top,
				*left;

	/* copy decoded pixels from above and left */
	top = AllocImage(size,1,SHORT_TYPE);
	GetSubImage(alpha,top,x-1,y-1);
	p = (SInt *) GetImageData(top);
	for (i=0;i<size;i++) mb_in[i] = f1bit(p[i]);
	FreeImage(top);
	
	left = AllocImage(1,MB_SIZE,SHORT_TYPE);
	GetSubImage(alpha,left,x-1,y);
	p = (SInt *) GetImageData(left);
	for (i=0,j=size;i<MB_SIZE;i++,j+=size) mb_in[j] = f1bit(p[i]);
	FreeImage(left);

	/* copy pixels from alpha_mb */
	k=0;
	for (i=1;i<size-1;i++)
		for (j=1;j<size-1;j++,k++)
			mb_in[i*size+j] = alpha_mb[k];

	/* replicate pixels along the bottom */
	for (	k=(size-1)*size;k<xy_size-1;k++)
		mb_in[k] = mb_in[k-size];

	/* replicate pixels along the right */
	for (	k=2*size-1;k<xy_size-1;k+=size)
		mb_in[k] = mb_in[k-1];

	mb_in[xy_size-1] = mb_in[xy_size-size-2];

	/* do the median filtering */
	k=0;
	for (i=1;i<size-1;i++)
		for (j=1;j<size-1;j++,k++) 
			{
				l = (i-1)*size+j-1;
				alpha_mb[k] = ((mb_in[l]+mb_in[l+1]+mb_in[l+2]
												+mb_in[l+size]+mb_in[l+size+1]+mb_in[l+size+2]
												+mb_in[l+2*size]+mb_in[l+2*size+1]+mb_in[l+2*size+2])>4);
			}
#if 0			
	for (i=0;i<MB_SIZE;i++,printf("\n")) 
		for (j=0;j<MB_SIZE;j++)
			printf("%d ",alpha_mb[i*MB_SIZE+j]);

	printf("\n");

	for (i=0;i<size;i++,printf("\n")) 
		for (j=0;j<size;j++)
			printf("%d ",mb_in[i*size+j]);
	
	getchar();
#endif
}


Void ChangeSamplingRate( UChar *buff, UChar *data,
			Int h_size, Int v_size, Int b_size, Int size )
{
Int i;

  if( b_size > size )
    DownSampling( buff, data, h_size, v_size, b_size, size );
  else if( b_size == size ) {
    for( i=0; i<h_size*v_size; i++ ) *(data+i) = *(buff+i);
  } else {
			UpSampling1( buff, data, h_size, v_size, b_size, size );
	}
}

/* Void UpSampling( UChar *buff, UChar *data, Int h_size,
		Int v_size, Int b_size, Int size )
{
  Int i, j, nw, nh;
  Int ii, ij;
  float ri, rj;
  Int pos0, pos1, pos2;
  Int A, B, C, D;

  nw = h_size*size/b_size;
  nh = v_size*size/b_size;

  for (j = 0; j < nh; j++ ) {
    rj = (float)((2*j+1)*b_size-size)/(float)(2*size);
    if( ((2*j+1)*b_size-size) < 0 )
      ij = (Int)rj-1;
    else
      ij = (Int)rj;
    rj -= (float)ij;
    for (i = 0; i < nw; i++) {
      ri = (float)((2*i+1)*b_size-size)/(float)(2*size);
      if( ((2*i+1)*b_size-size) < 0 )
				ii = (Int)ri-1;
      else
				ii = (Int)ri;
      ri -= (float)ii;
      pos0 = ii + ij * h_size;
      pos1 = ii + (ij + 1) * h_size;
      pos2 = i + j * nw;
      if( (ii == h_size-1) && (ij == v_size-1) ) { 
	A = (Int)buff[pos0];  
	B = (Int)buff[pos0];  
	C = (Int)buff[pos0];  
	D = (Int)buff[pos0];  
      } else if( (ii < 0) && (ij < 0) ) {
	A = (Int)buff[pos1+1];
	B = (Int)buff[pos1+1];
	C = (Int)buff[pos1+1];
	D = (Int)buff[pos1+1];
      } else if( (ii == h_size-1) && (ij < 0)  ) {
	A = (Int)buff[pos1];
	B = (Int)buff[pos1];
	C = (Int)buff[pos1];
	D = (Int)buff[pos1];
      } else if( (ij == v_size-1) && (ii < 0) ) {
	A = (Int)buff[pos0+1];  
	B = (Int)buff[pos0+1];  
	C = (Int)buff[pos0+1];
	D = (Int)buff[pos0+1];
      } else if( (ii == h_size-1) ) {
	A = (Int)buff[pos0];
	B = (Int)buff[pos1];
	C = (Int)buff[pos1];
	D = (Int)buff[pos0];
      } else if( (ij == v_size-1) ) {
	A = (Int)buff[pos0];  
	B = (Int)buff[pos0];  
	C = (Int)buff[pos0+1];
	D = (Int)buff[pos0+1];
      } else if( (ii < 0) ) {
	A = (Int)buff[pos0+1];  
	B = (Int)buff[pos1+1];  
	C = (Int)buff[pos1+1];
	D = (Int)buff[pos0+1];
      } else if( (ij < 0) ) {
	A = (Int)buff[pos1];  
	B = (Int)buff[pos1];  
	C = (Int)buff[pos1+1];
	D = (Int)buff[pos1+1];
      } else {
	A = (Int)buff[pos0];  
	B = (Int)buff[pos1];  
	C = (Int)buff[pos1+1];
	D = (Int)buff[pos0+1];
      }
    if( ri<0.5 && rj<0.5 ) {
	if((ri*rj)<=0.5) data[pos2] = A;
	else             data[pos2] = ((A&(B|C|D))|(B&C&D));
      } else if( ri<0.5 && rj<1.0 ) {
	if(ri*(1.0-rj)<=0.5) data[pos2] = B;
	else                 data[pos2] = ((B&(A|C|D))|(A&C&D));
      } else if( ri<1.0 && rj<0.5 ) {
	if((1.0-ri)*rj<=0.5) data[pos2] = D;
	else                 data[pos2] = ((D&(B|C|A))|(B&C&A));
      } else {
	if((1.0-ri)*(1.0-rj)<=0.5) data[pos2] = C;
	else                     data[pos2] = ((C&(B|A|D))|(B&A&D));
      }
    }
  }
} */

Void UpSampling1(UChar *buff, UChar *data,
		Int h_size, Int v_size, Int b_size, Int size) {
  int nw, nh;
  int i,j;

  nw = h_size*size/b_size;
  nh = v_size*size/b_size;

  for (i=0; i<nh; i++)
    for (j=0; j<nw; j++) {
      int ii = i*b_size/size;
      int jj = j*b_size/size;

      data[i*nw+j] = buff[ii*h_size+jj];
    }
}
			
Void DownSampling( UChar *buff, UChar *data, Int h_size,
		  Int v_size, Int b_size, Int size )
{
  Int i, j, nw, nh;
  Int cnt, dat;
  Int ii, ij;
  Int ii1, ii2, ij1, ij2;
  Int pos0, pos1;
 
  nw = h_size*size/b_size;
  nh = v_size*size/b_size;

  for (j = 0; j < nh; j++ ) {
    ij1 = (b_size*j)/size;
    ij2 = (b_size*(j+1))/size-1;
    if( ij2 > v_size-1 ) ij2 = v_size-1;
    for (i = 0; i < nw; i++) {
      ii1 = (b_size*i)/size;
      ii2 = (b_size*(i+1))/size-1;
      if( ii2 > h_size-1 ) ii2 = h_size-1;
      pos1 = i + j * nw;
      dat = cnt = 0;
      for( ii=ii1; ii<=ii2; ii++ ) for( ij=ij1; ij<=ij2; ij++ ) {
	cnt++;
	pos0 = ii + ij * h_size;
	dat += f1bit((Int)buff[pos0]);
      }
      data[pos1] = (dat<(cnt/2))?0:1;
    }
  }
}

Int
GetContextUS(
	     UChar a,
	     UChar b,
	     UChar c,
	     UChar d,
	     UChar e,
	     UChar f,
	     UChar g,
	     UChar h
	     )
{
  int ret;

  ret=(int)(a+(b<<1)+(c<<2)+(d<<3)+(e<<4)+(f<<5)+(g<<6)+(h<<7));

  return ret;
}

/* SAIT begin */
/********** comment out 
Void AdaptiveUpSampling( 
			UChar *buff,
			UChar *data,
			Int h_size,
			Int v_size,
			UChar top_sub_border[2][4+MB_SIZE/2],
			UChar left_sub_border[MB_SIZE/2][2]
			)
{
  UChar
    val[12];

  static Int
    Th[256]={
       3, 6, 6, 7,  4, 7, 7, 8,  6, 7, 5, 8,  7, 8, 8, 9,
       6, 5, 5, 8,  5, 6, 8, 9,  7, 6, 8, 9,  8, 7, 9,10,
       6, 7, 7, 8,  7, 8, 8, 9,  7,10, 8, 9,  8, 9, 9,10,
       7, 8, 6, 9,  6, 9, 9,10,  8, 9, 9,10, 11,10,10,11,
       6, 9, 5, 8,  5, 6, 8, 9,  7,10,10, 9,  8, 7, 9,10,
       7, 6, 8, 9,  8, 7, 7,10,  8, 9, 9,10,  9, 8,10, 9,
       7, 8, 8, 9,  6, 9, 9,10,  8, 9, 9,10,  9,10,10, 9,
       8, 9,11,10,  7,10,10,11,  9,12,10,11, 10,11,11,12,
       6, 7, 5, 8,  5, 6, 8, 9,  5, 6, 6, 9,  8, 9, 9,10,
       5, 8, 8, 9,  6, 7, 9,10,  6, 7, 9,10,  9,10,10,11,
       7, 8, 6, 9,  8, 9, 9,10,  8, 7, 9,10,  9,10,10,11,
       8, 9, 7,10,  9,10, 8,11,  9,10,10,11, 10,11, 9,12,
       7, 8, 6, 9,  8, 9, 9,10, 10, 9, 7,10,  9,10,10,11,
       8, 7, 7,10,  7, 8, 8, 9,  9,10,10,11, 10,11,11,12,
       8, 9, 9,10,  9,10,10, 9,  9,10,10,11, 10,11,11,12,
       9,10,10,11, 10,11,11,12, 10,11,11,12, 11,12,12,13};


  Int
    x[12],y[12],
    context,
    th,
    m,
    iup, jup,
    width_up, height_up,
    pi, pj,
    pos;

  width_up  = h_size<<1;
  height_up = v_size<<1;

  for (jup = 0; jup < height_up; jup++ ) {
    y[0] = ((jup+1)>>1)-1;
    pj = ((jup-(y[0]<<1))<<1)-1;

    pos = jup*width_up;

    for (iup = 0; iup < width_up; iup++) {
      x[0] = ((iup+1)>>1)-1;
      pi = ((iup-(x[0]<<1))<<1)-1;

      x[ 1]=x[0]+1; y[ 1]=y[0];
      x[ 2]=x[0];   y[ 2]=y[0]+1;
      x[ 3]=x[0]+1; y[ 3]=y[0]+1;
      x[ 4]=x[0];   y[ 4]=y[0]-1;
      x[ 5]=x[0]+1; y[ 5]=y[0]-1;
      x[ 6]=x[0]-1; y[ 6]=y[0];
      x[ 7]=x[0]+2; y[ 7]=y[0];
      x[ 8]=x[0]-1; y[ 8]=y[0]+1;
      x[ 9]=x[0]+2; y[ 9]=y[0]+1;
      x[10]=x[0];   y[10]=y[0]+2;
      x[11]=x[0]+1; y[11]=y[0]+2;

      for(m=0;m<12;m++)
	val[m]=GetRefValue(x[m],y[m],buff,h_size,v_size,
			   top_sub_border,left_sub_border);

      if( pi<2 && pj<2 ) {
	context=GetContextUS(val[5],val[4],val[6],val[8],
			     val[10],val[11],val[9],val[7]);
      } else if( pi<4 && pj<2 ) {
	context=GetContextUS(val[9],val[7],val[5],val[4],
			     val[6],val[8],val[10],val[11]);
      } else if( pi<2 && pj<4 ) {
	context=GetContextUS(val[6],val[8],val[10],val[11],
			     val[9],val[7],val[5],val[4]);
      } else {
	context=GetContextUS(val[10],val[11],val[9],val[7],
			     val[5],val[4],val[6],val[8]);
      }

      th=Th[context];

      if( pi<2 && pj<2 ) {
	data[pos+iup]
	  = WEIGHT(val[0],
		   val[1],val[2],val[3],
		   val[4],val[5],val[6],val[7],
		   val[8],val[9],val[10],val[11],
		   th);

      } else if( pi<4 && pj<2 ) {
	data[pos+iup]
	  = WEIGHT(val[1],
		   val[0],val[2],val[3],
		   val[4],val[5],val[6],val[7],
		   val[8],val[9],val[10],val[11],
		   th);

      } else if( pi<2 && pj<4 ) {
	data[pos+iup]
	  = WEIGHT(val[2],
		   val[1],val[0],val[3],
		   val[4],val[5],val[6],val[7],
		   val[8],val[9],val[10],val[11],
		   th);

      } else {
	data[pos+iup]
	  = WEIGHT(val[3],
		   val[1],val[2],val[0],
		   val[4],val[5],val[6],val[7],
		   val[8],val[9],val[10],val[11],
		   th);
      }
    }
  }
}
****************************/
Void AdaptiveUpSampling( 
			UChar *buff,
			UChar *data,
			Int h_size,
			Int v_size,
			Int offset
			)
{
  UChar
    other_total,
    x_lim,
    y_lim,
    val[12];
  Int
    x[12],y[12],
    m,
    i, j,
    h_size_border,
    width_up,
    pi, pj,
    pi_st,pi_en,pj_st,pj_en,
    pi_p;

  h_size_border=h_size+4;
  width_up  = h_size<<1;

  /* --  4  5 -- */
  /*  6  0  1  7 */
  /*  8  2  3  9 */
  /* -- 10 11 -- */

  for (j = -1; j < v_size; j++ ) {
    y[ 0]=y[ 1]=y[ 6]=y[ 7]=j+2;
    y[ 2]=y[ 3]=y[ 8]=y[ 9]=j+3;
    y[ 4]=y[ 5]            =j+1;
    y[10]=y[11]            =j+4;

    if(j>-1)pj_st=0;
    else    pj_st=1;
    
    if(j<v_size-1)pj_en=2;
    else          pj_en=1;

    for (i = -1; i < h_size; i++) {

      x[ 0]=x[ 2]=x[ 4]=x[10]=i+2;
      x[ 1]=x[ 3]=x[ 5]=x[11]=i+3;
      x[ 6]=x[ 8]            =i+1;
      x[ 7]=x[ 9]            =i+4;

      if(i>-1)pi_st=0;
      else    pi_st=1;

      if(i<h_size-1)pi_en=2;
      else          pi_en=1;

      for(m=0;m<12;m++){
	if(x[m]<h_size+2 && y[m]<v_size+2){

	  val[m]=buff[y[m]*h_size_border+x[m]];

	}else{

	  if(y[m]<2){
	    val[m]=buff[y[m]*h_size_border+x[m]];
	  }else{
	    x_lim=LIMADRS(x[m],2,h_size+2);
	    y_lim=LIMADRS(y[m],2,v_size+2);
	    val[m]=buff[y_lim*h_size_border+x_lim];
	  }
	}
      }

      other_total=val[4]+val[5]+val[6]+val[7]+val[8]+val[9]+val[10]+val[11];

      for(pj=pj_st;pj<pj_en;pj++){
	pi_p=((j<<1)+1+pj+offset)*(width_up+(offset<<1))+(i<<1)+1+offset;

	for(pi=pi_st;pi<pi_en;pi++){

	  if( pi<1 && pj<1 ) {
	    data[pi_p+pi]
	      = WEIGHT(val[0],val[1],val[2],val[3],other_total,
		       Th[GetContextUS(val[5],val[4],val[6],val[8],
				       val[10],val[11],val[9],val[7])]);

	  } else if( pj<1 ) {
	    data[pi_p+pi]
	      = WEIGHT(val[1],val[0],val[2],val[3],other_total,
		       Th[GetContextUS(val[9],val[7],val[5],val[4],
				       val[6],val[8],val[10],val[11])]);

	  } else if( pi<1 ) {
	    data[pi_p+pi]
	      = WEIGHT(val[2],val[1],val[0],val[3],other_total,
		       Th[GetContextUS(val[6],val[8],val[10],val[11],
				       val[9],val[7],val[5],val[4])]);
	  } else {
	    data[pi_p+pi]
	      = WEIGHT(val[3],val[1],val[2],val[0],other_total,
		       Th[GetContextUS(val[10],val[11],val[9],val[7],
				       val[5],val[4],val[6],val[8])]);
	  }
	}
      }
    }
  }
}
/* SAIT end */


UChar
GetRefValue(
	    int x_adr,
	    int y_adr,
	    unsigned char *buff,
	    int h_size,
	    int v_size,
	    unsigned char top_sub_border[2][4+MB_SIZE/2],
	    unsigned char left_sub_border[MB_SIZE/2][2]
	    )
{
  UChar
    x_lim,
    y_lim,
    ret;

  if(x_adr<-2 || x_adr>h_size+1 || y_adr<-2 || y_adr>v_size+1){
    fprintf(stderr,"wrong x_adr=%d y_adr=%d in GetRefValue()\n",x_adr,y_adr);
    exit(0);
  }

  if(x_adr>=0 && x_adr<h_size && y_adr>=0 && y_adr<v_size){

    ret=buff[y_adr*h_size+x_adr];

  }else{

    if(y_adr<0)                      ret=top_sub_border[2+y_adr][2+x_adr];
    else if(x_adr<0 && y_adr<v_size) ret=left_sub_border[y_adr][2+x_adr];
    else{
      x_lim=LIMADRS(x_adr,0,h_size);
      y_lim=LIMADRS(y_adr,0,v_size);
      ret=buff[y_lim*h_size+x_lim];
    }                    

  }

  return ret;
}

/* SAIT begin */
/*********** comment out 
Void UpSampling(
		UChar *buff,
		UChar *data,
		Int h_size, 
		Int v_size,
		Image *rec_image,
		Int h_image,
		Int v_image,
		Int xmb,
		Int ymb,
		Int b_size,
		Int size
		)
{
  Image 
    *mblock_top,
    *mblock_top_left,
    *mblock_top_right,
    *mblock_left;

  SInt
    *a_mb_top,
    *a_mb_top_left,
    *a_mb_top_right,
    *a_mb_left;

  UChar
    tmp,
    temp[MB_SIZE*MB_SIZE],
    top_sub_border[2][4+MB_SIZE/2],
    left_sub_border[MB_SIZE/2][2],
    mb_top[MB_SIZE*MB_SIZE],
    mb_top_left[MB_SIZE*MB_SIZE],
    mb_top_right[MB_SIZE*MB_SIZE],
    mb_left[MB_SIZE*MB_SIZE];

  Int
    i, j, k,
    is,
    scale_shift,
    scale;

  scale=size/b_size;

  if(scale==2)scale_shift=1;
  else if(scale==4)scale_shift=2;

  for(j=0;j<size;j++){
    is=j*size;
    for(i=0;i<size;i++)
      mb_top_left[is+i]=mb_top[is+i]=mb_top_right[is+i]=mb_left[is+i]
	=data[is+i]=0;
  }

  mblock_top_left  = AllocImage(size,size,SHORT_TYPE);
  mblock_top       = AllocImage(size,size,SHORT_TYPE);
  mblock_top_right = AllocImage(size,size,SHORT_TYPE);
  mblock_left      = AllocImage(size,size,SHORT_TYPE);

  a_mb_top_left  = (SInt *) GetImageData(mblock_top_left);
  a_mb_top       = (SInt *) GetImageData(mblock_top);
  a_mb_top_right = (SInt *) GetImageData(mblock_top_right);
  a_mb_left      = (SInt *) GetImageData(mblock_left);

  if(ymb!=0 && xmb!=0){
    GetSubImage(rec_image,mblock_top_left, (xmb-size),(ymb-size));
    for(j=0;j<size;j++){
      is=j*size;
      for(i=0;i<size;i++)mb_top_left[is+i]=f1bit((UChar)a_mb_top_left[is+i]);
    }
  }else{
    for(j=0;j<size;j++){
      is=j*size;
      for(i=0;i<size;i++)mb_top_left[is+i]=0;
    }
  }

  if(ymb!=0){
    GetSubImage(rec_image,mblock_top,       xmb,      (ymb-size));
    for(j=0;j<size;j++){
      is=j*size;
      for(i=0;i<size;i++)mb_top[is+i]=f1bit((UChar)a_mb_top[is+i]);
    }
  }else{
    for(j=0;j<size;j++){
      is=j*size;
      for(i=0;i<size;i++)mb_top[is+i]=0;
    }
  }

  if(ymb!=0 && xmb!=h_image-size){
    GetSubImage(rec_image,mblock_top_right,(xmb+size),(ymb-size));
    for(j=0;j<size;j++){
      is=j*size;
      for(i=0;i<size;i++)mb_top_right[is+i]=f1bit((UChar)a_mb_top_right[is+i]);
    }
  }else{
    for(j=0;j<size;j++){
      is=j*size;
      for(i=0;i<size;i++)mb_top_right[is+i]=0;
    }
  }

  if(xmb!=0){
    GetSubImage(rec_image,mblock_left,(xmb-size),ymb);
    for(j=0;j<size;j++){
      is=j*size;
      for(i=0;i<size;i++)mb_left[is+i]=f1bit((UChar)a_mb_left[is+i]);
    }
  }else{
    for(j=0;j<size;j++){
      is=j*size;
      for(i=0;i<size;i++)mb_left[is+i]=0;
    }
  }

  top_sub_border[0][0]=mb_top_left[size*size-size-2];
  top_sub_border[0][1]=mb_top_left[size*size-size-1];
  top_sub_border[1][0]=mb_top_left[size*size-2];
  top_sub_border[1][1]=mb_top_left[size*size-1];
  top_sub_border[0][h_size+2]=mb_top_right[size*size-(size<<1)];
  top_sub_border[0][h_size+3]=mb_top_right[size*size-(size<<1)+1];
  top_sub_border[1][h_size+2]=mb_top_right[size*size-size];
  top_sub_border[1][h_size+3]=mb_top_right[size*size-size+1];

  for(j=0;j<2;j++){
    for(i=0;i<h_size;i++){
      tmp=0;
      for(k=0;k<scale;k++)tmp+=mb_top[size*size-(2-j)*size+scale*i+k];
      top_sub_border[j][i+2]=(tmp+scale/2)/scale;
    }
  }

  for(i=0;i<2;i++){
    for(j=0;j<v_size;j++){
      tmp=0;
      for(k=0;k<scale;k++)tmp+=mb_left[(scale*j+k)*size+size-2+i];
      left_sub_border[j][i]=(tmp+scale/2)/scale;
    }
  }

  if(scale==2){
    AdaptiveUpSampling(buff,data,h_size,v_size,
		       top_sub_border,left_sub_border);
  }else{
    AdaptiveUpSampling(buff,temp,h_size,v_size,
		       top_sub_border,left_sub_border);
    
    top_sub_border[0][(h_size<<1)+2]=top_sub_border[0][h_size+2];
    top_sub_border[0][(h_size<<1)+3]=top_sub_border[0][h_size+3];
    top_sub_border[1][(h_size<<1)+2]=top_sub_border[1][h_size+2];
    top_sub_border[1][(h_size<<1)+3]=top_sub_border[1][h_size+3];
    
    for(j=0;j<2;j++)for(i=(h_size<<1)-1;i>=0;i--)
      top_sub_border[j][i+2]=top_sub_border[j][i/2+2];
    
    for(i=0;i<2;i++)for(j=(v_size<<1)-1;j>=0;j--)
      left_sub_border[j][i]=left_sub_border[j/2][i];
    
    AdaptiveUpSampling(temp,data,(h_size<<1),(v_size<<1),
		       top_sub_border,left_sub_border);
  }
  
  FreeImage (mblock_top);
  FreeImage (mblock_top_left);
  FreeImage (mblock_top_right);
  FreeImage (mblock_left);

}
**********************/
Void UpSampling(
		Image *bordered_smb_data,
		UChar *data,
		Int h_size, /* size of block */
		Int v_size,
		Int h_image, /* size of VOP */
		Int v_image,
		Int xmb,
		Int ymb,
		Int b_size,
		Int size
                )
{
  UChar
    buff[(MB_SIZE+4)*(MB_SIZE+4)],
    temp[12*12];

  SInt
    *p;

  Int
    i, j,
    is_next,
    is,
    scale_shift,
    scale;

  p = (SInt *) GetImageData(bordered_smb_data);
  for( i=0; i<b_size+4; i++)
    for( j=0; j<b_size+4; j++, p++ ) {
      buff[i*(b_size+4)+j] = (UChar) (*p);
    }

  scale=size/b_size;

  if(scale==2)scale_shift=1;
  else if(scale==4)scale_shift=2;

  if(scale==2){
    AdaptiveUpSampling(buff,data,h_size,v_size,0);
  }else{

    AdaptiveUpSampling(buff,temp,h_size,v_size,2);

    /* top border */
    temp[0]=buff[0];
    temp[1]=buff[1];
    temp[(h_size<<1)+4]=buff[h_size+4];
    temp[(h_size<<1)+5]=buff[h_size+5];

    temp[(h_size<<1)+2]=buff[h_size+2];
    temp[(h_size<<1)+3]=buff[h_size+3];
    temp[(h_size<<2)+6]=buff[(h_size<<1)+6];
    temp[(h_size<<2)+7]=buff[(h_size<<1)+7];

    for(j=0;j<2;j++){
      is_next=j*((h_size<<1)+4);
      is=j*(h_size+4)+1;
      for(i=2;i<(h_size<<1)+2;i++)temp[is_next+i]=buff[is+(i>>1)];
    }

    /* left border */
    for(j=2;j<(v_size<<1)+2;j++){
      is_next=j*((h_size<<1)+4);
      is=(1+(j>>1))*(h_size+4);
      for(i=0;i<2;i++)temp[is_next+i]=buff[is+i];
    }

    AdaptiveUpSampling(temp,data,(h_size<<1),(v_size<<1),0);

  }
}
/* SAIT end */


/***********************************************************CommentBegin******
 *
 * -- SelectRefVop -- Select reference VOP for shape coding
 *											
 *
 * Author :		
 *	Minhua Zhou (HHI Berlin)
 *
 * Created :		
 *	17-04-98
 * 
 * Arguments In: 	
 *		 prev - the forward reference VOP
 *		 curr - the current VOP
 *		 next - the backward reference VOP
 *               TRB  - temporal distance between the current and forward VOP
 *               TRD  - temporal distance between the backward and forward VOP
 *
 * Arguments In/Out:
 *				
 *					
 *
 * Arguments Out:
 *
 * Return values : 0 :forward 1: backward
 *
 * Side effects :	
 *	-
 *
 * Description : 
 *
 * See also :
 *
 ***********************************************************CommentEnd********/

Int SelectRefVop(Vop *prevs, Vop *curr, Vop *next, Int TRB, Int TRD) {
  Int direction=1,forward=0,backward=1;
   
   if ((GetVopPredictionType(curr)==0) || (GetVopPredictionType(curr)==1))    
         return 0;

   if ((GetVopWidth(prevs)!=0)&&(GetVopWidth(next)!=0)) {
/*** 4/19 changed by SHARP */
       if (TRB<=TRD-TRB) direction =forward;
/* 4/19 changed by SHARP ***/
             else direction = backward;
       } else if (GetVopWidth(prevs)!=0)
          direction = forward;
           else if (GetVopWidth(next)!=0)
              direction = backward;
             else fprintf(stdout,"WRONG in  SelectREFtype");  

               return direction;

 }


