/* The copyright in this software is being made available under the BSD
 * License, included below. This software may be subject to other third party
 * and contributor rights, including patent rights, and no such rights are
 * granted under this license.  
 *
 * Copyright (c) 2010-2012, ITU/ISO/IEC
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
 *    be used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */


#include "ViewSynDef.h"
#include "PictureResample.h"

/* ************************************************
 *  class CPictureResample
 * *********************************************** */

CPictureResample::CPictureResample()
{
	int i=0;

	for(i=0;i<PIXEL_VALUE_RANGE;++i)
	{
		//AVCFir6TapUpsampleTable[i].value_mul5=i*5;
		//AVCFir6TapUpsampleTable[i].value_mul20=i*20;
		PiXelValueMul5[i]=i*5;
		PixelValueMul20[i]=i*20;

	}
}

CPictureResample::~CPictureResample()
{
}
 
/*
 * \brief
 *    Clip the pixel value to [0, 255]
 * \param pxlVal
 *    Input pixel value
 * \return
 *    Pixel value within [0, 255]
 */
unsigned char CPictureResample::PixelClip(const int pxlVal)
{
  if (pxlVal < 0) return 0;
  if (pxlVal > 255) return 255;
  return (unsigned char) pxlVal;
}

/*
 * \brief
 *    Resampling by simple pixel repeating 
 *
 * \input
 * \param Org
 *    Input image (One component, U or V) in WidthxHeight
 * \param Width, Height
 *    The resolution of the picture (UV component)
 *
 * \output
 * \param Dst
 *    Output image (One component, U or V) in 2Widthx2Height
 */
void CPictureResample::RepeatPixel420to444(imgpel** Dst, imgpel** Org, int Width, int Height)
{
  int x, y;
  int w, h;
  
  w = Width<<1;
  h = Height<<1;
  
  for (y = 0; y < h; y++)
  {
	  for (x = 0; x < w;  x++)
	  {
		  Dst[y][x] = Org[y>>1][x>>1];
	  }
  }
}

/*
 * \brief
 *    Resampling by simple pixel dropping
 *
 * \input
 * \param Org
 *    Input image (One component, U or V) in 2Widthx2Height
 * \param Width, Height
 *    The resolution of the picture (UV component)
 *
 * \output
 * \param Dst
 *    Output image (One component, U or V) in WidthxHeight
 */
void CPictureResample::DropPixel444to420(imgpel** Dst, imgpel** Org, int Width, int Height)
{
  int x, y;
  
  for (y = 0; y < Height; y++)
  {
	  for (x = 0; x < Width;  x++)
	  {
		  Dst[y][x] = Org[y<<1][x<<1];
	  }
  }
}

/*
 * \brief
 *    Check if the Resampler is ready for use.
 * \return
 *    0: Ready
 *    non-zero: Not ready
 */
int CPictureResample::State()
{
  return 0;
}

/*
 * \brief
 *    Resampling from 420 to 444. WidthxHeight => 2Widthx2Height
 *
 * \input
 * \param Org
 *    Input image (One component, U or V) in WidthxHeight
 * \param Width, Height
 *    The resolution of the picture (UV component)
 *
 * \output
 * \param Dst
 *    Output image (One component, U or V) in 2Widthx2Height
 */
void CPictureResample::PictureResample420to444(imgpel**Dst, imgpel**Org, int Width, int Height)
{
  RepeatPixel420to444(Dst, Org, Width, Height);
}

void CPictureResample::PictureResample420to444ForRefView(imgpel** output_left_u, imgpel** input_left_u,
														 imgpel** output_left_v, imgpel** input_left_v,
														 imgpel** output_right_u,imgpel** input_right_u, 
														 imgpel** output_right_v,imgpel** input_right_v,
														 int Width, int Height,int SynDir)
{
	int x, y;
	int w, h;

	w = Width<<1;
	h = Height<<1;

	if(SynDir==2)
	{
		//!<synthesize from left and right
		for (y = 0; y < h; y++)
		{
			imgpel* li_U=input_left_u[y>>1];
			imgpel* li_V=input_left_v[y>>1];
			imgpel* ri_U=input_right_u[y>>1];
			imgpel* ri_V=input_right_v[y>>1];
			imgpel* lo_U=output_left_u[y];
			imgpel* lo_V=output_left_v[y];
			imgpel* ro_U=output_right_u[y];
			imgpel* ro_V=output_right_v[y];
			for (x = 0; x < w;  x++)
			{
				*(lo_U+x)=*(li_U+(x>>1));
				*(lo_V+x)=*(li_V+(x>>1));
				*(ro_U+x)=*(ri_U+(x>>1));
				*(ro_V+x)=*(ri_V+(x>>1));
			}
		}
	}
	else if(SynDir==1)
	{
		//!<synthesize from right
		for (y = 0; y < h; y++)
		{
			imgpel* ri_U=input_right_u[y>>1];
			imgpel* ri_V=input_right_v[y>>1];
			imgpel* ro_U=output_right_u[y];
			imgpel* ro_V=output_right_v[y];
			for (x = 0; x < w;  x++)
			{
				*(ro_U+x)=*(ri_U+(x>>1));
				*(ro_V+x)=*(ri_V+(x>>1));
			}
		}
	}
	else if(SynDir==0)
	{
		//!<synthesize from left
		for (y = 0; y < h; y++)
		{
			imgpel* li_U=input_left_u[y>>1];
			imgpel* li_V=input_left_v[y>>1];
			imgpel* lo_U=output_left_u[y];
			imgpel* lo_V=output_left_v[y];
			for (x = 0; x < w;  x++)
			{
				*(lo_U+x)=*(li_U+(x>>1));
				*(lo_V+x)=*(li_V+(x>>1));
			}
		}
	}

}

/*
 * \brief
 *    Resampling from 444 to 420. 2Widthx2Height => WidthxHeight
 *
 * \input
 * \param Org
 *    Input image (One component, U or V) in 2Widthx2Height
 * \param Width, Height
 *    The resolution of the picture (UV component)
 *
 * \output
 * \param Dst
 *    Output image (One component, U or V) in WidthxHeight
 */
void CPictureResample::PictureResample444to420(imgpel**Dst, imgpel**Org, int Width, int Height)
{
  DropPixel444to420(Dst, Org, Width, Height);
}

void CPictureResample::PictureResample444to420ForRefView(imgpel** output_left_u, imgpel** input_left_u, 
														 imgpel** output_left_v, imgpel** input_left_v,
														 imgpel** output_right_u,imgpel** input_right_u,
														 imgpel** output_right_v,imgpel** input_right_v, 
														 int Width, int Height)
{
	int x, y;

	for (y = 0; y < Height; y++)
	{
		for (x = 0; x < Width;  x++)
		{
			if(output_left_u&&input_left_u)
				output_left_u[y][x] = input_left_u[y<<1][x<<1];

			if(output_left_v&&input_left_v)
				output_left_v[y][x] = input_left_v[y<<1][x<<1];

			if(output_right_u&&input_right_u)
				output_right_u[y][x] = input_right_u[y<<1][x<<1];

			if(output_right_v&&input_right_v)
				output_right_v[y][x] = input_right_v[y<<1][x<<1];
		}
	}
}

/*
 * \brief
 *    Upsample the picture, and we will get more warped pixels in the synthesized picture
 * 
 * \input
 * \param Yi
 *    The input image.  Resolution is Width, Height
 * \param Width, Height
 *    The resolution of the input picture
 *
 * \output
 * \param Yo
 *    The output image. Resolution is Width*2, Height
 *
 * \return
 *    None
 */
