
#include "win32.h"
#include "defines.h"
#include "typedefs.h"
#include "ifunctions.h"
#include "memalloc.h"
#include "resample.h"


#define TAP_10_FLT 1          // 1: use a set of 10-tap filters for downsampling; 0: a set of 12-taps.
#define KAISER_FLT 0          // 1: use Kaiser filter, 0: use sine-windowed filter


static  imgpel Clip( int iValue, int imin, int imax )   ;
static void ConvertImgpelToIntBuffer(ResizeParameters * pResizeParameters,int component);
static void ConvertIntBufferToImgpel(ResizeParameters* pResizeParameters,int component);
#if 0 // Outdated functionality
static void Downsampling( ResizeParameters* pResizeParameters, int component ) ;
static void img_downSample ( ResizeParameters*  ResizeParams, int component);
#endif
static void Upsampling(ResizeParameters* pResizeParameters, int component,int method )	 ;
static void img_upSample(ResizeParameters*  ResizeParams, int component, int method);

static void img_bilinear_fast( imgpel** low_img,imgpel** high_img,int low_height, int low_width, int high_height, int high_width);


static imgpel Clip( int iValue, int imin, int imax )
{
	int tmp;
	imgpel rV ;
	memset(&rV,0x00,sizeof(imgpel));
	tmp= ( iValue < imin ? imin : iValue > imax ? imax : iValue );
	memcpy(&rV,&tmp,sizeof(imgpel))  ;

	return rV;
}
static void ConvertImgpelToIntBuffer(ResizeParameters * pResizeParameters,int component)
{
	int src_stride;
	int img_stride=	pResizeParameters->img_stride;

	imgpel* imgpel_Src=pResizeParameters->img_buffer[component];
	int * pDst=pResizeParameters->resize_buffer;

	int width=pResizeParameters->input_width;
	int height=pResizeParameters->input_height;

	int i,j,tmp;

	if((component<0)||(component>2))
	{
		printf("invalid imgpel component\n");
		exit(1);
	}

	if(component>0)
	{
		width=width>>1;
		height=height>>1;
	}


	if(pResizeParameters->down_sample)
		src_stride=pResizeParameters->input_stride[component];
	else
		src_stride=pResizeParameters->output_stride[component];

	for( j = 0; j < height; j++ )
	{
		for( i = 0; i < width;  i++ )
		{
			//	tmp=0x00;
			//	printf("%d\n",tmp);
			memset(&tmp,0x00,sizeof(int));
			memcpy(&tmp,&(imgpel_Src[i]),sizeof(imgpel));
			pDst[i] = tmp;
		}
		pDst+=img_stride;
		imgpel_Src+=src_stride;
	}
	return ;
}

static void ConvertIntBufferToImgpel(ResizeParameters* pResizeParameters,int component)
{

	int dst_stride;
	int img_stride=pResizeParameters->	img_stride;

	int* pSrc=	 pResizeParameters->resize_buffer;
	imgpel* imgpel_dst=pResizeParameters->img_buffer[component];


	int width=pResizeParameters->output_width;
	int height=pResizeParameters->output_heigh;

	int i,j;
	int minValue=pResizeParameters->minValue;
	int maxValue=pResizeParameters->maxValue;

	if((component<0)||(component>2))
	{
		printf("invalid imgpel component\n");
		exit(1);
	}

	if(pResizeParameters->down_sample)
		dst_stride=pResizeParameters->input_stride[component];
	else
		dst_stride=pResizeParameters->output_stride[component];

	if(component>0)
	{
		width=width>>1;
		height=height>>1;
	}

	for( j = 0; j < height; j++ )
	{
		for( i = 0; i < width;  i++ )
		{
			imgpel_dst[i] = Clip( pSrc[i], minValue, maxValue );
		}
		imgpel_dst+= dst_stride;
		pSrc += img_stride;
	}
}

