/***************************************************************************************/
/*								  	  	       */
/*      Program Name : bmp_arbitrary_rotate.c		 	 	  	       */
/*								  	  	       */
/*	Date         : 06.07.31	New Create			  	  	       */
/*								  	  	       */
/*	Author       : Takashi Nakajima			  	  	       */
/*								  	  	       */
/*	Function     : picture rotation                     			       */
/*		       						  	  	       */
/*      ver01  06.07.31   New Create Bi Lnear				   	  	       */
/*		ver02  14.09.09   Lanczos3    						  	  	       */
/*								  	               */
/***************************************************************************************/
				
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <string.h>
#define uchar           unsigned char
#define ushort          unsigned short
#define uint            unsigned int
#define ulong           unsigned long
#define rchar           register char
#define rshort          register short
#define rint            register int
#define rlong           register long
#define ruchar          register uchar
#define rushort         register ushort
#define ruint           register uint
#define rulong          register ulong
#define schar           static char
#define sshhort         static short
#define sint            static int
#define slong           static long
#define suchar          static uchar
#define sushort         static ushort
#define suint           static uint
#define sulong          static ulong
#define ORG_IMAGE_X     720
#define ORG_IMAGE_Y     480

#define BUNBOMAX 32
#define BUNSHIMAX 31
#define TAPMAXY 50
#define TAPMAXC 50
                                                                                                                                                         
typedef struct control_data {
  uint          sizex;
  uint          sizey;
  uint          startx;
  uint          starty;
  char         InputFileName[128];
  char         InputFileName2[128];
  char         OutputFileName[128];
  uint          hv;
  uint		sm;
  uint          smy;	
  uint          bunshi;
  uint          bunbo;
  uint          norm;
  uint          mado;
  uint          tapnum_y;
  uint          tapnum_c;
  double        Fs;	
  double        angle;	
} CNTL;
        char inputfile[50];
        char inputfile2[50];
        char outputfile[50];
        int hsize;
        int vsize;
        int org_image_x;
        int org_image_y;
	void coeffhairetsuculc(uint , uint, uint , uint, uint, uint, uint, uint, double, double, double, double, double *,double *, uint,double);
        double INITPHASECULC(uint , uint , uint , uint , uint );
        uint FILPATCULC(uint , uint , uint , double , double *);
        void COEFCULC( uint , uint , uint , uint , uint , uint , uint, double );
  	void normarize(uint ,uint ,uint ,uint , double *, uint  );
	void DFT1DV(int , double *, double *, double *, double *);
	void DFT1DH(int , int  , double *, double*, double *, double *);
	void IDFT1DV(int , double *, double *, double *, double *);
	void IDFT1DH(int , int  , double *, double*, double *, double *);
void resize( int hsize, int vsize, int sizeminus, int smy,  unsigned char *vin_buffer , unsigned char *vout);
void    print_help( void )
{
  fprintf( stderr, "Usage: ARBITRARY ROTATION BMP LANCZOS3 [options]\n" );
  fprintf( stderr, "\toptions: \n" );
  fprintf( stderr, "\t  -help          : help\n" );
  fprintf( stderr, "\t  -i             : input bitmap filename(BMP24bittruecolor)\n" );
  fprintf( stderr, "\t  -o             : output bitmap filename(BMP24bittruecolor auto add .bmp extension\n" );
  fprintf( stderr, "\t  -angle         : angle 0<SIETA<360 \n" );
//  fprintf( stderr, "\t  -x             : 出力補正スペクトルを何倍にするか指定\n" );
//  fprintf( stderr, "\t  -orgx          : 水平画素サイズ(任意の自然数)\n" );
//  fprintf( stderr, "\t  -orgy          : 垂直画素サイズ(任意の自然数)\n" );
//  fprintf( stderr, "\t  -sizexminus    : 原画像水平方向サイズと水平方向縮小後サイズとの差分(任意の自然数)\n" );
//  fprintf( stderr, "\t  -sizexminusy   : 原画像垂直方向サイズと垂直方向縮小後サイズとの差分(任意の自然数)\n" );
//  fprintf( stderr, "\t  -hv       : 1:水平 2:プログレッシブ垂直 3:インタレース垂直\n" );
//  fprintf( stderr, "\t  -bunshi   : 縮小率分子 max31\n" );
//  fprintf( stderr, "\t  -bunbo    : 縮小率分母 max32\n" );
//  fprintf( stderr, "\t  -tapnum_y : 輝度フィルタタップ数  推奨 21 max50\n" );
//  fprintf( stderr, "\t  -tapnum_c : 色差フィルタタップ数  推奨 11 max50\n" );
//  fprintf( stderr, "\t  -norm     : 総係数合計 推奨4096 サブサンプルプログラムで使う場合\n" );
//  fprintf( stderr, "\t  -mado     : 1:矩形 2:Lanczos 3:hanning(両端が0) 4:hamming\n" );
//  fprintf( stderr, "\t  -Fsc      : サブサンプル後のサンプリング周波数を１としたときカットオフ周波数を指定(推奨0.5)\n" );

}
void    option_set(short argc,char *argv[], CNTL *ptr)
{
  short i;
                                                                                                                                                         
  for(i=1;i < argc;i++) {
    if(argv[i][0] != '-')
      continue;

    if ( !strcmp( &argv[i][1], "h" ) ){
      /* \245\330\245\353\245\327\311\275\274\250 */
      print_help();
      exit(0);
    } else if ( !strcmp( &argv[i][1], "o" ) ){
      /* \275\320\316\317\245\325\245\241\245\244\245\353\314\276 */
      strcpy(ptr->OutputFileName, argv[++i]);
    } else if ( !strcmp( &argv[i][1], "i" ) ){
      strcpy(ptr->InputFileName, argv[++i]);
    } else if ( !strcmp( &argv[i][1], "i2" ) ){
      strcpy(ptr->InputFileName2, argv[++i]);
                                                                                                                                                         
    } else if ( !strcmp( &argv[i][1], "x" ) ){
      ptr->sizex = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "y" ) ){
      ptr->sizey = atoi(argv[++i]);
                                                                                                                                                         
    } else if ( !strcmp( &argv[i][1], "startx" ) ){
      ptr->startx = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "starty" ) ){
      ptr->starty = atoi(argv[++i]);
                                                                                                                                                         
    } else if ( !strcmp( &argv[i][1], "hv" ) ){
      ptr->hv = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "bunshi" ) ){
      ptr->bunshi = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "bunbo" ) ){
      ptr->bunbo = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "norm" ) ){
      ptr->norm = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "mado" ) ){
      ptr->mado = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "tapnum_y" ) ){
      ptr->tapnum_y = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "tapnum_c" ) ){
      ptr->tapnum_c = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "Fsc" ) ){
      ptr->Fs = atof(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "angle" ) ){
      ptr->angle = atof(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "sizexminus" ) ){
      ptr->sm = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "sizexminusy" ) ){
      ptr->smy = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "orgx" ) ){
      /* \277\345\312\277\312\375\270\376\306\376\316\317\262\350\301\374\245\265\245\244\245\272 */
      org_image_x = atoi(argv[++i]);
    } else if ( !strcmp( &argv[i][1], "orgy" ) ){
      /* \277\342\304\276\312\375\270\376\306\376\316\317\262\350\301\374\245\265\245\244\245\272 */
      org_image_y = atoi(argv[++i]);
    } else {
      print_help();
      exit(0);
    }
  }
                                                                                                                                                         
}