void CPictureResample::DoUpsample(imgpel** Yo, imgpel** Yi, int Width, int Height)
{
  int i, j, pel[6];
  int WidthMinus1;
  imgpel* out;
  imgpel* in;
  
  WidthMinus1 = Width-1;

  for (j = 0; j < Height; j++)
  {
    out = Yo[j];
    in  = Yi[j];
    for(i = 0; i < Width; i++)
    {
      pel[0] = CLIP(i-2, 0, WidthMinus1);
      pel[1] = CLIP(i-1, 0, WidthMinus1);
      pel[2] = CLIP(i  , 0, WidthMinus1);
      pel[3] = CLIP(i+1, 0, WidthMinus1);
      pel[4] = CLIP(i+2, 0, WidthMinus1);
      pel[5] = CLIP(i+3, 0, WidthMinus1);

      out[ (i)<<1   ] = in[pel[2]];
      out[((i)<<1)+1] = CLIP( (20*(in[pel[2]]+in[pel[3]]) - 5*(in[pel[1]]+in[pel[4]]) + (in[pel[0]]+in[pel[5]]) +16)>>5, 0, 255 );
    }
  }
}

/*
 * \brief
 *    Downsample the picture, and we will get more warped pixels in the synthesized picture
 * 
 * \input
 * \param Yi
 *    The input image.  Resolution is Width, Height
 * \param Width, Height
 *    The resolution of the input picture
 *
 * \output
 * \param Yo
 *    The output image. Resolution is Width/2, Height
 *
 * \return
 *    None
 */
void CPictureResample::DoDownsample(imgpel** Yo, imgpel** Yi, int Width, int Height)
{
  int i, j, pel[6];
  int WidthMinus1;
  imgpel* out;
  imgpel* in;
  
  WidthMinus1 = Width-1;

  for (j = 0; j < Height; j++)
  {
    out = Yo[j];
    in  = Yi[j];
    for(i = 0; i < Width; i+=2)
    {
      pel[0] = CLIP(i-1, 0, WidthMinus1);
      pel[1] = CLIP(i  , 0, WidthMinus1);
      pel[2] = CLIP(i+1, 0, WidthMinus1);

      out[(i >> 1)] = CLIP ( (in[pel[0]] + 2*in[pel[1]] + in[pel[2]]) >> 2, 0, 255);
    }
  }
}

/*
 * \brief
 *    Upsample the picture, and we will get more warped pixels in the synthesized picture
 * 
 * \input
 * \param Yi
 *    The input image.  Resolution is Width, Height
 * \param Width, Height
 *    The resolution of the input picture
 * \param Factor
 *    Must be 2 or 4. Upsample to 2 times or 4 times
 *
 * \output
 * \param Yo
 *    The output image. Resolution is Width*2, Height
 *
 * \return
 *    0: success
 *    -1: fail
 */