static int calcute_ref_pixel_pos(ResizeParameters* pResizeParameters)
{
	int input_width=pResizeParameters->input_width;
	int input_height=pResizeParameters->input_height;
	int output_width=pResizeParameters->output_width;
	int output_height=pResizeParameters->output_heigh;
	int crop_x0=pResizeParameters->crop_x0;
	int crop_y0=pResizeParameters->crop_y0;
	int crop_w=pResizeParameters->crop_w;
	int crop_h =pResizeParameters->crop_h;
	int input_chroma_phase_shift_x= 0;
	int input_chroma_phase_shift_y= 0;
	int output_chroma_phase_shift_x=0;
	int output_chroma_phase_shift_y=0;
	int i=0,j=0;
	int memory_size=0;

	if(!pResizeParameters->down_sample)
	{
		int ratio1_flag ;
		int G = 2, J, M, S = 12;
		unsigned short C, C1, D1;
		int D, E, q, w;

		for(i=0;i<2;++i)
		{
			if(i)
			{
				//!<UV
				input_width=input_width>>1;
				input_height=input_height>>1;
				output_width=output_width>>1;
				output_height=output_height>>1;
				crop_x0=crop_x0>>1;
				crop_y0=crop_y0>>1;
				crop_h=crop_h>>1;
				crop_w=crop_w>>1;
				input_chroma_phase_shift_x= pResizeParameters->input_chroma_phase_shift_x;
				input_chroma_phase_shift_y= pResizeParameters->input_chroma_phase_shift_y;
				output_chroma_phase_shift_x=pResizeParameters->output_chroma_phase_shift_x;
				output_chroma_phase_shift_y= pResizeParameters->output_chroma_phase_shift_y;
			}
			ratio1_flag= ( input_width == crop_w );

			// initialization
			pResizeParameters->pos_x[i]=(int*)malloc(output_width*sizeof(int));
			pResizeParameters->pos_y[i]=(int*)malloc(output_height*sizeof(int));
			memory_size+=(output_width+output_height)*sizeof(int);

			for(j=0; j<crop_x0; ++j)  
				pResizeParameters->pos_x[i][j] = -128;

			for(j=crop_x0+crop_w; j<output_width; ++j)  
				pResizeParameters->pos_x[i][j] = -128;

			if(ratio1_flag)
			{
				for(j = 0; j < crop_w; j++)
				{
					pResizeParameters->pos_x[i][j+crop_x0] = j*16+4*(2+output_chroma_phase_shift_x)-4*(2+input_chroma_phase_shift_x);
				}
			}
			else
			{
				J = 1;
				M = 13; 
				if(i)
				{
					J ++;
					M --;
				}

				// S = M + G +  J  - F;

				C = (unsigned short)( ((1<<(M+G))*input_width + (crop_w>>1))/crop_w );
				//D = ((-1)<<(G-1+J+M)) + (1<<(S-1)) - (input_chroma_phase_shift_x<<(G-2+J+M));
				D = ((-1)<<15) + (1<<11) - (input_chroma_phase_shift_x<<14);

				C1 = C<<J;
				E = 0;

				q = (C<<(J-1)) + D + (C<<(J-2))*output_chroma_phase_shift_x;
				w = q>>S;
				D1 = (unsigned short)(q - (w<<S));
				E += w;
				pResizeParameters->pos_x[i][0+crop_x0] = E;

				for(j = 1; j < crop_w; ++j)
				{
					q = C1 + D1;
					w = q>>S;
					D1 = (unsigned short)(q - (w<<S));
					E += w;	  
					pResizeParameters->pos_x[i][j+crop_x0] = E;
				}
			}

			ratio1_flag = ( input_height == crop_h );

			for(j=0; j<crop_y0; j++)   
				pResizeParameters->pos_y[i][j] = -128;

			for(j=crop_y0+crop_h; j<output_height; j++) 
				pResizeParameters->pos_y[i][j] = -128;

			if(ratio1_flag)
			{
				for(j = 0; j < crop_h; j++)
				{
					pResizeParameters->pos_y[i][j+crop_y0] = j*16+4*(2+output_chroma_phase_shift_y)-4*(2+input_chroma_phase_shift_y);
				}
			}
			else
			{
				J = 1; M = 13; 
				if(i)
				{
					J ++;
					M --;
				};
				// S = M + G +  J  - F;

				C = (unsigned short)(((1<<(M+G))*input_height + (crop_h>>1))/crop_h);
				//D = ((-1)<<(G-1+J+M)) + (1<<(S-1)) - (input_chroma_phase_shift_y<<(G-2+J+M));
				D = ((-1)<<15) + (1<<11) - (input_chroma_phase_shift_y<<14);

				C1 = C<<J;
				E = 0;

				q = (C<<(J-1)) + D + (C<<(J-2))*output_chroma_phase_shift_y;
				w = q>>S;
				D1 = (unsigned short)(q - (w<<S));
				E += w;
				pResizeParameters->pos_y[i][0+crop_y0] = E;

				for(j = 1; j < crop_h; j++)
				{
					q = C1 + D1;
					w = q>>S;
					D1 = (unsigned short)(q - (w<<S));
					E += w;	  
					pResizeParameters->pos_y[i][j+crop_y0] = E;
				}
			}


		}
	}
	else
	{
		for(i=0;i<2;++i)
		{
			if(i)
			{
				input_width=input_width>>1;
				input_height=input_height>>1;
				output_width=output_width>>1;
				output_height=output_height>>1;
				crop_x0=crop_x0>>1;
				crop_y0=crop_y0>>1;
				crop_h=crop_h>>1;
				crop_w=crop_w>>1;

				input_chroma_phase_shift_x=pResizeParameters->input_chroma_phase_shift_x;
				input_chroma_phase_shift_y =pResizeParameters->input_chroma_phase_shift_y;
				output_chroma_phase_shift_x=pResizeParameters->output_chroma_phase_shift_x;
				output_chroma_phase_shift_y=pResizeParameters->output_chroma_phase_shift_y;
			}

			// initialization
			pResizeParameters->pos_x[i]=(int*)malloc(output_width*sizeof(int));
			pResizeParameters->pos_y[i]=(int*)malloc(output_height*sizeof(int));

			memory_size+=(output_width+output_height)*sizeof(int);

			for( j = 0; j < output_width; ++j )
			{
				pResizeParameters->pos_x[i][j] = 16*crop_x0 + ( j*crop_w*16 + 4*(2+output_chroma_phase_shift_x)*crop_w - 4*(2+input_chroma_phase_shift_x)*output_width + output_width/2) / output_width;
			}


			for( j = 0; j < output_height; ++j )
			{
				pResizeParameters->pos_y[i][j] = 16*crop_y0 + ( j*crop_h*16 + 4*(2+output_chroma_phase_shift_y)*crop_h - 4*(2+input_chroma_phase_shift_y)*output_height + output_height/2 ) / output_height;
			}

		}
	}

	return memory_size;
}
#if 0 // Outdated functionality
static void Downsampling( ResizeParameters* pResizeParameters, int component ) 
{
	const int filter16[8][16][12] = 
	{   // sine, N = 3
		{ // D = 1
			{0,0,0,0,0,128,0,0,0,0,0,0},
			{0,0,0,2,-6,127,7,-2,0,0,0,0},
			{0,0,0,3,-12,125,16,-5,1,0,0,0},
			{0,0,0,4,-16,120,26,-7,1,0,0,0},
			{0,0,0,5,-18,114,36,-10,1,0,0,0},
			{0,0,0,5,-20,107,46,-12,2,0,0,0},
			{0,0,0,5,-21,99,57,-15,3,0,0,0},
			{0,0,0,5,-20,89,68,-18,4,0,0,0},
			{0,0,0,4,-19,79,79,-19,4,0,0,0},
			{0,0,0,4,-18,68,89,-20,5,0,0,0},
			{0,0,0,3,-15,57,99,-21,5,0,0,0},
			{0,0,0,2,-12,46,107,-20,5,0,0,0},
			{0,0,0,1,-10,36,114,-18,5,0,0,0},
			{0,0,0,1,-7,26,120,-16,4,0,0,0},
			{0,0,0,1,-5,16,125,-12,3,0,0,0},
			{0,0,0,0,-2,7,127,-6,2,0,0,0}
		},
		{ // D = 1.5
			{0,2,0,-14,33,86,33,-14,0,2,0,0},
			{0,1,1,-14,29,85,38,-13,-1,2,0,0},
			{0,1,2,-14,24,84,43,-12,-2,2,0,0},
			{0,1,2,-13,19,83,48,-11,-3,2,0,0},
			{0,0,3,-13,15,81,53,-10,-4,3,0,0},
			{0,0,3,-12,11,79,57,-8,-5,3,0,0},
			{0,0,3,-11,7,76,62,-5,-7,3,0,0},
			{0,0,3,-10,3,73,65,-2,-7,3,0,0},
			{0,0,3,-9,0,70,70,0,-9,3,0,0},
			{0,0,3,-7,-2,65,73,3,-10,3,0,0},
			{0,0,3,-7,-5,62,76,7,-11,3,0,0},
			{0,0,3,-5,-8,57,79,11,-12,3,0,0},
			{0,0,3,-4,-10,53,81,15,-13,3,0,0},
			{0,0,2,-3,-11,48,83,19,-13,2,1,0},
			{0,0,2,-2,-12,43,84,24,-14,2,1,0},
			{0,0,2,-1,-13,38,85,29,-14,1,1,0}
		},
#if KAISER_FLT
		{ // Kaiser, N=3, D=2, beta=4
			{2,0,-9,0,39,64,39,0,-9,0,2,0},
			{2,0,-8,-2,36,64,41,2,-9,0,2,0},
			{2,1,-8,-3,33,63,44,4,-9,-1,2,0},
			{1,1,-7,-4,31,63,46,5,-9,-1,2,0},
			{1,1,-7,-5,28,62,49,8,-9,-2,2,0},
			{1,2,-6,-6,25,61,51,10,-9,-3,2,0},
			{1,2,-6,-7,22,60,53,12,-9,-3,2,1},
			{1,2,-5,-8,20,58,55,15,-9,-4,2,1},
			{1,2,-4,-8,17,56,56,17,-8,-4,2,1},
			{1,2,-4,-9,15,55,58,20,-8,-5,2,1},
			{1,2,-3,-9,12,53,60,22,-7,-6,2,1},
			{0,2,-3,-9,10,51,61,25,-6,-6,2,1},
			{0,2,-2,-9,8,49,62,28,-5,-7,1,1},
			{0,2,-1,-9,5,46,63,31,-4,-7,1,1},
			{0,2,-1,-9,4,44,63,33,-3,-8,1,2},
			{0,2,0,-9,2,41,64,36,-2,-8,0,2}
		},
#else
		{ // D = 2
			{2,0,-10,0,40,64,40,0,-10,0,2,0},
			{2,1,-9,-2,37,64,42,2,-10,-1,2,0},
			{2,1,-9,-3,34,64,44,4,-10,-1,2,0},
			{2,1,-8,-5,31,63,47,6,-10,-2,3,0},
			{1,2,-8,-6,29,62,49,8,-10,-2,3,0},
			{1,2,-7,-7,26,61,52,10,-10,-3,3,0},
			{1,2,-6,-8,23,60,54,13,-10,-4,3,0},
			{1,2,-6,-9,20,59,56,15,-10,-4,3,1},
			{1,2,-5,-9,18,57,57,18,-9,-5,2,1},
			{1,3,-4,-10,15,56,59,20,-9,-6,2,1},
			{0,3,-4,-10,13,54,60,23,-8,-6,2,1},
			{0,3,-3,-10,10,52,61,26,-7,-7,2,1},
			{0,3,-2,-10,8,49,62,29,-6,-8,2,1},
			{0,3,-2,-10,6,47,63,31,-5,-8,1,2},
			{0,2,-1,-10,4,44,64,34,-3,-9,1,2},
			{0,2,-1,-10,2,42,64,37,-2,-9,1,2}
		},
#endif
		{ // D = 2.5
#if TAP_10_FLT
			{0,-4,-7,11,38,52,38,11,-7,-4,0,0},
			{0,-4,-7,9,37,51,40,13,-6,-7,2,0},
			{0,-3,-7,8,35,51,41,14,-5,-7,1,0},
			{0,-2,-8,6,33,51,42,16,-5,-7,2,0},
			{0,-2,-8,5,32,50,43,18,-4,-8,2,0},
			{0,-2,-8,4,30,50,45,19,-3,-8,1,0},
			{0,-1,-8,2,28,49,46,21,-2,-8,1,0},
			{0,-1,-8,1,26,49,47,23,-1,-8,0,0},
			{0,0,-8,0,24,48,48,24,0,-8,0,0},
			{0,0,-8,-1,23,47,49,26,1,-8,-1,0},
			{0,1,-8,-2,21,46,49,28,2,-8,-1,0},
			{0,1,-8,-3,19,45,50,30,4,-8,-2,0},
			{0,2,-8,-4,18,43,50,32,5,-8,-2,0},
			{0,2,-7,-5,16,42,51,33,6,-8,-2,0},
			{0,1,-7,-5,14,41,51,35,8,-7,-3,0},
			{0,2,-7,-6,13,40,51,37,9,-7,-4,0}
#else
			{3,-7,-7,11,38,52,38,11,-7,-7,0,3},
			{3,-6,-7,9,36,51,39,13,-6,-7,0,3},
			{3,-6,-7,8,35,51,41,14,-5,-7,-1,2},
			{3,-5,-8,6,33,51,42,16,-5,-7,-1,3},
			{3,-5,-8,5,32,50,43,18,-4,-8,-1,3},
			{3,-4,-8,3,30,50,45,19,-3,-8,-2,3},
			{3,-4,-8,2,28,49,46,21,-2,-8,-2,3},
			{3,-4,-8,1,26,49,47,23,-1,-8,-3,3},
			{3,-3,-8,0,24,48,48,24,0,-8,-3,3},
			{3,-3,-8,-1,23,47,49,26,1,-8,-4,3},
			{3,-2,-8,-2,21,46,49,28,2,-8,-4,3},
			{3,-2,-8,-3,19,45,50,30,3,-8,-4,3},
			{3,-1,-8,-4,18,43,50,32,5,-8,-5,3},
			{3,-1,-7,-5,16,42,51,33,6,-8,-5,3},
			{2,-1,-7,-5,14,41,51,35,8,-7,-6,3},
			{3,0,-7,-6,13,39,51,36,9,-7,-6,3}
#endif
#if 0  // N=4 version tested in Nice
			{5,-8,-7,11,38,51,38,11,-7,-8,0,4},// 0
			{4,-7,-8,10,37,51,40,13,-7,-8,-1,4},
			{4,-7,-8,8,35,51,41,15,-6,-8,-1,4},
			{4,-7,-8,7,34,51,42,16,-5,-9,-1,4},
			{5,-6,-9,5,32,50,44,18,-4,-9,-2,4},// 1/4
			{5,-6,-9,4,31,50,45,20,-4,-10,-3,5},
			{5,-5,-10,3,29,49,46,22,-3,-10,-3,5},
			{5,-5,-9,1,27,48,47,23,-1,-9,-4,5},
			{5,-4,-10,0,25,48,48,25,0,-10,-4,5},// 1/2
			{5,-4,-9,-1,23,47,48,27,1,-9,-5,5},
			{5,-3,-10,-3,22,46,49,29,3,-10,-5,5},
			{5,-3,-10,-4,20,45,50,31,4,-9,-6,5},
			{4,-2,-9,-4,18,44,50,32,5,-9,-6,5},
			{4,-1,-9,-5,16,42,51,34,7,-8,-7,4},
			{4,-1,-8,-6,15,41,51,35,8,-8,-7,4},
			{4,-1,-8,-7,13,40,51,37,10,-8,-7,4}
#endif
		},
		{ // D = 3
			{-2,-7,0,17,35,43,35,17,0,-7,-5,2},
			{-2,-7,-1,16,34,43,36,18,1,-7,-5,2},
			{-1,-7,-1,14,33,43,36,19,1,-6,-5,2},
			{-1,-7,-2,13,32,42,37,20,3,-6,-5,2},
			{0,-7,-3,12,31,42,38,21,3,-6,-5,2},
			{0,-7,-3,11,30,42,39,23,4,-6,-6,1},
			{0,-7,-4,10,29,42,40,24,5,-6,-6,1},
			{1,-7,-4,9,27,41,40,25,6,-5,-6,1},
			{1,-6,-5,7,26,41,41,26,7,-5,-6,1},
			{1,-6,-5,6,25,40,41,27,9,-4,-7,1},
			{1,-6,-6,5,24,40,42,29,10,-4,-7,0},
			{1,-6,-6,4,23,39,42,30,11,-3,-7,0},
			{2,-5,-6,3,21,38,42,31,12,-3,-7,0},
			{2,-5,-6,3,20,37,42,32,13,-2,-7,-1},
			{2,-5,-6,1,19,36,43,33,14,-1,-7,-1},
			{2,-5,-7,1,18,36,43,34,16,-1,-7,-2}
		},
		{ // D = 3.5
			{-6,-3,5,19,31,36,31,19,5,-3,-6,0},
			{-6,-4,4,18,31,37,32,20,6,-3,-6,-1},
			{-6,-4,4,17,30,36,33,21,7,-3,-6,-1},
			{-5,-5,3,16,30,36,33,22,8,-2,-6,-2},
			{-5,-5,2,15,29,36,34,23,9,-2,-6,-2},
			{-5,-5,2,15,28,36,34,24,10,-2,-6,-3},
			{-4,-5,1,14,27,36,35,24,10,-1,-6,-3},
			{-4,-5,0,13,26,35,35,25,11,0,-5,-3},
			{-4,-6,0,12,26,36,36,26,12,0,-6,-4},
			{-3,-5,0,11,25,35,35,26,13,0,-5,-4},
			{-3,-6,-1,10,24,35,36,27,14,1,-5,-4},
			{-3,-6,-2,10,24,34,36,28,15,2,-5,-5},
			{-2,-6,-2,9,23,34,36,29,15,2,-5,-5},
			{-2,-6,-2,8,22,33,36,30,16,3,-5,-5},
			{-1,-6,-3,7,21,33,36,30,17,4,-4,-6},
			{-1,-6,-3,6,20,32,37,31,18,4,-4,-6}
		},
		{ // D = 4
			{-9,0,9,20,28,32,28,20,9,0,-9,0},
			{-9,0,8,19,28,32,29,20,10,0,-4,-5},
			{-9,-1,8,18,28,32,29,21,10,1,-4,-5},
			{-9,-1,7,18,27,32,30,22,11,1,-4,-6},
			{-8,-2,6,17,27,32,30,22,12,2,-4,-6},
			{-8,-2,6,16,26,32,31,23,12,2,-4,-6},
			{-8,-2,5,16,26,31,31,23,13,3,-3,-7},
			{-8,-3,5,15,25,31,31,24,14,4,-3,-7},
			{-7,-3,4,14,25,31,31,25,14,4,-3,-7},
			{-7,-3,4,14,24,31,31,25,15,5,-3,-8},
			{-7,-3,3,13,23,31,31,26,16,5,-2,-8},
			{-6,-4,2,12,23,31,32,26,16,6,-2,-8},
			{-6,-4,2,12,22,30,32,27,17,6,-2,-8},
			{-6,-4,1,11,22,30,32,27,18,7,-1,-9},
			{-5,-4,1,10,21,29,32,28,18,8,-1,-9},
			{-5,-4,0,10,20,29,32,28,19,8,0,-9}
		},
		{ // D = 6
			{-6,8,13,18,20,22,20,18,13,8,4,-10},
			{-6,8,13,17,20,21,20,18,13,9,4,-9},
			{-6,8,12,17,20,21,20,18,14,9,4,-9},
			{-7,7,12,17,20,21,21,18,14,9,5,-9},
			{-7,7,12,16,20,21,21,18,14,10,5,-9},
			{-7,7,12,16,20,21,21,18,14,10,5,-9},
			{-8,7,11,16,20,21,21,19,15,10,5,-9},
			{-8,6,11,16,19,21,21,19,15,11,6,-9},
			{-8,6,11,15,19,21,21,19,15,11,6,-8},
			{-9,6,11,15,19,21,21,19,16,11,6,-8},
			{-9,5,10,15,19,21,21,20,16,11,7,-8},
			{-9,5,10,14,18,21,21,20,16,12,7,-7},
			{-9,5,10,14,18,21,21,20,16,12,7,-7},
			{-9,5,9,14,18,21,21,20,17,12,7,-7},
			{-9,4,9,14,18,20,21,20,17,12,8,-6},
			{-9,4,9,13,18,20,21,20,17,13,8,-6}
		}
	};
	int i, j, k, m, *px, *py, x, y, x16, y16, filter;


	int input_width=pResizeParameters->input_width;
	int input_height=pResizeParameters->input_height;
	int output_width=pResizeParameters->output_width;
	int output_height=pResizeParameters->output_heigh;
	int crop_x0=pResizeParameters->crop_x0;
	int crop_y0=pResizeParameters->crop_y0;
	int crop_w=pResizeParameters->crop_w;
	int crop_h =pResizeParameters->crop_h;


	int stride;

	int * resize_int_buffer=pResizeParameters->resize_buffer;
	int * resize_int_buffer_tmp=pResizeParameters->resize_buffer_tmp;



	if(component)
	{
		input_width=input_width>>1;
		input_height=input_height>>1;
		output_width=output_width>>1;
		output_height=output_height>>1;
		crop_x0=crop_x0>>1;
		crop_y0=crop_y0>>1;
		crop_h=crop_h>>1;
		crop_w=crop_w>>1;
	}

	if((component<0)||(component>2))
	{
		printf("invalid imgpel component\n");
		exit(1);
	}

	stride=pResizeParameters->img_stride   ;

	px=component?pResizeParameters->pos_x[1]:pResizeParameters->pos_x[0];
	py=component?pResizeParameters->pos_y[1]:pResizeParameters->pos_y[0];


	//========== horizontal downsampling ===========
	// if(crop_w*2 > 7*output_width) filter = 7;
	//else 
	if(crop_w*7 > 20*output_width)
		filter = 6;
	else if(crop_w*2 > 5*output_width) 
		filter = 5;
	else if(crop_w*1 > 2*output_width) 
		filter = 4;
	else if(crop_w*3 > 5*output_width)
		filter = 3;
	else if(crop_w*4 > 5*output_width) 
		filter = 2;
	else if(crop_w*19 > 20*output_width)
		filter = 1;
	else filter = 0;

	for( j = 0; j < input_height; j++ ) 
	{
		int*  piSrc = &resize_int_buffer[j*stride];
		for( i = 0; i < output_width; i++ )
		{
			x16 = px[i]&0x0f;
			x = px[i]>>4;
			resize_int_buffer_tmp[i] = 0;
			for( k=0; k<12; k++) 
			{
				m = x - 5 + k;
				if( m<0 ) 
					m = 0;
				else 
					if( m>(input_width-1) ) 
					m=input_width-1;
				resize_int_buffer_tmp[i] += filter16[filter][x16][k]*piSrc[m];
			}
		}
		//----- copy row back to image buffer -----
		memcpy( piSrc, resize_int_buffer_tmp, output_width*sizeof(int) );
	}

	//========== vertical downsampling ===========
	//if     (crop_h*2 > 7*output_height) filter = 7;
	//else 
	if(crop_h*7 > 20*output_height) 
		filter = 6;
	else if(crop_h*2 > 5*output_height)
		filter = 5;
	else if(crop_h*1 > 2*output_height)
		filter = 4;
	else if(crop_h*3 > 5*output_height) 
		filter = 3;
	else if(crop_h*4 > 5*output_height) 
		filter = 2;
	else if(crop_h*19 > 20*output_height)
		filter = 1;
	else filter = 0;

	for( i = 0; i < output_width; i++ ) 
	{
		int*  piSrc = &resize_int_buffer[i];
		for( j = 0; j < output_height; j++ )
		{
			y16 = py[j]&0x0f;
			y = py[j]>>4;
			resize_int_buffer_tmp[j] = 0;
			for( k=0; k<12; k++) 
			{
				m = y - 5 + k;
				if( m<0 ) 
					m = 0;
				else if( m>(input_height-1) )
					m=input_height-1;
				resize_int_buffer_tmp[j] += filter16[filter][y16][k]*piSrc[m*stride];
			}
		}
		//----- scale and copy back to image buffer -----
		for( j = 0; j < output_height; j++ )
		{
			piSrc[j*stride] = ( resize_int_buffer_tmp[j] + (1<<13) ) / (1<<14);
		}
	}

}
#endif