int main(int argc, char *argv[]){
FILE *fpr1;
FILE *fpr2;
FILE *fpw;
unsigned char *vin;
unsigned char *vout;
unsigned char *vin_buffer;
//#define HSIZE 360
//#define VSIZE 288
//#define tmp HSIZE*VSIZE 
int i,j,k,l,m,n,o ;
CNTL  *cnt;
int center0;
int sizeminus;
int filesizebyte;
unsigned char *B;
unsigned char *G;
unsigned char *R;
unsigned char *BIN;
unsigned char *GIN;
unsigned char *RIN;
unsigned char *RUPOUT;
unsigned char *GUPOUT;
unsigned char *BUPOUT;
unsigned char temp;
unsigned char temp2;
unsigned int  filesize;
double	      DiagonalLength;
int	      NewHsize;
int	      NewVsize;
double        PI;
double 	      *rotx;
double	      *roty;
double	      *screen_rotx;
double	      *screen_roty;
int	      *introtx;
int	      *introty;
double				aaa;
double				bbb;
int				ww;
double				xx;
int				yy;
int				zz;
double				low_x;
double				up_x;
int				wwg;
int				xxg;
int				yyg;
int				zzg;
double				low_xg;
double				up_xg;
int				wwr;
int				xxr;
int				yyr;
int				zzr;
double				low_xr;
double				up_xr;
double				ccc;
double				ddd;


  org_image_x = ORG_IMAGE_X;
  org_image_y = ORG_IMAGE_Y;

        if( argc < 2 ) {
                print_help();
                exit(0);
        }
//-----debug-----
//for(;;);
//----------------
        cnt = (CNTL *)malloc( sizeof(CNTL)*sizeof(uchar) );
                                                                                                                                                         
        /* \245\307\245\325\245\251\245\353\245\310\303\315\300\337\304\352 */
        cnt->sizex = ORG_IMAGE_X;    
        cnt->sizey = ORG_IMAGE_Y;     
        cnt->startx = 0;
        cnt->starty = 0;
                                                                                                                                                         
        /* \245\252\245\327\245\267\245\347\245\363\245\301\245\247\245\303\245\257 */
        option_set(argc, argv, cnt);
                                                                                                                                                         
                                                                                                                                                         
        hsize = org_image_x;
        vsize = org_image_y;
        strcpy(inputfile,cnt->InputFileName);
        strcpy(inputfile2,cnt->InputFileName2);
        strcpy(outputfile,cnt->OutputFileName);
	sizeminus = cnt->sm;
                                                                                                                                                         
/********************************/ 
/*				*/
/*	  MAIN ROUTINE		*/
/*				*/
/********************************/

//	vin_buffer = (unsigned char *)malloc(sizeof(unsigned char)*hsize*vsize);
//	vout = (unsigned char *)malloc(sizeof(unsigned char)*(hsize+sizeminus)*(vsize+smy)*2);

        if((fpr1 = fopen(inputfile,"rb"))==NULL){
                exit(0);
        }
//debug start
//for(;;);
//debug end
/***************************************************/
/* picture size & file size get from bitmap header */
/***************************************************/
	fseek(fpr1,18,SEEK_SET);
	fread(&hsize,sizeof(int),1,fpr1);
//debug start
//printf ("%d\n",hsize);
//for(;;);
//debug end
	fread(&vsize,sizeof(int),1,fpr1);
	fseek(fpr1,2,SEEK_SET);
	fread(&filesizebyte,sizeof(int),1,fpr1);
//debug start
//printf ("%d\n",filesizebyte);
//for(;;);
//debug end

/***************/
/* picture get */
/***************/
	vin = (unsigned char *)malloc(sizeof(unsigned char)*(filesizebyte-54));
	B = (unsigned char *)malloc(sizeof(unsigned char)*hsize*vsize);
	G = (unsigned char *)malloc(sizeof(unsigned char)*hsize*vsize);
	R = (unsigned char *)malloc(sizeof(unsigned char)*hsize*vsize);
	fseek(fpr1,54,SEEK_SET);
	if(fread(vin,sizeof(unsigned char),filesizebyte - 54,fpr1) != filesizebyte -54 ){
		printf("input file size err!!\n");
		exit(1);
	}
	fclose(fpr1);
//debug start
//for(;;);
//debug end

/***************************************/
/* set to B,G,R array with RGB PICTURE */
/***************************************/
	for(i=0,k=0;i<vsize;i++){
		for(j=0;j<hsize;j++){
			*(B+j*vsize+i) = *(vin+k);
			k++;
			*(G+j*vsize+i) = *(vin+k);
			k++;
			*(R+j*vsize+i) = *(vin+k);
			k++;
		}
		if(((hsize*3)%4) == 1){
			k=k+3;
		}
		if(((hsize*3)%4) == 2){
			k=k+2;
		}
		if(((hsize*3)%4) == 3){
			k=k+1;
		}
		if(((hsize*3)%4) == 0){
			;
		}
	}
//debug start
//for(;;);
//debug end
	BIN = (unsigned char *)malloc(sizeof(unsigned char)*hsize*vsize);
	GIN = (unsigned char *)malloc(sizeof(unsigned char)*hsize*vsize);
	RIN = (unsigned char *)malloc(sizeof(unsigned char)*hsize*vsize);

/*******************/
/* RGB arrangement */	
/*******************/

	for(i=0;i<vsize;i++){
		for(j=0;j<hsize;j++){
			*(RIN+j*vsize+i) = *(R+j*vsize+vsize-1-i);
			*(GIN+j*vsize+i) = *(G+j*vsize+vsize-1-i);
			*(BIN+j*vsize+i) = *(B+j*vsize+vsize-1-i);	
/* debug start */
//printf("%d ",*(BIN+j*vsize+i));
/* debug end */
		}
	}

//	RUPOUT = (unsigned char *)malloc(sizeof(unsigned char)*(hsize)*(vsize));
//	GUPOUT = (unsigned char *)malloc(sizeof(unsigned char)*(hsize)*(vsize));
//	BUPOUT = (unsigned char *)malloc(sizeof(unsigned char)*(hsize)*(vsize));

//	resize(  hsize,  vsize,  sizeminus,  cnt->smy,   RIN ,  RUPOUT);
//	resize(  hsize,  vsize,  sizeminus,  cnt->smy,   GIN ,  GUPOUT);
//	resize(  hsize,  vsize,  sizeminus,  cnt->smy,   BIN ,  BUPOUT);

//	sprintf(cnt->OutputFileName,"%s.bmp",outputfile);
//	fpw = fopen(cnt->OutputFileName,"wb");

/***************/
/* θ-> radian */
/***************/
	PI = atan(1.0) * 4.0;
	cnt->angle = cnt->angle * PI / 180.0;
	rotx = (double *)malloc(sizeof(double)*hsize*vsize);
	roty = (double *)malloc(sizeof(double)*hsize*vsize);
	for(i=0;i<vsize;i++){
		for(j=0;j<hsize;j++){
			*(rotx+j*vsize+i) = cos(cnt->angle) * ((double)(j)-((double)(hsize-1)/2.0)) + sin(cnt->angle) *(((double)(vsize-1)/2.0) - (double)(i));
			*(roty+j*vsize+i) = (-1.0) * sin(cnt->angle) * ((double)(j)-((double)(hsize-1)/2.0)) + cos(cnt->angle) * (((double)(vsize-1)/2.0) - (double)(i));
		}
	}	
/*debug start*/
//	for(i=0;i<vsize;i++){
//		for(j=0;j<hsize;j++){
//			printf( "(%d,%d)=%f,%f\n",j,i,*(rotx+j*vsize+i),*(roty+j*vsize+i));
//		}
//	}

//goto hhh;

/* debug end */
/*************************/
/* 回転前の座標		 */
/*     			 */
/*			 */
/*			 */
/*       *<-koko   *	 */
/*			 */
/*			 */
/*		+	 */
/*			 */
/*	 *         *	 */
/*			 */
/*			 */
/*			 */
/*************************/
	screen_rotx = (double *)malloc(sizeof(double)*hsize*vsize);
	screen_roty = (double *)malloc(sizeof(double)*hsize*vsize);

	for(i=0;i<vsize;i++){
		for(j=0;j<hsize;j++){
			*(screen_rotx+j*vsize+i) = *(rotx+j*vsize+i) + ((double)(hsize-1)/2.0) ;
//			*(screen_roty+j*vsize+i) = (((double)(vsize-1)/2.0) - (double)(i)) - *(roty+j*vsize+i); 	
			*(screen_roty+j*vsize+i) = ((double)(vsize-1)/2.0)  - *(roty+j*vsize+i); 	
		}
	}	

/*debug start*/
//	for(i=0;i<vsize;i++){
//		for(j=0;j<hsize;j++){
//			printf( "(%d,%d)=%f,%f\n",j,i,*(screen_rotx+j*vsize+i),*(screen_roty+j*vsize+i));
//		}
//	}

//goto hhh;

/* debug end */

	introtx = (int *)malloc(sizeof(int)*hsize*vsize);	
	introty = (int *)malloc(sizeof(int)*hsize*vsize);	
	
	for(i=0;i<vsize;i++){
		for(j=0;j<hsize;j++){
			if(*(screen_rotx+j*vsize+i) < 0.0){ //小さい方の整数に変換
			  	*(introtx+j*vsize+i) = (int)(*(screen_rotx+j*vsize+i)) - 1 ;
			} else {
				*(introtx+j*vsize+i) = (int)(*(screen_rotx+j*vsize+i));
			}
			if(*(screen_roty+j*vsize+i) < 0.0){ //小さい方の整数に変換
			  	*(introty+j*vsize+i) = (int)(*(screen_roty+j*vsize+i)) - 1 ;
			} else {
				*(introty+j*vsize+i) = (int)(*(screen_roty+j*vsize+i));
			}

		}
	}
/*debug start*/
//	for(i=0;i<vsize;i++){
//		for(j=0;j<hsize;j++){
//			printf( "(%d,%d)=%d,%d\n",j,i,*(introtx+j*vsize+i),*(introty+j*vsize+i));
//		}
//	}

//goto hhh;

/* debug end */

/**************/
/* 画素値計算 */
/**************/

/*****************/
/*		 */
/*		 */
/*    w	     x	 */
/*		 */
/*		 */
/*		 */
/*    y      z	 */
/*		 */
/*****************/
unsigned char *SQUARE,*SQUARER,*SQUAREG;
	int TAPNUMH,TAPNUMV,ll,kk;
	double TAPH[8],TAPV[8],TAPHSUM,FILTERH[8],FILTERHR[8],FILTERHG[8],FILTERV,FILTERVR,FILTERVG,TAPVSUM;
	TAPNUMV=TAPNUMH=8;
	RUPOUT = (unsigned char *)malloc(sizeof(unsigned char)*(hsize)*(vsize));
	GUPOUT = (unsigned char *)malloc(sizeof(unsigned char)*(hsize)*(vsize));
	BUPOUT = (unsigned char *)malloc(sizeof(unsigned char)*(hsize)*(vsize));
	SQUARE = (unsigned char *)malloc(sizeof(unsigned char)*TAPNUMV*TAPNUMH);
	SQUARER = (unsigned char *)malloc(sizeof(unsigned char)*TAPNUMV*TAPNUMH);
	SQUAREG = (unsigned char *)malloc(sizeof(unsigned char)*TAPNUMV*TAPNUMH);

	for(i=0;i<vsize;i++){
		for(j=0;j<hsize;j++){
			if((*(introtx+j*vsize+i) < 0) || ((*(introtx+j*vsize+i) + 1) > (hsize - 1)) || (*(introty+j*vsize+i) < 0) || ((*(introty+j*vsize+i)+1) > (vsize-1))){
				*(RUPOUT+j*vsize+i) = 128;
				*(GUPOUT+j*vsize+i) = 128;
				*(BUPOUT+j*vsize+i) = 128;
/* debug start */
//printf("%d,%d\n",*(introtx+j*vsize+i),*(introty+j*vsize+i));
/* debug end */
			} else {
				aaa = *(screen_rotx+j*vsize+i) - (double)(*(introtx+j*vsize+i));
//				bbb = 1.0 - aaa ;
//debug start
//				if(j==123 && i==253){printf("i=%d,j=%d,aaa=%f\n",i,j,aaa);}
//debug end				
				for(k=0;k<TAPNUMV;k++){
					for(l=0;l<TAPNUMH;l++){
						ll= *(introtx+j*vsize+i)+l-3;
						if(ll<0){
						    ll=-ll;
						} else if(ll >= hsize){
							ll = 2*(hsize-1)-ll;
						}
						kk = *(introty+j*vsize+i)+k-3;
						if(kk<0){
							kk=-kk;
						} else if(kk >= vsize){
							kk = 2*(vsize-1)-kk;
						}
//							SQUARE[l*TAPNUMV+k] = *(BIN+(*(introtx+j*vsize+i)+ll)*vsize+(*(introty+j*vsize+i))+kk) ;//(0,0)
  //                          SQUARER[l*TAPNUMV+k] =*(RIN+(*(introtx+j*vsize+i)+ll)*vsize+(*(introty+j*vsize+i))+kk) ;
	//					    SQUAREG[l*TAPNUMV+k] =*(GIN+(*(introtx+j*vsize+i)+ll)*vsize+(*(introty+j*vsize+i))+kk) ;
							SQUARE[l*TAPNUMV+k] = *(BIN+(ll)*vsize+(kk)) ;//(0,0)
                            SQUARER[l*TAPNUMV+k] =*(RIN+(ll)*vsize+(kk)) ;
						    SQUAREG[l*TAPNUMV+k] =*(GIN+(ll)*vsize+(kk)) ;
						//debug strat
//							if(i==0 && j==195){printf("k=%d,l=%d,kk=%d,ll=%d,SQUARE[l*TAPNUMV+k]=%d\n",k,l,kk,ll,SQUARE[l*TAPNUMV+k]);}
//							if(SQUARE[l*TAPNUMV+k] != 128){printf("i=%d,j=%d\n",i,j);while(1);}
//debug end
					}
				}
//debug start
//					if(i==0 && j==195){while(1);}
//debug end				
				for(k=0;k<TAPNUMH;k++){
					xx=-3.0-aaa+(double)(k);
					if(xx<=-3.0 || xx>=3.0){
						TAPH[k] = 0.0;
					} else if(xx == 0.0){
						TAPH[k] = 1.0;
					} else {
						TAPH[k] = sin(PI*xx)*sin(PI*xx/3.0)/(PI*xx/3.0)/(PI*xx);
					}
				}
				TAPHSUM = 0.0;
				for(k=0;k<TAPNUMH;k++){
				     TAPHSUM += TAPH[k];
				}
				for(k=0;k<TAPNUMH;k++){
					TAPH[k] /= TAPHSUM;
				}
				for(k=0;k<TAPNUMV;k++){
					FILTERH[k] = 0.0;
					FILTERHR[k] = 0.0;
					FILTERHG[k] = 0.0;
				}
				for(k=0;k<TAPNUMV;k++){
					for(l=0;l<TAPNUMH;l++){
						FILTERH[k] += TAPH[l]*SQUARE[l*TAPNUMV+k];
						FILTERHR[k] += TAPH[l]*SQUARER[l*TAPNUMV+k];
						FILTERHG[k] += TAPH[l]*SQUAREG[l*TAPNUMV+k];
					}
//debug start
//						printf("FILTER[%d]=%f\n",k,FILTERH[k]);
//debug end
				}
//debug start
//					if(i==0 && j==195){while(1);}
//debug end				
				ccc = *(screen_roty+j*vsize+i) - (double)(*(introty+j*vsize+i));
//debug start
//				if(j==123 && i==253){printf("i=%d,j=%d,ccc=%f\n",i,j,ccc);}
//debug end				
				for(k=0;k<TAPNUMV;k++){
					xx=-3.0-ccc+(double)(k);
					if(xx<=-3.0 || xx>=3.0){
						TAPV[k] = 0.0;
					} else if(xx == 0.0){
						TAPV[k] = 1.0;
					} else {
						TAPV[k] = sin(PI*xx)*sin(PI*xx/3.0)/(PI*xx/3.0)/(PI*xx);
					}
				}
				TAPVSUM = 0.0;
				for(k=0;k<TAPNUMV;k++){
				     TAPVSUM += TAPV[k];
				}
				for(k=0;k<TAPNUMV;k++){
					TAPV[k] /= TAPVSUM;
				}
					FILTERV = 0.0;
				    FILTERVR = 0.0;
				    FILTERVG = 0.0;
				for(k=0;k<TAPNUMV;k++){
					FILTERV += FILTERH[k]*TAPV[k];
					FILTERVR += FILTERHR[k]*TAPV[k];
					FILTERVG += FILTERHG[k]*TAPV[k];
				}
				
				if(FILTERV+0.5 > 255.0) {FILTERV = 255;}
				if(FILTERVR+0.5 > 255.0) {FILTERVR = 255;}
				if(FILTERVG+0.5 > 255.0) {FILTERVG = 255;}
				if(FILTERV+0.5 < 0.0) {FILTERV = 0.0;}
				if(FILTERVR+0.5 < 0.0) {FILTERVR = 0.0;}
				if(FILTERVG+0.5 < 0.0) {FILTERVG = 0.0;}
				
				//SQUARE[4*TAPNUMV+3] = *(BIN+(*(introtx+j*vsize+i)+1)*vsize+(*(introty+j*vsize+i)));//(1,0)
				//SQUARE[3*TAPNUMV+4] = *(BIN+(*(introtx+j*vsize+i))*vsize+(*(introty+j*vsize+i))+1) ;//(0,1)
				//SQUARE[4*TAPNUMV+4] = *(BIN+(*(introtx+j*vsize+i)+1)*vsize+(*(introty+j*vsize+i))+1) ;//(1,1)
				//SQUARE[0*TAPNUMV+0] = 
//				low_x = (double)ww*bbb + (double)xx*aaa;
//				up_x = (double)yy*bbb + (double)zz*aaa;
//				ccc = *(screen_roty+j*vsize+i) - (double)(*(introty+j*vsize+i));
//				ddd = 1.0 - ccc;
//				*(BUPOUT+j*vsize+i) = (unsigned char)((low_x*ddd + up_x*ccc)+0.5);
				*(BUPOUT+j*vsize+i) = (unsigned char)(FILTERV+0.5);
///				wwg = *(GIN+(*(introtx+j*vsize+i))*vsize+(*(introty+j*vsize+i))) ;
//				xxg = *(GIN+(*(introtx+j*vsize+i)+1)*vsize+(*(introty+j*vsize+i)));
//				yyg = *(GIN+(*(introtx+j*vsize+i))*vsize+(*(introty+j*vsize+i))+1) ;
//				zzg = *(GIN+(*(introtx+j*vsize+i)+1)*vsize+(*(introty+j*vsize+i))+1) ;
//				low_xg = (double)wwg*bbb + (double)xxg*aaa;
//				up_xg = (double)yyg*bbb + (double)zzg*aaa;
				*(GUPOUT+j*vsize+i) = (unsigned char)(FILTERVG+0.5);
//				wwr = *(RIN+(*(introtx+j*vsize+i))*vsize+(*(introty+j*vsize+i))) ;
//				xxr = *(RIN+(*(introtx+j*vsize+i)+1)*vsize+(*(introty+j*vsize+i)));
//				yyr = *(RIN+(*(introtx+j*vsize+i))*vsize+(*(introty+j*vsize+i))+1) ;
//				zzr = *(RIN+(*(introtx+j*vsize+i)+1)*vsize+(*(introty+j*vsize+i))+1) ;
//				low_xr = (double)wwr*bbb + (double)xxr*aaa;
//				up_xr = (double)yyr*bbb + (double)zzr*aaa;
				*(RUPOUT+j*vsize+i) = (unsigned char)(FILTERVR+0.5);
//debug start
//				if(j==123 && i==253){printf("%f %f %f\n",FILTERVR+0.5,FILTERVG+0.5,FILTERV+0.5);}
//debug end				
/* debug start */
//printf("%d,%d,%d,%d\n",(*(introtx+j*vsize+i))*vsize+(*(introty+j*vsize+i)),(*(introtx+j*vsize+i)+1)*vsize+(*(introty+j*vsize+i)),(*(introtx+j*vsize+i))*vsize+(*(introty+j*vsize+i))+1,(*(introtx+j*vsize+i)+1)*vsize+(*(introty+j*vsize+i))+1);
//printf("%f,%f,%f,%f\n",aaa,bbb,ccc,ddd);
//printf("%d,%d\n",*(introtx+j*vsize+i),*(introty+j*vsize+i));
//printf("%d ",*(BUPOUT+j*vsize+i));
/* debug end */
			}
			
		}
	}

/* debug start */
//for(i=0;i<vsize;i++){
//	for(j=0;j<hsize;j++){
//		*(BUPOUT+j*vsize+i) = *(BIN+j*vsize+i);
//		*(GUPOUT+j*vsize+i) = *(GIN+j*vsize+i);
//		*(RUPOUT+j*vsize+i) = *(RIN+j*vsize+i);
//	}
//}
/* debug end */	

//j=115+8;i=253;
//				*(RUPOUT+j*vsize+i) = 0;//(unsigned char)(FILTERVR+0.5);
//				*(GUPOUT+j*vsize+i) = 0;//(unsigned char)(FILTERVR+0.5);
//				*(BUPOUT+j*vsize+i) = 0;//(unsigned char)(FILTERVR+0.5);


	




//	hsize = NewHsize;
//	vsize = NewVsize;

	sprintf(cnt->OutputFileName,"%dx%d_%s.bmp",hsize,vsize,outputfile);
	fpw = fopen(cnt->OutputFileName,"wb");
/************************/
/* HEADER 54 byte write */
/************************/
	if(((hsize*3)%4) == 0){
		filesize = 0x36 + hsize*vsize*3;
	} else {
		filesize = 0x36 + hsize*vsize*3+(4-(hsize*3)%4)*vsize;
	}

	temp = 0x42; //'B'
	fwrite(&temp,sizeof(unsigned char),1,fpw);
	temp = 0x4D; //'M'
	fwrite(&temp,sizeof(unsigned char),1,fpw);
	fwrite(&filesize,sizeof(unsigned int),1,fpw);
	filesize = 0;
	fwrite(&filesize,sizeof(unsigned int),1,fpw);
	filesize = 0x00000036;
	fwrite(&filesize,sizeof(unsigned int),1,fpw);
	filesize = 0x28;
	fwrite(&filesize,sizeof(unsigned int),1,fpw);
	fwrite(&hsize,sizeof(int),1,fpw);	
	fwrite(&vsize,sizeof(int),1,fpw);
	filesize = 0x00180001;
	fwrite(&filesize,sizeof(unsigned int),1,fpw);
	filesize = 0;
	fwrite(&filesize,sizeof(unsigned int),1,fpw);
	fwrite(&filesize,sizeof(unsigned int),1,fpw);
	filesize = 0x00000EC4;
	fwrite(&filesize,sizeof(unsigned int),1,fpw);
	fwrite(&filesize,sizeof(unsigned int),1,fpw);
	filesize = 0;
	fwrite(&filesize,sizeof(unsigned int),1,fpw);
	fwrite(&filesize,sizeof(unsigned int),1,fpw);
	temp2 =0;

	for(i=0;i<vsize;i++){
		for(j=0;j<hsize;j++){
			fwrite((BUPOUT+j*vsize+vsize-1-i),sizeof(unsigned char),1,fpw);
			fwrite((GUPOUT+j*vsize+vsize-1-i),sizeof(unsigned char),1,fpw);
			fwrite((RUPOUT+j*vsize+vsize-1-i),sizeof(unsigned char),1,fpw);
		}
		temp = 4-((hsize*3)%4) ;
		if(temp != 4 ){
			for(k=0;k<temp;k++){
				fwrite( &temp2,sizeof(unsigned char),1,fpw);
			}
		}
	}	

	fclose(fpw);
hhh:
        return 0;
}