int CPictureResample::UpsampleView(imgpel** Yo, imgpel** Yi, int Width, int Height, int Factor)
{
	imgpel** Ym=NULL;

	if (Factor == 2)
		DoUpsample(Yo, Yi, Width, Height);
	else
	{
		get_mem2D(&Ym,Height,Width*2);
		DoUpsample(Ym, Yi, Width, Height);
		DoUpsample(Yo, Ym, Width*2, Height);
		free_mem2D(Ym);
	}

	return 0;
}
int CPictureResample::UpsampleRefView(imgpel**left_output_Y,imgpel**left_input_Y, 
									  imgpel**left_output_U,imgpel**left_input_U, 
									  imgpel**left_output_V,imgpel**left_input_V, 
									  imgpel**left_output_depth,imgpel**left_input_depth,
									  imgpel**right_output_Y,imgpel**right_input_Y, 
									  imgpel**right_output_U,imgpel**right_input_U, 
									  imgpel**right_output_V,imgpel**right_input_V, 
									  imgpel**right_output_depth,imgpel**right_input_depth,
									  int Width, int Height, int Factor,int SynDirection)
{
	int i, j;
	int p0,p1,p2,p3,p4,p5;
	int pel[6];

	if(Factor==4)
	{
		int output_height=Height;
		int output_width=Width*Factor;
		int output_width_minus2 = output_width-2;
		int output_width_minus1 = output_width-1;

		for(j=0;j<output_height;++j)
		{
			for(i=0;i<output_width;i+=4)
			{
				if(left_output_Y&&left_input_Y)
					left_output_Y[j][i]=left_input_Y[j][i>>2];
				if(left_output_U&&left_input_U)
					left_output_U[j][i]=left_input_U[j][i>>2];
				if(left_output_V&&left_input_V)
					left_output_V[j][i]=left_input_V[j][i>>2];
				if(left_output_depth&&right_input_depth)
					left_output_depth[j][i]=left_input_depth[j][i>>2];

				if(right_output_Y&&right_input_Y)
					right_output_Y[j][i]=right_input_Y[j][i>>2];
				if(right_output_U&&right_input_U)
					right_output_U[j][i]=right_input_U[j][i>>2];
				if(right_output_V&&right_input_V)
					right_output_V[j][i]=right_input_V[j][i>>2];
				if(right_output_depth&&right_input_depth)
					right_output_depth[j][i]=right_input_depth[j][i>>2];
			}
			for(i=2;i<output_width;i+=2)
			{
				pel[0] = CLIP(i-6, 0, output_width_minus2);
				pel[1] = CLIP(i-4, 0, output_width_minus2);
				pel[2] = CLIP(i-2  , 0, output_width_minus2);
				pel[3] = CLIP(i+2, 0, output_width_minus2);
				pel[4] = CLIP(i+4, 0, output_width_minus2);
				pel[5] = CLIP(i+6, 0, output_width_minus2);

				if(left_output_Y&&left_input_Y)
					left_input_Y[j][i]=CLIP((20*(left_input_Y[j][pel[2]]+left_input_Y[j][pel[3]])-
											5*(left_input_Y[j][pel[1]]+left_input_Y[j][pel[4]])+
											(left_input_Y[j][pel[0]]+left_input_Y[j][pel[5]])+16)>>5,0,255);
				if(left_output_U&&left_input_U)
					left_input_U[j][i]=CLIP((20*(left_input_U[j][pel[2]]+left_input_U[j][pel[3]])-
											5*(left_input_U[j][pel[1]]+left_input_U[j][pel[4]])+
											(left_input_U[j][pel[0]]+left_input_U[j][pel[5]])+16)>>5,0,255);
				if(left_output_V&&left_input_V)
					left_output_V[j][i]=CLIP((20*(left_input_V[j][pel[2]]+left_input_V[j][pel[3]])-
											5*(left_input_V[j][pel[1]]+left_input_V[j][pel[4]])+
											(left_input_V[j][pel[0]]+left_input_V[j][pel[5]])+16)>>5,0,255);
				if(left_output_depth&&right_input_depth)
					left_output_depth[j][i]=CLIP((20*(left_input_depth[j][pel[2]]+left_input_depth[j][pel[3]])-
											5*(left_input_depth[j][pel[1]]+left_input_depth[j][pel[4]])+
											(left_input_depth[j][pel[0]]+left_input_depth[j][pel[5]])+16)>>5,0,255);

				if(right_output_Y&&right_input_Y)
					right_output_Y[j][i]=CLIP((20*(right_input_Y[j][pel[2]]+right_input_Y[j][pel[3]])-
											5*(right_input_Y[j][pel[1]]+right_input_Y[j][pel[4]])+
											(right_input_Y[j][pel[0]]+right_input_Y[j][pel[5]])+16)>>5,0,255);
				if(right_output_U&&right_input_U)
					right_output_U[j][i]=CLIP((20*(right_input_U[j][pel[2]]+right_input_U[j][pel[3]])-
											5*(right_input_U[j][pel[1]]+right_input_U[j][pel[4]])+
											(right_input_U[j][pel[0]]+right_input_U[j][pel[5]])+16)>>5,0,255);
				if(right_output_V&&right_input_V)
					right_output_V[j][i]=CLIP((20*(right_input_V[j][pel[2]]+right_input_V[j][pel[3]])-
											5*(right_input_V[j][pel[1]]+right_input_V[j][pel[4]])+
											(right_input_V[j][pel[0]]+right_input_V[j][pel[5]])+16)>>5,0,255);
				if(right_output_depth&&right_input_depth)
					right_output_depth[j][i]=CLIP((20*(right_input_depth[j][pel[2]]+right_input_depth[j][pel[3]])-
													5*(right_input_depth[j][pel[1]]+right_input_depth[j][pel[4]])+
													(right_input_depth[j][pel[0]]+right_input_depth[j][pel[5]])+16)>>5,0,255);
			}

			for(i=1;i<output_width;i+=2)
			{
				pel[0] = CLIP(i-5, 0, output_width_minus1);
				pel[1] = CLIP(i-3, 0, output_width_minus1);
				pel[2] = CLIP(i-1  , 0, output_width_minus1);
				pel[3] = CLIP(i+1, 0, output_width_minus1);
				pel[4] = CLIP(i+3, 0, output_width_minus1);
				pel[5] = CLIP(i+5, 0, output_width_minus1);

				if(left_output_Y&&left_input_Y)
					left_input_Y[j][i]=CLIP((20*(left_input_Y[j][pel[2]]+left_input_Y[j][pel[3]])-
					5*(left_input_Y[j][pel[1]]+left_input_Y[j][pel[4]])+
					(left_input_Y[j][pel[0]]+left_input_Y[j][pel[5]])+16)>>5,0,255);
				if(left_output_U&&left_input_U)
					left_input_U[j][i]=CLIP((20*(left_input_U[j][pel[2]]+left_input_U[j][pel[3]])-
					5*(left_input_U[j][pel[1]]+left_input_U[j][pel[4]])+
					(left_input_U[j][pel[0]]+left_input_U[j][pel[5]])+16)>>5,0,255);
				if(left_output_V&&left_input_V)
					left_output_V[j][i]=CLIP((20*(left_input_V[j][pel[2]]+left_input_V[j][pel[3]])-
					5*(left_input_V[j][pel[1]]+left_input_V[j][pel[4]])+
					(left_input_V[j][pel[0]]+left_input_V[j][pel[5]])+16)>>5,0,255);
				if(left_output_depth&&right_input_depth)
					left_output_depth[j][i]=CLIP((20*(left_input_depth[j][pel[2]]+left_input_depth[j][pel[3]])-
					5*(left_input_depth[j][pel[1]]+left_input_depth[j][pel[4]])+
					(left_input_depth[j][pel[0]]+left_input_depth[j][pel[5]])+16)>>5,0,255);

				if(right_output_Y&&right_input_Y)
					right_output_Y[j][i]=CLIP((20*(right_input_Y[j][pel[2]]+right_input_Y[j][pel[3]])-
					5*(right_input_Y[j][pel[1]]+right_input_Y[j][pel[4]])+
					(right_input_Y[j][pel[0]]+right_input_Y[j][pel[5]])+16)>>5,0,255);
				if(right_output_U&&right_input_U)
					right_output_U[j][i]=CLIP((20*(right_input_U[j][pel[2]]+right_input_U[j][pel[3]])-
					5*(right_input_U[j][pel[1]]+right_input_U[j][pel[4]])+
					(right_input_U[j][pel[0]]+right_input_U[j][pel[5]])+16)>>5,0,255);
				if(right_output_V&&right_input_V)
					right_output_V[j][i]=CLIP((20*(right_input_V[j][pel[2]]+right_input_V[j][pel[3]])-
					5*(right_input_V[j][pel[1]]+right_input_V[j][pel[4]])+
					(right_input_V[j][pel[0]]+right_input_V[j][pel[5]])+16)>>5,0,255);
				if(right_output_depth&&right_input_depth)
						right_output_depth[j][i]=CLIP((20*(right_input_depth[j][pel[2]]+right_input_depth[j][pel[3]])-
						5*(right_input_depth[j][pel[1]]+right_input_depth[j][pel[4]])+
						(right_input_depth[j][pel[0]]+right_input_depth[j][pel[5]])+16)>>5,0,255);
			}
		}
	}
	else if(Factor==2)
	{
		int output_height=Height;
		int output_width=Width*Factor;
		int output_width_minus2 = output_width-2;


		for(j=0;j<output_height;++j)
		{
			if(SynDirection==2)
			{
				//!<synthesize from left and right
				imgpel* li_Y=left_input_Y[j];
				imgpel* li_U=left_input_U[j];
				imgpel* li_V=left_input_V[j];
				imgpel* li_D=left_input_depth[j];
				imgpel* lo_Y=left_output_Y[j];
				imgpel* lo_U=left_output_U[j];
				imgpel* lo_V=left_output_V[j];
				imgpel* lo_D=left_output_depth[j];
				imgpel* ri_Y=right_input_Y[j];
				imgpel* ri_U=right_input_U[j];
				imgpel* ri_V=right_input_V[j];
				imgpel* ri_D=right_input_depth[j];
				imgpel* ro_Y=right_output_Y[j];
				imgpel* ro_U=right_output_U[j];
				imgpel* ro_V=right_output_V[j];
				imgpel* ro_D=right_output_depth[j];
				for(i=0;i<output_width;i+=2)
				{
					*(lo_Y+i)=*(li_Y+(i>>1));
					*(lo_U+i)=*(li_U+(i>>1));
					*(lo_V+i)=*(li_V+(i>>1));
					*(lo_D+i)=*(li_D+(i>>1));
					*(ro_Y+i)=*(ri_Y+(i>>1));
					*(ro_U+i)=*(ri_U+(i>>1));
					*(ro_V+i)=*(ri_V+(i>>1));
					*(ro_D+i)=*(ri_D+(i>>1));
				}
				for(i=1;i<output_width;i+=2)
				{
					p0 = CLIP(i-5, 0, output_width_minus2);
					p1 = CLIP(i-3, 0, output_width_minus2);
					p2 = CLIP(i-1  , 0, output_width_minus2);
					p3 = CLIP(i+1, 0, output_width_minus2);
					p4 = CLIP(i+3, 0, output_width_minus2);
					p5 = CLIP(i+5, 0, output_width_minus2);

					*(lo_Y+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_Y+p2))+
						*(PixelValueMul20+*(lo_Y+p3))-
						*(PiXelValueMul5+*(lo_Y+p1))-
						*(PiXelValueMul5+*(lo_Y+p4))+
						*(lo_Y+p0)+
						*(lo_Y+p5)+16)>>5,0,255);
					*(lo_U+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_U+p2))+
						*(PixelValueMul20+*(lo_U+p3))-
						*(PiXelValueMul5+*(lo_U+p1))-
						*(PiXelValueMul5+*(lo_U+p4))+
						*(lo_U+p0)+
						*(lo_U+p5)+16)>>5,0,255);
					*(lo_V+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_V+p2))+
						*(PixelValueMul20+*(lo_V+p3))-
						*(PiXelValueMul5+*(lo_V+p1))-
						*(PiXelValueMul5+*(lo_V+p4))+
						*(lo_V+p0)+
						*(lo_V+p5)+16)>>5,0,255);
					*(lo_D+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_D+p2))+
						*(PixelValueMul20+*(lo_D+p3))-
						*(PiXelValueMul5+*(lo_D+p1))-
						*(PiXelValueMul5+*(lo_D+p4))+
						*(lo_D+p0)+
						*(lo_D+p5)+16)>>5,0,255);
					*(ro_Y+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_Y+p2))+
						*(PixelValueMul20+*(ro_Y+p3))-
						*(PiXelValueMul5+*(ro_Y+p1))-
						*(PiXelValueMul5+*(ro_Y+p4))+
						*(ro_Y+p0)+
						*(ro_Y+p5)+16)>>5,0,255);
					*(ro_U+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_U+p2))+
						*(PixelValueMul20+*(ro_U+p3))-
						*(PiXelValueMul5+*(ro_U+p1))-
						*(PiXelValueMul5+*(ro_U+p4))+
						*(ro_U+p0)+
						*(ro_U+p5)+16)>>5,0,255);
					*(ro_V+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_V+p2))+
						*(PixelValueMul20+*(ro_V+p3))-
						*(PiXelValueMul5+*(ro_V+p1))-
						*(PiXelValueMul5+*(ro_V+p4))+
						*(ro_V+p0)+
						*(ro_V+p5)+16)>>5,0,255);
					*(ro_D+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_D+p2))+
						*(PixelValueMul20+*(ro_D+p3))-
						*(PiXelValueMul5+*(ro_D+p1))-
						*(PiXelValueMul5+*(ro_D+p4))+
						*(ro_D+p0)+
						*(ro_D+p5)+16)>>5,0,255);
				}
			}
			else if(SynDirection==1)
			{
				//!<synthesize from right
				imgpel* ri_Y=right_input_Y[j];
				imgpel* ri_U=right_input_U[j];
				imgpel* ri_V=right_input_V[j];
				imgpel* ri_D=right_input_depth[j];
				imgpel* ro_Y=right_output_Y[j];
				imgpel* ro_U=right_output_U[j];
				imgpel* ro_V=right_output_V[j];
				imgpel* ro_D=right_output_depth[j];
				for(i=0;i<output_width;i+=2)
				{
					*(ro_Y+i)=*(ri_Y+(i>>1));
					*(ro_U+i)=*(ri_U+(i>>1));
					*(ro_V+i)=*(ri_V+(i>>1));
					*(ro_D+i)=*(ri_D+(i>>1));
				}
				for(i=1;i<output_width;i+=2)
				{
					p0 = CLIP(i-5, 0, output_width_minus2);
					p1 = CLIP(i-3, 0, output_width_minus2);
					p2 = CLIP(i-1  , 0, output_width_minus2);
					p3 = CLIP(i+1, 0, output_width_minus2);
					p4 = CLIP(i+3, 0, output_width_minus2);
					p5 = CLIP(i+5, 0, output_width_minus2);

					*(ro_Y+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_Y+p2))+
						*(PixelValueMul20+*(ro_Y+p3))-
						*(PiXelValueMul5+*(ro_Y+p1))-
						*(PiXelValueMul5+*(ro_Y+p4))+
						*(ro_Y+p0)+
						*(ro_Y+p5)+16)>>5,0,255);
					*(ro_U+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_U+p2))+
						*(PixelValueMul20+*(ro_U+p3))-
						*(PiXelValueMul5+*(ro_U+p1))-
						*(PiXelValueMul5+*(ro_U+p4))+
						*(ro_U+p0)+
						*(ro_U+p5)+16)>>5,0,255);
					*(ro_V+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_V+p2))+
						*(PixelValueMul20+*(ro_V+p3))-
						*(PiXelValueMul5+*(ro_V+p1))-
						*(PiXelValueMul5+*(ro_V+p4))+
						*(ro_V+p0)+
						*(ro_V+p5)+16)>>5,0,255);
					*(ro_D+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_D+p2))+
						*(PixelValueMul20+*(ro_D+p3))-
						*(PiXelValueMul5+*(ro_D+p1))-
						*(PiXelValueMul5+*(ro_D+p4))+
						*(ro_D+p0)+
						*(ro_D+p5)+16)>>5,0,255);
				}
			}
			else if(SynDirection==0)
			{
				//!<synthesize from right
				imgpel* li_Y=left_input_Y[j];
				imgpel* li_U=left_input_U[j];
				imgpel* li_V=left_input_V[j];
				imgpel* li_D=left_input_depth[j];
				imgpel* lo_Y=left_output_Y[j];
				imgpel* lo_U=left_output_U[j];
				imgpel* lo_V=left_output_V[j];
				imgpel* lo_D=left_output_depth[j];

				for(i=0;i<output_width;i+=2)
				{
					*(lo_Y+i)=*(li_Y+(i>>1));
					*(lo_U+i)=*(li_U+(i>>1));
					*(lo_V+i)=*(li_V+(i>>1));
					*(lo_D+i)=*(li_D+(i>>1));
				}
				for(i=1;i<output_width;i+=2)
				{
					p0 = CLIP(i-5, 0, output_width_minus2);
					p1 = CLIP(i-3, 0, output_width_minus2);
					p2 = CLIP(i-1  , 0, output_width_minus2);
					p3 = CLIP(i+1, 0, output_width_minus2);
					p4 = CLIP(i+3, 0, output_width_minus2);
					p5 = CLIP(i+5, 0, output_width_minus2);

					*(lo_Y+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_Y+p2))+
						*(PixelValueMul20+*(lo_Y+p3))-
						*(PiXelValueMul5+*(lo_Y+p1))-
						*(PiXelValueMul5+*(lo_Y+p4))+
						*(lo_Y+p0)+
						*(lo_Y+p5)+16)>>5,0,255);
					*(lo_U+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_U+p2))+
						*(PixelValueMul20+*(lo_U+p3))-
						*(PiXelValueMul5+*(lo_U+p1))-
						*(PiXelValueMul5+*(lo_U+p4))+
						*(lo_U+p0)+
						*(lo_U+p5)+16)>>5,0,255);
					*(lo_V+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_V+p2))+
						*(PixelValueMul20+*(lo_V+p3))-
						*(PiXelValueMul5+*(lo_V+p1))-
						*(PiXelValueMul5+*(lo_V+p4))+
						*(lo_V+p0)+
						*(lo_V+p5)+16)>>5,0,255);
					*(lo_D+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_D+p2))+
						*(PixelValueMul20+*(lo_D+p3))-
						*(PiXelValueMul5+*(lo_D+p1))-
						*(PiXelValueMul5+*(lo_D+p4))+
						*(lo_D+p0)+
						*(lo_D+p5)+16)>>5,0,255);
				}
			}
		}
	}
	else
	{
		assert(0);
	}

	return 0;

}