static void Upsampling(ResizeParameters* pResizeParameters, int component,int method )
{
	int filter16[16][6] = 
	{ // Lanczos3
		{0,0,32,0,0,0},
		{0,-2,32,2,0,0},
		{1,-3,31,4,-1,0},
		{1,-4,30,6,-1,0},
		{1,-4,28,9,-2,0},
		{1,-4,27,11,-3,0},
		{1,-5,25,14,-3,0},
		{1,-5,22,17,-4,1},
		{1,-5,20,20,-5,1},
		{1,-4,17,22,-5,1},
		{0,-3,14,25,-5,1},
		{0,-3,11,27,-4,1},
		{0,-2,9,28,-4,1},
		{0,-1,6,30,-4,1},
		{0,-1,4,31,-3,1},
		{0,0,2,32,-2,0}
	};
	int filter16_chroma[16][6] = 
	{ // bilinear
		{0,0,32,0,0,0},
		{0,0,30,2,0,0},
		{0,0,28,4,0,0},
		{0,0,26,6,0,0},
		{0,0,24,8,0,0},
		{0,0,22,10,0,0},
		{0,0,20,12,0,0},
		{0,0,18,14,0,0},
		{0,0,16,16,0,0},
		{0,0,14,18,0,0},
		{0,0,12,20,0,0},
		{0,0,10,22,0,0},
		{0,0,8,24,0,0},
		{0,0,6,26,0,0},
		{0,0,4,28,0,0},
		{0,0,2,30,0,0}
	};


	int input_width=pResizeParameters->input_width;
	int input_height=pResizeParameters->input_height;
	int output_width=pResizeParameters->output_width;
	int output_height=pResizeParameters->output_heigh;
	int crop_x0=pResizeParameters->crop_x0;
	int crop_y0=pResizeParameters->crop_y0;
	int crop_w=pResizeParameters->crop_w;
	int crop_h =pResizeParameters->crop_h;

	int stride=pResizeParameters->img_stride ;

	int * resize_int_buffer=pResizeParameters->resize_buffer;
	int * resize_int_buffer_tmp=pResizeParameters->resize_buffer_tmp;

	//JVT-S067
	int i, j, k, *px, *py;
	int x16, y16, x, y, m;

	px=component?pResizeParameters->pos_x[1]:pResizeParameters->pos_x[0];
	py=component?pResizeParameters->pos_y[1]:pResizeParameters->pos_y[0];

	if(component)
	{
		input_width=input_width>>1;
		input_height=input_height>>1;
		output_width=output_width>>1;
		output_height=output_height>>1;
		crop_x0=crop_x0>>1;
		crop_y0=crop_y0>>1;
		crop_h=crop_h>>1;
		crop_w=crop_w>>1;
	}
	if(method)
	{
		for (i=0; i<16; i++)
			for (j=0; j<6; j++)
				filter16[i][j] = filter16_chroma[i][j];
	}

	//========== horizontal upsampling ===========
	for( j = 0; j < input_height; j++ ) 
	{
		int*  piSrc = &resize_int_buffer[j*stride];
		for( i = 0; i < output_width; i++ )
		{
			if( px[i]==-128 ) 
				continue;
			x16 = px[i]&0x0f;
			x = px[i]>>4;
			resize_int_buffer_tmp[i] = 0;
			for( k=0; k<6; k++) 
			{
				m = x - 2 + k;
				if( m<0 )
					m = 0;
				else 
					if( m>input_width-1) 
					m=input_width-1;

				resize_int_buffer_tmp[i] += filter16[x16][k]*piSrc[m];
			}
			resize_int_buffer_tmp[i] = resize_int_buffer_tmp[i];
		}
		//----- copy row back to image buffer -----
		memcpy( piSrc, resize_int_buffer_tmp, output_width*sizeof(int) );
	}
	//========== vertical upsampling ===========
	for( i = 0; i < output_width; i++ ) 
	{
		int*  piSrc = &resize_int_buffer[i];
		for( j = 0; j < output_height; j++ )
		{
			if( py[j]==-128 || px[i]==-128)
			{
				resize_int_buffer_tmp[j] = 128;
				continue;
			}
			y16 = py[j]&0x0f;
			y = py[j]>>4;
			resize_int_buffer_tmp[j] = 0;
			for( k=0; k<6; k++) 
			{
				m = y - 2 + k;
				if( m<0 ) 
					m = 0;
				else 
					if( m>input_height-1) 
					m=input_height-1;

				resize_int_buffer_tmp[j] += filter16[y16][k]*piSrc[m*stride];
			}
			resize_int_buffer_tmp[j] = (resize_int_buffer_tmp[j]+512)/1024;
		}
		//----- scale and copy back to image buffer -----
		for( j = 0; j < output_height; j++ )
		{
			piSrc[j*stride] = resize_int_buffer_tmp[j];
		}
	}
}