void resize( int hsize, int vsize, int sizeminus, int smy,  unsigned char *vin_buffer , unsigned char *vout)
{ 

double *VINR;
double *VINI;
double *VOUTR;
double *VOUTI;
double *VINRptr;
double *VINIptr;
double *VOUTRptr;
double *VOUTIptr;
double *kariR;
double *kariI;
int i,j,k,l,m,n,o ;
double PI;
double *fourieR;
double *fourieI;
	PI = atan(1)*4.0;
	kariR = (double *)malloc(sizeof(double)*(hsize+sizeminus)*(vsize+smy));
	kariI = (double *)malloc(sizeof(double)*(hsize+sizeminus)*(vsize+smy));
	VINR = (double *)malloc(sizeof(double)*(hsize+sizeminus)*(vsize+smy));
	VINI = (double *)malloc(sizeof(double)*(hsize+sizeminus)*(vsize+smy));
	VOUTR = (double *)malloc(sizeof(double)*(hsize+sizeminus)*(vsize+smy));
	VOUTI = (double *)malloc(sizeof(double)*(hsize+sizeminus)*(vsize+smy));
	VINRptr = VINR;
	VINIptr = VINI;
	VOUTRptr = VOUTR;
	VOUTIptr = VOUTI;
/************************/
/*			*/
/*      BUFFERING	*/
/*			*/
/************************/
//	for(i=0,k=0;i<vsize;i++){
//		for(j=0;j<hsize;j++){
//			*(vin_buffer+j*vsize+i) = *(vin+k);
//			k++;
//		}
//	}
/*************************/
/*			 */
/*     第一象限代入	 */
/*			 */
/*************************/
	for(i=0;i<vsize;i++){
		for(j=0;j<hsize;j++){
			*(VINR+j*vsize+i) = (double)(*(vin_buffer+j*vsize+i));
//			*(VINI+j*2*vsize+i) = 0.0;
		}
	}
/*************************/
/*			 */
/*     第二象限代入	 */
/*			 */
/*************************/
/*	for(i=0;i<vsize;i++){
		for(j=0;j<hsize;j++){
			*(VINR+(j+hsize)*2*vsize+i) = (double)(*(vin_buffer+(hsize-1-j)*vsize+i));
			*(VINI+(j+hsize)*2*vsize+i) = 0.0; 
		}
	}
*/
/*************************/
/*			 */
/*     第三象限代入	 */
/*			 */
/*************************/
/*
	for(i=0;i<vsize;i++){
		for(j=0;j<hsize;j++){
			*(VINR+j*2*vsize+i+vsize) = (double)(*(vin_buffer+j*vsize+(vsize-1-i)));
			*(VINI+j*2*vsize+i+vsize) = 0.0;
		}
	}
*/
/*************************/
/*			 */
/*     第四象限代入	 */
/*			 */
/*************************/
/*
	for(i=0;i<vsize;i++){
		for(j=0;j<hsize;j++){
			*(VINR+(j+hsize)*2*vsize+i+vsize) = (double)(*(vin_buffer+(hsize-1-j)*vsize+(vsize-1-i)));
			*(VINI+(j+hsize)*2*vsize+i+vsize) = 0.0;
		}
	}
*/

//debug
//for(;;);
//------
	fprintf(stderr,"水平方向のDFT開始しました。\n");

	for(i=0;i<vsize;i++){
		DFT1DH (hsize,vsize,VINRptr+i,VINIptr+i,VOUTRptr+i,VOUTIptr+i);
		printf("DFTH remain %d Times\n",vsize+hsize+(vsize+smy)+(hsize+sizeminus)-1-i);
	}

	fprintf(stderr,"水平方向のDFT終了しました。\n");
	for(i=0;i<vsize*hsize;i++){
		*(VINR+i) = *(VOUTR+i);
//		*(VINI+i) = *(VOUTI+i);
	}
//debug
//for(;;);
//------

	fprintf(stderr,"垂直方向のDFT開始しました。\n");

	for(i=0;i<hsize;i++){
		DFT1DV (vsize,VINRptr+(vsize)*i,VINIptr+(vsize)*i,VOUTRptr+(vsize)*i,VOUTIptr+(vsize)*i);
		printf("DFTV remain %d Times\n",hsize+(vsize+smy)+(hsize+sizeminus)-1-i);
	}
	fprintf(stderr,"垂直方向のDFT終了しました。\n");


//	fourieR = (double *)malloc(sizeof(double)*(hsize-sizeminus)*vsize);
//	fourieI = (double *)malloc(sizeof(double)*(hsize-sizeminus)*vsize);
	fourieR = (double *)malloc(sizeof(double)*(hsize+sizeminus)*(vsize+smy)*4);
	fourieI = (double *)malloc(sizeof(double)*(hsize+sizeminus)*(vsize+smy)*4);

/*縮小した画像のフーリエ変換像の配列作成*/

	fprintf(stderr,"高周波成分の除去開始しました。\n");
//	for(i=0;i<vsize*2;i++){
//		*(VOUTRptr+((hsize+sizeminus))*vsize*2+i) = *(VOUTRptr+((hsize+sizeminus))*vsize*2+i) * 2.0;
//		*(VOUTIptr+((hsize+sizeminus))*vsize*2+i) = 0.0;	
//	}

	for(i=0;i<vsize;i++){
		for(j=0;j<hsize-sizeminus;j++){
			*(fourieR+j*vsize+i)=*(VOUTRptr+j*vsize+i);
//			*(fourieI+j*vsize*2+i)=*(VOUTIptr+j*vsize*2+i);
		}
//		for(j=0;j<sizeminus;j++){
//			*(fourieR+(j+hsize)*vsize+i) = 0.0;
//			*(fourieI+(j+hsize)*vsize+i) = 0.0;
//		}
/*		for(j=0;j<hsize;j++){
			*(fourieR+((hsize+sizeminus*2)+j)*vsize*2+i) = *(VOUTRptr+(hsize+j)*vsize*2+i);
			*(fourieI+((hsize+sizeminus*2)+j)*vsize*2+i) = *(VOUTIptr+(hsize+j)*vsize*2+i);
		}
*/
	}

//	for(j=0;j<(hsize-sizeminus);j++){
//		*(fourieR+j*vsize*2+(vsize+smy)) = *(fourieR+j*vsize*2+(vsize+smy)) * 2.0;
//		*(fourieI+j*vsize*2+(vsize+smy)) = 0.0;
//	}

	for(j=0;j<(hsize-sizeminus);j++){
		for(i=0;i<vsize-smy;i++){
			*(kariR+j*(vsize-(smy))+i)=*(fourieR+j*vsize+i);
//			*(kariI+j*(vsize-(smy))+i)=*(fourieI+j*vsize+i);
		}
//		for(i=0;i<(smy);i++){
//			*(kariR+j*(vsize+(smy))+i+vsize) = 0.0;
//			*(kariI+j*2*(vsize+(smy))+i+vsize) = 0.0;
//		}
/*		for(i=0;i<vsize;i++){
			*(kariR+j*2*(vsize+(smy))+i+(vsize+(smy)*2)) =*(fourieR+j*2*vsize+i+vsize);
			*(kariI+j*2*(vsize+(smy))+i+(vsize+(smy)*2)) =*(fourieI+j*2*vsize+i+vsize);
		}
*/
	}
//debug start
//for(i=0;i<2*(vsize-smy);i++){
//	for(j=0;j<2*(hsize-sizeminus);j++){
//		printf("%f\n",*(kariR+j*2*(vsize-smy)+i));
//	}
//}	
//debug end
	for(i=0;i<(vsize-smy);i++){
		for(j=0;j<(hsize-sizeminus);j++){
			*(fourieR+j*(vsize-smy)+i) = *(kariR+j*(vsize-smy)+i);
//			*(fourieI+j*(vsize-smy)+i) = *(kariI+j*(vsize-smy)+i);
		}
	}
	fprintf(stderr,"高周波成分の除去終了しました。\n");
//debug start
//for(i=0;i<2*(vsize-smy);i++){
//	for(j=0;j<2*(hsize-sizeminus);j++){
//		printf("%f\n",*(fourieR+j*2*(vsize-smy)+i));
//	}
//}	
//debug end
	fprintf(stderr,"水平方向のIDFT開始しました。\n");
	
	for(i=0;i<(vsize-smy);i++){
		IDFT1DH ((hsize-sizeminus),(vsize-smy),fourieR+i,fourieI+i,VOUTRptr+i,VOUTIptr+i);
		printf("IDFTH remain %d Times\n",(vsize-smy)+(hsize-sizeminus)-1-i);
	}
	fprintf(stderr,"水平方向のIDFT終了しました。\n");
//debug start
//for(i=0;i<2*(vsize-smy);i++){
//	for(j=0;j<2*(hsize-sizeminus);j++){
//		printf("%f\n",*(VOUTRptr+j*2*(vsize-smy)+i));
//	}
//}	
//debug end
	fprintf(stderr,"垂直方向のIDFT開始しました。\n");
	for(i=0;i<(hsize-sizeminus);i++){
		IDFT1DV ((vsize-smy),VOUTRptr+(vsize-smy)*i,VOUTIptr+(vsize-smy)*i,fourieR+(vsize-smy)*i,fourieI+(vsize-smy)*i);
		printf("IDFTV remain %d Times\n",(hsize-sizeminus)-1-i);
	}
	fprintf(stderr,"垂直方向のIDFT終了しました。\n");
	
	fprintf(stderr,"出力中。\n");
	
	for(i=0,k=0;i<vsize-smy;i++){
		for(j=0;j<(hsize-sizeminus);j++){
			if((*(fourieR+j*(vsize-smy)+i)/(((double)(hsize*vsize)))*4.0) >= 255.0){
				*(vout+j*(vsize-smy)+i) = 255;
			} else if((*(fourieR+j*(vsize-smy)+i)/(((double)(hsize*vsize)))*4.0) <= 0.0){
				*(vout+j*(vsize-smy)+i) = 0;
			} else {
				*(vout+j*(vsize-smy)+i) = (unsigned char)(*(fourieR+j*(vsize-smy)+i)/(((double)(hsize*vsize)))*4.0);
//				*(vout+k) = (unsigned char)(*(fourieR+j*(vsize-smy)+i)/(double)(hsize*vsize)/((double)(vsize-smy) * (double)(hsize-sizeminus)));
//				*(vout+k) = (unsigned char)(*(fourieR+j*(vsize-smy)+i)/(double)(hsize*vsize)/(double)(hsize*vsize)*((double)(vsize-smy) * (double)(hsize-sizeminus)));
//				*(vout+k) = (unsigned char)((*(fourieR+j*(vsize-smy)+i))/(sqrt((double)(hsize*vsize)*((double)(vsize-smy) * (double)(hsize-sizeminus)))));
//				*(vout+k) = (unsigned char)((*(fourieR+j*(vsize-smy)+i))*((double)(hsize*vsize)));
			}
//debug
//printf("%f\n",((*(fourieR+j*2*(vsize-smy)+i))/(double)(hsize*vsize*4)));
//
			k++;
		}
	}
}// resize kansuu end	