#if QC_VSP_Asymmetric_Resolution

int CPictureResample::UpsampleRefView420(imgpel**left_output_Y,imgpel**left_input_Y, 
									  imgpel**left_output_U,imgpel**left_input_U, 
									  imgpel**left_output_V,imgpel**left_input_V, 
									  imgpel**left_output_depth,imgpel**left_input_depth,
									  imgpel**right_output_Y,imgpel**right_input_Y, 
									  imgpel**right_output_U,imgpel**right_input_U, 
									  imgpel**right_output_V,imgpel**right_input_V, 
									  imgpel**right_output_depth,imgpel**right_input_depth,
									  int Width, int Height, int Factor,int SynDirection)
{
	int i, j;
	int p0,p1,p2,p3,p4,p5;
	int pel[6];

	if(Factor==4)
	{
		int output_height=Height;
		int output_width=Width*Factor;
		int output_width_minus2 = output_width-2;
		int output_width_minus1 = output_width-1;

		for(j=0;j<output_height;++j)
		{
			for(i=0;i<output_width;i+=4)
			{
				if(left_output_Y&&left_input_Y)
					left_output_Y[j][i]=left_input_Y[j][i>>2];
				
				if(right_output_Y&&right_input_Y)
					right_output_Y[j][i]=right_input_Y[j][i>>2];
				
			}
			for(i=2;i<output_width;i+=2)
			{
				pel[0] = CLIP(i-6, 0, output_width_minus2);
				pel[1] = CLIP(i-4, 0, output_width_minus2);
				pel[2] = CLIP(i-2  , 0, output_width_minus2);
				pel[3] = CLIP(i+2, 0, output_width_minus2);
				pel[4] = CLIP(i+4, 0, output_width_minus2);
				pel[5] = CLIP(i+6, 0, output_width_minus2);

				if(left_output_Y&&left_input_Y)
					left_input_Y[j][i]=CLIP((20*(left_input_Y[j][pel[2]]+left_input_Y[j][pel[3]])-
											5*(left_input_Y[j][pel[1]]+left_input_Y[j][pel[4]])+
											(left_input_Y[j][pel[0]]+left_input_Y[j][pel[5]])+16)>>5,0,255);

				if(right_output_Y&&right_input_Y)
					right_output_Y[j][i]=CLIP((20*(right_input_Y[j][pel[2]]+right_input_Y[j][pel[3]])-
											5*(right_input_Y[j][pel[1]]+right_input_Y[j][pel[4]])+
											(right_input_Y[j][pel[0]]+right_input_Y[j][pel[5]])+16)>>5,0,255);
			}

			for(i=1;i<output_width;i+=2)
			{
				pel[0] = CLIP(i-5, 0, output_width_minus1);
				pel[1] = CLIP(i-3, 0, output_width_minus1);
				pel[2] = CLIP(i-1  , 0, output_width_minus1);
				pel[3] = CLIP(i+1, 0, output_width_minus1);
				pel[4] = CLIP(i+3, 0, output_width_minus1);
				pel[5] = CLIP(i+5, 0, output_width_minus1);

				if(left_output_Y&&left_input_Y)
					left_input_Y[j][i]=CLIP((20*(left_input_Y[j][pel[2]]+left_input_Y[j][pel[3]])-
					5*(left_input_Y[j][pel[1]]+left_input_Y[j][pel[4]])+
					(left_input_Y[j][pel[0]]+left_input_Y[j][pel[5]])+16)>>5,0,255);

				if(right_output_Y&&right_input_Y)
					right_output_Y[j][i]=CLIP((20*(right_input_Y[j][pel[2]]+right_input_Y[j][pel[3]])-
					5*(right_input_Y[j][pel[1]]+right_input_Y[j][pel[4]])+
					(right_input_Y[j][pel[0]]+right_input_Y[j][pel[5]])+16)>>5,0,255);
			}
		}

		// U V and depth are quarter size of Y
		output_height=Height/2;
		output_width=Width/2*Factor;
		output_width_minus2 = output_width-2;
		output_width_minus1 = output_width-1;

		for(j=0;j<output_height;++j)
		{
			for(i=0;i<output_width;i+=4)
			{
				if(left_output_U&&left_input_U)
					left_output_U[j][i]=left_input_U[j][i>>2];
				if(left_output_V&&left_input_V)
					left_output_V[j][i]=left_input_V[j][i>>2];
				if(left_output_depth&&right_input_depth)
					left_output_depth[j][i]=left_input_depth[j][i>>2];
			
				if(right_output_U&&right_input_U)
					right_output_U[j][i]=right_input_U[j][i>>2];
				if(right_output_V&&right_input_V)
					right_output_V[j][i]=right_input_V[j][i>>2];
				if(right_output_depth&&right_input_depth)
					right_output_depth[j][i]=right_input_depth[j][i>>2];
			}
			for(i=2;i<output_width;i+=2)
			{
				pel[0] = CLIP(i-6, 0, output_width_minus2);
				pel[1] = CLIP(i-4, 0, output_width_minus2);
				pel[2] = CLIP(i-2  , 0, output_width_minus2);
				pel[3] = CLIP(i+2, 0, output_width_minus2);
				pel[4] = CLIP(i+4, 0, output_width_minus2);
				pel[5] = CLIP(i+6, 0, output_width_minus2);

				if(left_output_U&&left_input_U)
					left_input_U[j][i]=CLIP((20*(left_input_U[j][pel[2]]+left_input_U[j][pel[3]])-
											5*(left_input_U[j][pel[1]]+left_input_U[j][pel[4]])+
											(left_input_U[j][pel[0]]+left_input_U[j][pel[5]])+16)>>5,0,255);
				if(left_output_V&&left_input_V)
					left_output_V[j][i]=CLIP((20*(left_input_V[j][pel[2]]+left_input_V[j][pel[3]])-
											5*(left_input_V[j][pel[1]]+left_input_V[j][pel[4]])+
											(left_input_V[j][pel[0]]+left_input_V[j][pel[5]])+16)>>5,0,255);
				if(left_output_depth&&right_input_depth)
					left_output_depth[j][i]=CLIP((20*(left_input_depth[j][pel[2]]+left_input_depth[j][pel[3]])-
											5*(left_input_depth[j][pel[1]]+left_input_depth[j][pel[4]])+
											(left_input_depth[j][pel[0]]+left_input_depth[j][pel[5]])+16)>>5,0,255);

				if(right_output_U&&right_input_U)
					right_output_U[j][i]=CLIP((20*(right_input_U[j][pel[2]]+right_input_U[j][pel[3]])-
											5*(right_input_U[j][pel[1]]+right_input_U[j][pel[4]])+
											(right_input_U[j][pel[0]]+right_input_U[j][pel[5]])+16)>>5,0,255);
				if(right_output_V&&right_input_V)
					right_output_V[j][i]=CLIP((20*(right_input_V[j][pel[2]]+right_input_V[j][pel[3]])-
											5*(right_input_V[j][pel[1]]+right_input_V[j][pel[4]])+
											(right_input_V[j][pel[0]]+right_input_V[j][pel[5]])+16)>>5,0,255);
				if(right_output_depth&&right_input_depth)
					right_output_depth[j][i]=CLIP((20*(right_input_depth[j][pel[2]]+right_input_depth[j][pel[3]])-
													5*(right_input_depth[j][pel[1]]+right_input_depth[j][pel[4]])+
													(right_input_depth[j][pel[0]]+right_input_depth[j][pel[5]])+16)>>5,0,255);
			}

			for(i=1;i<output_width;i+=2)
			{
				pel[0] = CLIP(i-5, 0, output_width_minus1);
				pel[1] = CLIP(i-3, 0, output_width_minus1);
				pel[2] = CLIP(i-1  , 0, output_width_minus1);
				pel[3] = CLIP(i+1, 0, output_width_minus1);
				pel[4] = CLIP(i+3, 0, output_width_minus1);
				pel[5] = CLIP(i+5, 0, output_width_minus1);

				if(left_output_U&&left_input_U)
					left_input_U[j][i]=CLIP((20*(left_input_U[j][pel[2]]+left_input_U[j][pel[3]])-
					5*(left_input_U[j][pel[1]]+left_input_U[j][pel[4]])+
					(left_input_U[j][pel[0]]+left_input_U[j][pel[5]])+16)>>5,0,255);
				if(left_output_V&&left_input_V)
					left_output_V[j][i]=CLIP((20*(left_input_V[j][pel[2]]+left_input_V[j][pel[3]])-
					5*(left_input_V[j][pel[1]]+left_input_V[j][pel[4]])+
					(left_input_V[j][pel[0]]+left_input_V[j][pel[5]])+16)>>5,0,255);
				if(left_output_depth&&right_input_depth)
					left_output_depth[j][i]=CLIP((20*(left_input_depth[j][pel[2]]+left_input_depth[j][pel[3]])-
					5*(left_input_depth[j][pel[1]]+left_input_depth[j][pel[4]])+
					(left_input_depth[j][pel[0]]+left_input_depth[j][pel[5]])+16)>>5,0,255);

				if(right_output_U&&right_input_U)
					right_output_U[j][i]=CLIP((20*(right_input_U[j][pel[2]]+right_input_U[j][pel[3]])-
					5*(right_input_U[j][pel[1]]+right_input_U[j][pel[4]])+
					(right_input_U[j][pel[0]]+right_input_U[j][pel[5]])+16)>>5,0,255);
				if(right_output_V&&right_input_V)
					right_output_V[j][i]=CLIP((20*(right_input_V[j][pel[2]]+right_input_V[j][pel[3]])-
					5*(right_input_V[j][pel[1]]+right_input_V[j][pel[4]])+
					(right_input_V[j][pel[0]]+right_input_V[j][pel[5]])+16)>>5,0,255);
				if(right_output_depth&&right_input_depth)
						right_output_depth[j][i]=CLIP((20*(right_input_depth[j][pel[2]]+right_input_depth[j][pel[3]])-
						5*(right_input_depth[j][pel[1]]+right_input_depth[j][pel[4]])+
						(right_input_depth[j][pel[0]]+right_input_depth[j][pel[5]])+16)>>5,0,255);
			}
		}
	}
	else if(Factor==2)
	{
		int output_height=Height;
		int output_width=Width*Factor;
		int output_width_minus2 = output_width-2;
		
		for(j=0;j<output_height;++j)
		{
			if(SynDirection==2)
			{
				//!<synthesize from left and right
				imgpel* li_Y=left_input_Y[j];
				imgpel* lo_Y=left_output_Y[j];
				imgpel* ri_Y=right_input_Y[j];
				imgpel* ro_Y=right_output_Y[j];
				
				for(i=0;i<output_width;i+=2)
				{
					*(lo_Y+i)=*(li_Y+(i>>1));
					*(ro_Y+i)=*(ri_Y+(i>>1));
				}
				for(i=1;i<output_width;i+=2)
				{
					p0 = CLIP(i-5, 0, output_width_minus2);
					p1 = CLIP(i-3, 0, output_width_minus2);
					p2 = CLIP(i-1  , 0, output_width_minus2);
					p3 = CLIP(i+1, 0, output_width_minus2);
					p4 = CLIP(i+3, 0, output_width_minus2);
					p5 = CLIP(i+5, 0, output_width_minus2);

					*(lo_Y+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_Y+p2))+
						*(PixelValueMul20+*(lo_Y+p3))-
						*(PiXelValueMul5+*(lo_Y+p1))-
						*(PiXelValueMul5+*(lo_Y+p4))+
						*(lo_Y+p0)+
						*(lo_Y+p5)+16)>>5,0,255);
					*(ro_Y+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_Y+p2))+
						*(PixelValueMul20+*(ro_Y+p3))-
						*(PiXelValueMul5+*(ro_Y+p1))-
						*(PiXelValueMul5+*(ro_Y+p4))+
						*(ro_Y+p0)+
						*(ro_Y+p5)+16)>>5,0,255);				
				}
			}
			else if(SynDirection==1)
			{
				//!<synthesize from right
				imgpel* ri_Y=right_input_Y[j];
				imgpel* ro_Y=right_output_Y[j];
				for(i=0;i<output_width;i+=2)
				{
					*(ro_Y+i)=*(ri_Y+(i>>1));				
				}
				for(i=1;i<output_width;i+=2)
				{
					p0 = CLIP(i-5, 0, output_width_minus2);
					p1 = CLIP(i-3, 0, output_width_minus2);
					p2 = CLIP(i-1  , 0, output_width_minus2);
					p3 = CLIP(i+1, 0, output_width_minus2);
					p4 = CLIP(i+3, 0, output_width_minus2);
					p5 = CLIP(i+5, 0, output_width_minus2);

					*(ro_Y+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_Y+p2))+
						*(PixelValueMul20+*(ro_Y+p3))-
						*(PiXelValueMul5+*(ro_Y+p1))-
						*(PiXelValueMul5+*(ro_Y+p4))+
						*(ro_Y+p0)+
						*(ro_Y+p5)+16)>>5,0,255);					
				}
			}
			else if(SynDirection==0)
			{
				//!<synthesize from right
				imgpel* li_Y=left_input_Y[j];				
				imgpel* lo_Y=left_output_Y[j];
				
				for(i=0;i<output_width;i+=2)
				{
					*(lo_Y+i)=*(li_Y+(i>>1));
				}
				for(i=1;i<output_width;i+=2)
				{
					p0 = CLIP(i-5, 0, output_width_minus2);
					p1 = CLIP(i-3, 0, output_width_minus2);
					p2 = CLIP(i-1  , 0, output_width_minus2);
					p3 = CLIP(i+1, 0, output_width_minus2);
					p4 = CLIP(i+3, 0, output_width_minus2);
					p5 = CLIP(i+5, 0, output_width_minus2);

					*(lo_Y+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_Y+p2))+
						*(PixelValueMul20+*(lo_Y+p3))-
						*(PiXelValueMul5+*(lo_Y+p1))-
						*(PiXelValueMul5+*(lo_Y+p4))+
						*(lo_Y+p0)+
						*(lo_Y+p5)+16)>>5,0,255);					
				}
			}
		}//


		// for U, V component and depth
		output_height=Height/2;
		output_width=Width/2*Factor;
		output_width_minus2 = output_width-2;
		
		for(j=0;j<output_height;++j)
		{
			if(SynDirection==2)
			{
				//!<synthesize from left and right
				imgpel* li_U=left_input_U[j];
				imgpel* li_V=left_input_V[j];
				imgpel* li_D=left_input_depth[j];
				
				imgpel* lo_U=left_output_U[j];
				imgpel* lo_V=left_output_V[j];
				imgpel* lo_D=left_output_depth[j];
				
				imgpel* ri_U=right_input_U[j];
				imgpel* ri_V=right_input_V[j];
				imgpel* ri_D=right_input_depth[j];
				
				imgpel* ro_U=right_output_U[j];
				imgpel* ro_V=right_output_V[j];
				imgpel* ro_D=right_output_depth[j];
				for(i=0;i<output_width;i+=2)
				{
					*(lo_U+i)=*(li_U+(i>>1));
					*(lo_V+i)=*(li_V+(i>>1));
					*(lo_D+i)=*(li_D+(i>>1));
					
					*(ro_U+i)=*(ri_U+(i>>1));
					*(ro_V+i)=*(ri_V+(i>>1));
					*(ro_D+i)=*(ri_D+(i>>1));
				}
				for(i=1;i<output_width;i+=2)
				{
					p0 = CLIP(i-5, 0, output_width_minus2);
					p1 = CLIP(i-3, 0, output_width_minus2);
					p2 = CLIP(i-1  , 0, output_width_minus2);
					p3 = CLIP(i+1, 0, output_width_minus2);
					p4 = CLIP(i+3, 0, output_width_minus2);
					p5 = CLIP(i+5, 0, output_width_minus2);

					*(lo_U+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_U+p2))+
						*(PixelValueMul20+*(lo_U+p3))-
						*(PiXelValueMul5+*(lo_U+p1))-
						*(PiXelValueMul5+*(lo_U+p4))+
						*(lo_U+p0)+
						*(lo_U+p5)+16)>>5,0,255);
					*(lo_V+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_V+p2))+
						*(PixelValueMul20+*(lo_V+p3))-
						*(PiXelValueMul5+*(lo_V+p1))-
						*(PiXelValueMul5+*(lo_V+p4))+
						*(lo_V+p0)+
						*(lo_V+p5)+16)>>5,0,255);
					*(lo_D+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_D+p2))+
						*(PixelValueMul20+*(lo_D+p3))-
						*(PiXelValueMul5+*(lo_D+p1))-
						*(PiXelValueMul5+*(lo_D+p4))+
						*(lo_D+p0)+
						*(lo_D+p5)+16)>>5,0,255);
					
					*(ro_U+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_U+p2))+
						*(PixelValueMul20+*(ro_U+p3))-
						*(PiXelValueMul5+*(ro_U+p1))-
						*(PiXelValueMul5+*(ro_U+p4))+
						*(ro_U+p0)+
						*(ro_U+p5)+16)>>5,0,255);
					*(ro_V+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_V+p2))+
						*(PixelValueMul20+*(ro_V+p3))-
						*(PiXelValueMul5+*(ro_V+p1))-
						*(PiXelValueMul5+*(ro_V+p4))+
						*(ro_V+p0)+
						*(ro_V+p5)+16)>>5,0,255);
					*(ro_D+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_D+p2))+
						*(PixelValueMul20+*(ro_D+p3))-
						*(PiXelValueMul5+*(ro_D+p1))-
						*(PiXelValueMul5+*(ro_D+p4))+
						*(ro_D+p0)+
						*(ro_D+p5)+16)>>5,0,255);
				}
			}
			else if(SynDirection==1)
			{
				//!<synthesize from right
				imgpel* ri_U=right_input_U[j];
				imgpel* ri_V=right_input_V[j];
				imgpel* ri_D=right_input_depth[j];
				
				imgpel* ro_U=right_output_U[j];
				imgpel* ro_V=right_output_V[j];
				imgpel* ro_D=right_output_depth[j];
				
				for(i=0;i<output_width;i+=2)
				{				
					*(ro_U+i)=*(ri_U+(i>>1));
					*(ro_V+i)=*(ri_V+(i>>1));
					*(ro_D+i)=*(ri_D+(i>>1));
				}
				for(i=1;i<output_width;i+=2)
				{
					p0 = CLIP(i-5, 0, output_width_minus2);
					p1 = CLIP(i-3, 0, output_width_minus2);
					p2 = CLIP(i-1  , 0, output_width_minus2);
					p3 = CLIP(i+1, 0, output_width_minus2);
					p4 = CLIP(i+3, 0, output_width_minus2);
					p5 = CLIP(i+5, 0, output_width_minus2);

					*(ro_U+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_U+p2))+
						*(PixelValueMul20+*(ro_U+p3))-
						*(PiXelValueMul5+*(ro_U+p1))-
						*(PiXelValueMul5+*(ro_U+p4))+
						*(ro_U+p0)+
						*(ro_U+p5)+16)>>5,0,255);
					*(ro_V+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_V+p2))+
						*(PixelValueMul20+*(ro_V+p3))-
						*(PiXelValueMul5+*(ro_V+p1))-
						*(PiXelValueMul5+*(ro_V+p4))+
						*(ro_V+p0)+
						*(ro_V+p5)+16)>>5,0,255);
					*(ro_D+i)=(imgpel)CLIP((*(PixelValueMul20+*(ro_D+p2))+
						*(PixelValueMul20+*(ro_D+p3))-
						*(PiXelValueMul5+*(ro_D+p1))-
						*(PiXelValueMul5+*(ro_D+p4))+
						*(ro_D+p0)+
						*(ro_D+p5)+16)>>5,0,255);
				}
			}
			else if(SynDirection==0)
			{
				//!<synthesize from right
				imgpel* li_U=left_input_U[j];
				imgpel* li_V=left_input_V[j];
				imgpel* li_D=left_input_depth[j];
				
				imgpel* lo_U=left_output_U[j];
				imgpel* lo_V=left_output_V[j];
				imgpel* lo_D=left_output_depth[j];

				for(i=0;i<output_width;i+=2)
				{
					*(lo_U+i)=*(li_U+(i>>1));
					*(lo_V+i)=*(li_V+(i>>1));
					*(lo_D+i)=*(li_D+(i>>1));
				}
				for(i=1;i<output_width;i+=2)
				{
					p0 = CLIP(i-5, 0, output_width_minus2);
					p1 = CLIP(i-3, 0, output_width_minus2);
					p2 = CLIP(i-1  , 0, output_width_minus2);
					p3 = CLIP(i+1, 0, output_width_minus2);
					p4 = CLIP(i+3, 0, output_width_minus2);
					p5 = CLIP(i+5, 0, output_width_minus2);

					*(lo_U+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_U+p2))+
						*(PixelValueMul20+*(lo_U+p3))-
						*(PiXelValueMul5+*(lo_U+p1))-
						*(PiXelValueMul5+*(lo_U+p4))+
						*(lo_U+p0)+
						*(lo_U+p5)+16)>>5,0,255);
					*(lo_V+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_V+p2))+
						*(PixelValueMul20+*(lo_V+p3))-
						*(PiXelValueMul5+*(lo_V+p1))-
						*(PiXelValueMul5+*(lo_V+p4))+
						*(lo_V+p0)+
						*(lo_V+p5)+16)>>5,0,255);
					*(lo_D+i)=(imgpel)CLIP((*(PixelValueMul20+*(lo_D+p2))+
						*(PixelValueMul20+*(lo_D+p3))-
						*(PiXelValueMul5+*(lo_D+p1))-
						*(PiXelValueMul5+*(lo_D+p4))+
						*(lo_D+p0)+
						*(lo_D+p5)+16)>>5,0,255);
				}
			}
		} // end for(j=0;j<output_height;++j): U, V, depth component
	}
	else
	{
		assert(0);
	}

	return 0;

}
#endif