#if 0 // Outdated functionality
static void img_downSample ( ResizeParameters*  Parameters,int component)	
{

	if(-1==component)
	{
		//Y
		ConvertImgpelToIntBuffer(Parameters,0);
		Downsampling(Parameters,0);
		ConvertIntBufferToImgpel(Parameters,0);

		//U
		ConvertImgpelToIntBuffer(Parameters,1);
		Downsampling(Parameters,1);
		ConvertIntBufferToImgpel(Parameters,1);

		//V
		ConvertImgpelToIntBuffer(Parameters,2);
		Downsampling(Parameters,2);
		ConvertIntBufferToImgpel(Parameters,2);
	}
	else
	{
		ConvertImgpelToIntBuffer(Parameters,component);
		Downsampling(Parameters,component);
		ConvertIntBufferToImgpel(Parameters,component);
	}
}
#endif

static void img_upSample(ResizeParameters* Parameters, int component, int method)
{
	if(-1==component)
	{
		//Y
		ConvertImgpelToIntBuffer(Parameters,0);
		Upsampling(Parameters,0,method);
		ConvertIntBufferToImgpel(Parameters,0);

		//U
		ConvertImgpelToIntBuffer(Parameters,1);
		Upsampling(Parameters,1,method);
		ConvertIntBufferToImgpel(Parameters,1);

		//V
		ConvertImgpelToIntBuffer(Parameters,2);
		Upsampling(Parameters,2,method);
		ConvertIntBufferToImgpel(Parameters,2);
	}
	else
	{
		ConvertImgpelToIntBuffer(Parameters,component);
		Upsampling(Parameters,component,method);
		ConvertIntBufferToImgpel(Parameters,component);
	}
}