void DFT1DV(int size, double *VINR, double *VINI, double *VOUTR, double *VOUTI)
{
	int i,j;
	double PI = atan(1)*4.0;
	for(i=0;i<size;i++){
		*(VOUTR+i) = 0.0;
//		*(VOUTI+i) = 0.0;
	}
	for(i=0;i<size;i++){
		for(j=0;j<size;j++){
			*(VOUTR+i) += (*(VINR+j)*cos(PI*(double)i*((double)(j)+0.5)/(double)size));// + *(VINI+j)*sin(2.0*PI*(double)i*(double)j/(double)size));
//			*(VOUTI+i) += (*(VINI+j)*cos(2.0*PI*(double)i*(double)j/(double)size) - *(VINR+j)*sin(2.0*PI*(double)i*(double)j/(double)size));
		}
		if(i==0){
			*(VOUTR+i) = 1.0/(2.0)*(*(VOUTR+i));
		}
	}	
		
}

void DFT1DH(int hsize, int vsize , double *VINR, double*VINI, double *VOUTR, double *VOUTI)
{
	int i,j;
        double PI = atan(1)*4.0;
        for(i=0;i<hsize;i++){
                *(VOUTR+i*vsize) = 0.0;
//                *(VOUTI+i*vsize) = 0.0;
        }
	for(i=0;i<hsize;i++){
                for(j=0;j<hsize;j++){
                        *(VOUTR+i*vsize) += (*(VINR+j*vsize)*cos(PI*(double)i*((double)(j)+0.5)/(double)hsize));// + *(VINI+j*vsize)*sin(2.0*PI*(double)i*(double)j/(double)hsize));
//                        *(VOUTI+i*vsize) += (*(VINI+j*vsize)*cos(2.0*PI*(double)i*(double)j/(double)hsize) - *(VINR+j*vsize)*sin(2.0*PI*(double)i*(double)j/(double)hsize));
                }
		if(i==0){
			*(VOUTR+i*vsize) = 1.0/(2.0)*(*(VOUTR+i*vsize));
		}
        }
}
void IDFT1DV(int size, double *VINR, double *VINI, double *VOUTR, double *VOUTI)
{
	int i,j;
	double PI = atan(1)*4.0;
	for(i=0;i<size;i++){
		*(VOUTR+i) = 0.0;
//		*(VOUTI+i) = 0.0;
	}
	for(i=0;i<size;i++){
		for(j=0;j<size;j++){
			*(VOUTR+i) += (*(VINR+j)*cos(PI*((double)(i)+0.5)*((double)(j)/*+0.5*/)/(double)size));// - *(VINI+j)*sin(2.0*PI*(double)i*(double)j/(double)size));
//			*(VOUTI+i) += (*(VINI+j)*cos(2.0*PI*(double)i*(double)j/(double)size) + *(VINR+j)*sin(2.0*PI*(double)i*(double)j/(double)size));
		}
		if(i==0){
			*(VOUTR+i) = 1.0*(*(VOUTR+i));
		}
	}	
		
}

void IDFT1DH(int hsize, int vsize , double *VINR, double*VINI, double *VOUTR, double *VOUTI)
{
	int i,j;
        double PI = atan(1)*4.0;
        for(i=0;i<hsize;i++){
                *(VOUTR+i*vsize) = 0.0;
//                *(VOUTI+i*vsize) = 0.0;
        }
	for(i=0;i<hsize;i++){
                for(j=0;j<hsize;j++){
                        *(VOUTR+i*vsize) += (*(VINR+j*vsize)*cos(PI*((double)(i)+0.5)*((double)(j)/*+0.5*/)/(double)hsize));// - *(VINI+j*vsize)*sin(2.0*PI*(double)i*(double)j/(double)hsize));
//                        *(VOUTI+i*vsize) += (*(VINI+j*vsize)*cos(2.0*PI*(double)i*(double)j/(double)hsize) + *(VINR+j*vsize)*sin(2.0*PI*(double)i*(double)j/(double)hsize));
                }
		if(i==0){
			*(VOUTR+i*vsize) = 1.0*(*(VOUTR+i*vsize));
		}
        }
}