/*
 * \brief
 *    Downsample the picture, and we will get more warped pixels in the synthesized picture
 * 
 * \input
 * \param Yi
 *    The input image.  Resolution is Width, Height
 * \param Width, Height
 *    The resolution of the input picture
 * \param Factor
 *    Must be 2 or 4. Downsample to 2 times or 4 times
 *
 * \output
 * \param Yo
 *    The output image. Resolution is Width/Factor, Height
 *
 * \return
 *    None
 */
int CPictureResample::DownsampleView(imgpel** Yo, imgpel** Yi, int Width, int Height, int Factor)
{
  imgpel** Ym=NULL;
  
  if (Factor == 2)
    DoDownsample(Yo, Yi, Width, Height);
  else
  {
	  get_mem2D(&Ym,Height,Width/2);

	  DoDownsample(Ym, Yi, Width, Height);
	  DoDownsample(Yo, Ym, Width/2, Height);
	  free_mem2D(Ym);
  }
  
  return 0;
}

int CPictureResample::DownsampleRefView(imgpel**output_Y,imgpel**input_Y, 
										imgpel**output_U,imgpel**input_U, 
										imgpel**output_V,imgpel**input_V, 
										imgpel**output_depth,imgpel**input_depth, 
										int Width, int Height, int Factor)
{
	int h,w;
	int pix_pos[7];
	int width_minus1=Width-1;
	if(Factor==2)
	{
		for(h=0;h<Height;++h)
		{
			for(w=0;w<Width;w+=2)
			{
				pix_pos[0]=CLIP(w-1,0,width_minus1);
				pix_pos[1]=w;
				pix_pos[2]=CLIP(w+1,0,width_minus1);

				if(output_Y&&input_Y)
					output_Y[h][w>>1]=(input_Y[h][pix_pos[0]]+input_Y[h][pix_pos[2]]+2*input_Y[h][pix_pos[1]])>>2;
				if(output_U&&input_U)
					output_U[h][w>>1]=(input_U[h][pix_pos[0]]+input_U[h][pix_pos[2]]+2*input_U[h][pix_pos[1]])>>2;
				if(output_V&&input_V)
					output_V[h][w>>1]=(input_V[h][pix_pos[0]]+input_V[h][pix_pos[2]]+2*input_V[h][pix_pos[1]])>>2;
				if(output_depth&&input_depth)
					input_depth[h][w>>1]=(input_depth[h][pix_pos[0]]+input_depth[h][pix_pos[2]]+2*input_depth[h][pix_pos[1]])>>2;
			}
		}
	}
	else if(Factor==4)
	{
		int pos0,pos1,pos2,pos3,pos4,pos5,pos6;
		for(h=0;h<Height;++h)
		{
			for(w=0;w<Width;w+=4)
			{
				pos0=CLIP(w-3,0,width_minus1);
				pos1=CLIP(w-2,0,width_minus1);
				pos2=CLIP(w-1,0,width_minus1);
				pos3=w;
				pos4=CLIP(w+1,0,width_minus1);
				pos5=CLIP(w+2,0,width_minus1);
				pos6=CLIP(w+3,0,width_minus1);

				if(output_Y&&input_Y)
					output_Y[h][w>>2]=(input_Y[h][pos0]+input_Y[h][pos6]+
											2*(input_Y[h][pos1]+input_Y[h][pos5])+
											3*(input_Y[h][pos2]+input_Y[h][pos4])+
											4*input_Y[h][pos3]+8)>>4;
				if(output_U&&input_U)
					output_U[h][w>>2]=(input_U[h][pos0]+input_U[h][pos6]+
											2*(input_U[h][pos1]+input_U[h][pos5])+
											3*(input_U[h][pos2]+input_U[h][pos4])+
											4*input_U[h][pos3]+8)>>4;
				if(output_V&&input_V)
					output_V[h][w>>2]=(input_V[h][pos0]+input_V[h][pos6]+
											2*(input_V[h][pos1]+input_V[h][pos5])+
											3*(input_V[h][pos2]+input_V[h][pos4])+
											4*input_V[h][pos3]+8)>>4;
				if(output_depth&&input_depth)
					output_depth[h][w>>2]=(input_depth[h][pos0]+input_depth[h][pos6]+
												2*(input_depth[h][pos1]+input_depth[h][pos5])+
												3*(input_depth[h][pos2]+input_depth[h][pos4])+
												4*input_depth[h][pos3]+8)>>4;

			}
		}
	}
	return 0;
}