static void img_bilinear_fast(imgpel** low_img,imgpel** high_img,int low_height, int low_width, int high_height, int high_width)
{
  int i,j,i2,j2;
  imgpel curr,right,down,down_right;

  for(j=0;j<low_height-1;++j)
  {
    for(i=0;i<low_width-1;++i)
    {
      curr=low_img[j][i];
      right=low_img[j][i+1];
      down=low_img[j+1][i];
      down_right=low_img[j+1][i+1];

      j2=j<<1;
      i2=i<<1;

      high_img[j2][i2]=curr;
      high_img[j2][i2+1]=(curr+right+1)>>1;
      high_img[j2+1][i2]=(curr+down+1)>>1;
      high_img[j2+1][i2+1]=(curr+right+down+down_right+2)>>2;
    }

    j2=j<<1;
    i2=i<<1;
    curr=low_img[j][i];
    down=low_img[j+1][i];

    high_img[j2][i2+1]=high_img[j2][i2]=curr;
    high_img[j2+1][i2+1]=high_img[j2+1][i2]=(curr+down+1)>>1;
  }
  j2=j<<1;
  for(i=0;i<low_width-1;++i)
  {
    i2=i<<1;
    curr=low_img[j][i];
    right=low_img[j][i+1];
    high_img[j2][i2]=curr;
    high_img[j2][i2+1]=(curr+right+1)>>1;
  }
  i2=i<<1;
  high_img[j2][i2+1]=high_img[j2][i2]=low_img[j][i];

  memcpy(high_img[high_height-1],high_img[high_height-2],high_width*sizeof(imgpel));
}


