//---------------------------------------------------------
// 概要      : 画像を表示する
// File Name : cvimage_01.cpp
//
// ※注意※
// OpenCVは【RGB】の順番ではなく，【BGR】の順になっている．
//
//
// 2009/06/15  Yuya Ishikawa
// 2009/06/22  T.Nakaguchi
//---------------------------------------------------------

#include <stdio.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

#define MAX_POINTS 5

// 変数宣言
IplImage *src_img;	// 入力画像
IplImage **dst_img;	// 出力画像
IplImage *g_showImg;	// 表示用画像


int levels = 0;  // トラックバーの値入力する数値の最小値
int g_numClick = 0;
CvPoint g_click[MAX_POINTS];


char g_path[1024];

//-------------------------------------------
//
// トラックバーの値が変わった時に呼ばれる関数
//
// 引数　pos：トラックバーの値
//
//-------------------------------------------
void on_change(int pos)
{
	// クリックを描画
	cvCopy(dst_img[pos], g_showImg);
	for (int i=0; i<g_numClick; i++)
	{
		cvLine(g_showImg, cvPoint(g_click[i].x-10, g_click[i].y-10),
			cvPoint(g_click[i].x+10, g_click[i].y+10), cvScalar(255,255,255,0));
		cvLine(g_showImg, cvPoint(g_click[i].x-10, g_click[i].y+10),
			cvPoint(g_click[i].x+10, g_click[i].y-10), cvScalar(255,255,255,0));
	}

	// 画像を表示する
	cvShowImage("dst_img", g_showImg);
}

//-------------------------------------------
//
// マウスイベント用コールバック関数
//
// マウスクリックしたときに呼び出される関数
//
//-------------------------------------------
void on_click(int event_id, int x, int y, int flags, void *param)
{
	int pos = cvGetTrackbarPos("撮影画像数", "dst_img");

	if (event_id == CV_EVENT_LBUTTONDOWN && g_numClick < MAX_POINTS)
	{
		printf("x,y = %d, %d\n", x, y);

		g_click[g_numClick ++] = cvPoint(x, y);
		on_change(pos);

		if (g_numClick == MAX_POINTS)
		{
			// データ保存
			char filename[1024];
			sprintf_s(filename, sizeof(filename), "%s/Info.csv", g_path);
			FILE *fp;
			fopen_s(&fp, filename, "w");	//ファイル名

			fprintf(fp, "%d\n", pos);
			for(int i=0; i<MAX_POINTS; i++)	fprintf(fp, "%d, %d\n", g_click[i].x, g_click[i].y);

			fclose(fp);	//ファイルを閉じる

			printf("データを保存しました．\n");
			printf("File: %s\n", filename);
		}
	}
	if (event_id == CV_EVENT_RBUTTONDOWN)
	{
		g_numClick = 0;
		on_change(pos);
		printf("ポイントをクリアしました\n");
	}
}

//-------------------------------------------
//
// main関数
//
//-------------------------------------------

int main( int argc, char **argv ){

	char date[10];  // 表示する画像の撮影日
	char *time[3] = {"morning", "daytime", "evening"};  // 表示する画像の時間帯 
	int mde;  // 朝昼夕
	int sub;  // 被験者番号
	int count;  // 撮影回数
	//char time[256];  // 表示する画像の時間帯
	//int NUM;		 // 表示する画像枚数

	// 表示する画像の撮影日
	printf("表示する画像の撮影日(例：0406)：");
	scanf_s("%s", date, sizeof(date));
	// 表示する画像の時間帯
	printf("表示する画像の時間帯 1:morning 2:daytime 3:evening：");
	scanf_s("%d", &mde);
	// 被験者番号
	printf("被験者番号：");
	scanf_s("%d", &sub);
	// 撮影回数
	printf("撮影回数：");
	scanf_s("%d", &count);
	//// 表示する画像枚数
	//printf("\n表示する画像枚数は？：");
	//scanf("%d", &NUM);

	// ファイルのパスを決定
	sprintf_s(g_path, sizeof(g_path), 
		"Z:/ST3_視診/臨床実験/舌撮影画像（20090406-20090612）/200904%s/%s%d-%d", date, time[mde-1], sub, count);

	// 枚数を決定
	char filename[1024];
	WIN32_FIND_DATA ffd;
	int numFrames = -1;
	do
	{
		sprintf_s(filename, sizeof(filename), "%s/snapshot%d.bmp", g_path, ++numFrames);
	}
	while(FindFirstFile(filename, &ffd) != INVALID_HANDLE_VALUE);
	printf("%d frames found.\n", numFrames);

	// 画像バッファ生成
	dst_img = new IplImage* [numFrames-30];

	// ウィンドウを生成する
	cvNamedWindow("dst_img", CV_WINDOW_AUTOSIZE);
	
	for(int i=0; i<numFrames-30; i++){
		// 舌画像のファイル名（tongue0.jpg, tougue1.jpg,･･･）
		char filename[1024];
		sprintf_s(filename, sizeof(filename), "%s/snapshot%d.bmp", g_path, i);

		// 画像の読み込み
		src_img = cvLoadImage (filename, CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
		if (!src_img)
		{
			fprintf(stderr, "ファイルの読み込みに失敗しました．\n");
			fprintf(stderr, "%s\n", filename);
			getchar();
			return 1;
		}

		// リサイズ領域を確保
		dst_img[i] = cvCreateImage(cvSize(src_img->width/2, src_img->height/2),IPL_DEPTH_8U, 3);

		// リサイズ
//		cvResize(src_img, dst_img[i], CV_INTER_CUBIC); 
		cvResize(src_img, dst_img[i], CV_INTER_NN); 
		//cvResizeの3番目の引数により補間法を指定できる
		//[補間法]------------------------------------------
		// CV_INTER_NN     : 最近傍補間
		// CV_INTER_LINEAR : バイリニア補間（双直線補間）
		// CV_INTER_AREA   : ピクセル領域の関係を用いたリサンプリング．
		//                   ( 拡大は CV_INTER_NN 同様．縮小はモアレを回避できる手法 )
		// CV_INTER_CUBIC  : 双三次補間
		//--------------------------------------------------

		cvReleaseImage(&src_img);
	}

	// 表示用画像の作成
	g_showImg = cvCreateImage(cvSize(dst_img[0]->width, dst_img[0]->height),IPL_DEPTH_8U, 3);

	// on_change関数で0秒目を呼び出して表示
	on_change(0);  

	// トラックバーを作成する
	cvCreateTrackbar("撮影画像数", "dst_img", &levels, numFrames-1, on_change);

	// マウスイベント
	cvSetMouseCallback("dst_img", on_click, 0);	
			
	// キー入力を待つ
	cvWaitKey( 0 );

	// メモリを解放する
	cvReleaseImage(&g_showImg);
	for(int j=0; j<numFrames-30; j++){
		cvReleaseImage(&dst_img[j]);
	}
	delete [] dst_img;

	// ウィンドウを破棄する
	cvDestroyWindow("dst_img");

	return 0;
}