#if QC_VSP_Asymmetric_Resolution
int CPictureResample::DownsampleRefView420(imgpel**output_Y,imgpel**input_Y, 
										imgpel**output_U,imgpel**input_U, 
										imgpel**output_V,imgpel**input_V, 
										imgpel**output_depth,imgpel**input_depth, 
										int Width, int Height, int Factor)
{
	int h,w;
	int pix_pos[7];
	int width_minus1=Width-1;
	if(Factor==2)
	{
		for(h=0;h<Height;++h)
		{
			for(w=0;w<Width;w+=2)
			{
				pix_pos[0]=CLIP(w-1,0,width_minus1);
				pix_pos[1]=w;
				pix_pos[2]=CLIP(w+1,0,width_minus1);

				if(output_Y&&input_Y)
					output_Y[h][w>>1]=(input_Y[h][pix_pos[0]]+input_Y[h][pix_pos[2]]+2*input_Y[h][pix_pos[1]])>>2;				
			}
		}

		//UV are quarter size of Y
		for(h=0;h<Height/2;++h)
		{
			for(w=0;w<Width/2;w+=2)
			{
				pix_pos[0]=CLIP(w-1,0,width_minus1);
				pix_pos[1]=w;
				pix_pos[2]=CLIP(w+1,0,width_minus1);

				if(output_U&&input_U)
					output_U[h][w>>1]=(input_U[h][pix_pos[0]]+input_U[h][pix_pos[2]]+2*input_U[h][pix_pos[1]])>>2;
				if(output_V&&input_V)
					output_V[h][w>>1]=(input_V[h][pix_pos[0]]+input_V[h][pix_pos[2]]+2*input_V[h][pix_pos[1]])>>2;
				if(output_depth&&input_depth)
					input_depth[h][w>>1]=(input_depth[h][pix_pos[0]]+input_depth[h][pix_pos[2]]+2*input_depth[h][pix_pos[1]])>>2;
			}
		}
	}
	else if(Factor==4)
	{
		int pos0,pos1,pos2,pos3,pos4,pos5,pos6;

		for(h=0;h<Height;++h)
		{
			for(w=0;w<Width;w+=4)
			{
				pos0=CLIP(w-3,0,width_minus1);
				pos1=CLIP(w-2,0,width_minus1);
				pos2=CLIP(w-1,0,width_minus1);
				pos3=w;
				pos4=CLIP(w+1,0,width_minus1);
				pos5=CLIP(w+2,0,width_minus1);
				pos6=CLIP(w+3,0,width_minus1);

				if(output_Y&&input_Y)
					output_Y[h][w>>2]=(input_Y[h][pos0]+input_Y[h][pos6]+
											2*(input_Y[h][pos1]+input_Y[h][pos5])+
											3*(input_Y[h][pos2]+input_Y[h][pos4])+
											4*input_Y[h][pos3]+8)>>4;
			}
		}

		//UV are quarter size of Y
		for(h=0;h<Height/2;++h)
		{
			for(w=0;w<Width/2;w+=4)
			{
				pos0=CLIP(w-3,0,width_minus1);
				pos1=CLIP(w-2,0,width_minus1);
				pos2=CLIP(w-1,0,width_minus1);
				pos3=w;
				pos4=CLIP(w+1,0,width_minus1);
				pos5=CLIP(w+2,0,width_minus1);
				pos6=CLIP(w+3,0,width_minus1);

				if(output_U&&input_U)
					output_U[h][w>>2]=(input_U[h][pos0]+input_U[h][pos6]+
											2*(input_U[h][pos1]+input_U[h][pos5])+
											3*(input_U[h][pos2]+input_U[h][pos4])+
											4*input_U[h][pos3]+8)>>4;
				if(output_V&&input_V)
					output_V[h][w>>2]=(input_V[h][pos0]+input_V[h][pos6]+
											2*(input_V[h][pos1]+input_V[h][pos5])+
											3*(input_V[h][pos2]+input_V[h][pos4])+
											4*input_V[h][pos3]+8)>>4;
				if(output_depth&&input_depth)
					output_depth[h][w>>2]=(input_depth[h][pos0]+input_depth[h][pos6]+
												2*(input_depth[h][pos1]+input_depth[h][pos5])+
												3*(input_depth[h][pos2]+input_depth[h][pos4])+
												4*input_depth[h][pos3]+8)>>4;

			}
		}
	}
	return 0;
}

#endif