int init_ImageResize(ResizeParameters* ResizeParams, int width_in,
					   int height_in, int width_out, int height_out)
{
	int input_luma_size,input_chroma_size;
	int memory_size=0;
	int downsampling=1;
	assert(ResizeParams);



	if(width_in>=width_out)
	{
		if(height_in>=height_out)
			downsampling=1;
		else
			assert(0);
	}
	else
	{
		if(height_in<=height_out)
			downsampling=0;
		else
			assert(0);
	}


	
	if(downsampling)
	{
		input_luma_size=width_in*height_in;
		input_chroma_size=(width_in>>1)*(height_in>>1);
		ResizeParams->down_sample=1;
	}
	else
	{

		input_luma_size=width_out*height_out;
		input_chroma_size=(width_out>>1)*(height_out>>1);
		ResizeParams->down_sample=0;
	}

	ResizeParams->input_width=width_in;
	ResizeParams->input_height=height_in;
	ResizeParams->output_width=width_out;
	ResizeParams->output_heigh=height_out;
	ResizeParams->input_chroma_phase_shift_x=-1;
	ResizeParams->input_chroma_phase_shift_y=0;
	ResizeParams->input_chroma_phase_shift_x=-1;
	ResizeParams->input_chroma_phase_shift_y=0;
	ResizeParams->output_chroma_phase_shift_x=-1;
	ResizeParams->output_chroma_phase_shift_y=0;

	ResizeParams->crop_x0=0;
	ResizeParams->crop_y0=0;
	ResizeParams->crop_w=imax(width_in,width_out);
	ResizeParams->crop_h=imax(height_in,height_out);

	ResizeParams->input_stride[0]=width_in;
	ResizeParams->input_stride[1]=ResizeParams->input_stride[2]=width_in>>1;
	ResizeParams->output_stride[0]=width_out;
	ResizeParams->output_stride[1]=ResizeParams->output_stride[2]=width_out>>1;

	ResizeParams->img_stride=  imax(width_in,width_out);
	ResizeParams->minValue=0;
	ResizeParams->maxValue=255;

	if((ResizeParams->resize_buffer=(int*)malloc(input_luma_size*sizeof(int)))==NULL)
		no_mem_exit("initSampleResize: pDownsampingParas->resize_buffer")	  ;
	memory_size+=input_luma_size*sizeof(int);
	if((ResizeParams->resize_buffer_tmp=(int*)malloc(imax(width_in,width_out)*sizeof(int)))==NULL)
		no_mem_exit("initSampleResize: pDownsampingParas->resize_buffer_tmp")  ;
	memory_size+=width_in*sizeof(int);
	if((ResizeParams->img_buffer[0]=(imgpel*)malloc(input_luma_size*sizeof(imgpel)))==NULL)
		no_mem_exit("initSampleResize: pDownsampingParas->img_buffer[0]")   ;
	memory_size+=input_luma_size*sizeof(imgpel);
	if((ResizeParams->img_buffer[1]=(imgpel*)malloc(input_chroma_size*sizeof(imgpel)))==NULL)
		no_mem_exit("init_downsampling: pDownsampingParas->img_buffer[1]")   ;
	memory_size+=input_chroma_size*sizeof(imgpel);
	if((ResizeParams->img_buffer[2]=(imgpel*)malloc(input_chroma_size*sizeof(imgpel)))==NULL)
		no_mem_exit("init_downsampling: pDownsampingParas->img_buffer[2]")   ;
	memory_size+=input_chroma_size*sizeof(imgpel);

	memory_size+=calcute_ref_pixel_pos(ResizeParams);
	return memory_size;
}

void destroy_ImageResize(ResizeParameters* pResizeParams)
{

	if(pResizeParams)
	{
		if(pResizeParams->resize_buffer)
		{
			free(pResizeParams->resize_buffer);
			pResizeParams->resize_buffer=NULL;
		}
		if(pResizeParams->resize_buffer_tmp)
		{
			free(pResizeParams->resize_buffer_tmp);
			pResizeParams->resize_buffer_tmp=NULL;
		}
		if(pResizeParams->img_buffer[0])
		{
			free(pResizeParams->img_buffer[0]);
			pResizeParams->img_buffer[0]=NULL;
		}
		if(pResizeParams->img_buffer[1])
		{
			free(pResizeParams->img_buffer[1]);
			pResizeParams->img_buffer[1]=NULL;
		}
		if(pResizeParams->img_buffer[2])
		{
			free(pResizeParams->img_buffer[2]);
			pResizeParams->img_buffer[2]=NULL;
		}
		if(pResizeParams->pos_x[0])
		{
			free(pResizeParams->pos_x[0]);
			pResizeParams->pos_x[0]=NULL;
		}
		if(pResizeParams->pos_x[1])
		{
			free(pResizeParams->pos_x[1]);
			pResizeParams->pos_x[1]=NULL;
		}
		if(pResizeParams->pos_y[0])
		{
			free(pResizeParams->pos_y[0]);
			pResizeParams->pos_y[0]=NULL;
		}
		if(pResizeParams->pos_y[1])
		{
			free(pResizeParams->pos_y[1]);
			pResizeParams->pos_y[1]=NULL;
		}
		free(pResizeParams);
		pResizeParams=NULL;
	}
}


void generic_upsampler(ResizeParameters* ResizeParams,
					  imgpel**low_imgY,imgpel**low_imgU,imgpel**low_imgV,
					  imgpel**high_imgY,imgpel**high_imgU,imgpel**high_imgV,
					  int component,int method)
{
	int width_in=ResizeParams->input_width;
	int height_in=ResizeParams->input_height;
	int width_out=ResizeParams->output_width;
	int height_out=ResizeParams->output_heigh;

	int j=0;

	//!<Just support 4:2:0 and 4:0:0
  if((method==BI_LINEAR)&&(ResizeParams->input_height*2==ResizeParams->output_heigh)&&(ResizeParams->input_width*2==ResizeParams->output_width))
  {
    if(low_imgY)
      img_bilinear_fast(low_imgY,high_imgY,ResizeParams->input_height,ResizeParams->input_width,ResizeParams->output_heigh,ResizeParams->output_width);
    if(low_imgU)
      img_bilinear_fast(low_imgU,high_imgU,(ResizeParams->input_height)>>1,(ResizeParams->input_width)>>1,(ResizeParams->output_heigh)>>1,(ResizeParams->output_width)>>1);
    if(low_imgV)
      img_bilinear_fast(low_imgV,high_imgV,(ResizeParams->input_height)>>1,(ResizeParams->input_width)>>1,(ResizeParams->output_heigh)>>1,(ResizeParams->output_width)>>1);

    return ;
  }
	if(low_imgY)
	{
		for(j=0;j<height_in;++j)
		{
			memcpy(ResizeParams->img_buffer[0]+j*width_out,low_imgY[j],width_in*sizeof(imgpel));
		}
	}
	if(low_imgU)
	{
		for(j=0;j<(height_in>>1);++j)
			memcpy(ResizeParams->img_buffer[1]+j*(width_out>>1),low_imgU[j],(width_in>>1)*sizeof(imgpel));
	}
	if(low_imgV)
	{
		for(j=0;j<(height_in>>1);++j)
			memcpy(ResizeParams->img_buffer[2]+j*(width_out>>1),low_imgV[j],(width_in>>1)*sizeof(imgpel));
	}

	img_upSample(ResizeParams,component, method);

	if(high_imgY)
	{
		for(j=0;j<height_out;++j)
		{
			memcpy(high_imgY[j],ResizeParams->img_buffer[0]+j*width_out,width_out*sizeof(imgpel));
		}
	}
	if(high_imgU)
	{
		for(j=0;j<(height_out>>1);++j)
		{
			memcpy(high_imgU[j],ResizeParams->img_buffer[1]+j*(width_out>>1),(width_out>>1)*sizeof(imgpel));
		}
	}
	if(high_imgV)
	{
		for(j=0;j<(height_out>>1);++j)
		{
			memcpy(high_imgV[j],ResizeParams->img_buffer[2]+j*(width_out>>1),(width_out>>1)*sizeof(imgpel));
		}
	}

}





