#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include "image.h"
#ifdef _DEBUG
#ifdef WIN32
#include <crtdbg.h>
#endif
#endif

#define MAX_BRIGHTNESS (255)


/**
 * @brief 画像情報構造体作成
 *
 */
Image _IMGcreate_image(int width, int height)
{
	Image image;

	if((image = (Image)malloc(sizeof(Image_)))==NULL) {
		fprintf(stderr, "cannot malloc: _IMGcreate_image");
		return NULL;
	}

	image->width = width;
	image->height = height;

	if((image->image = (unsigned char *)malloc(width*height))==NULL) {
		fprintf(stderr, "Can't malloc");
		return NULL;
	}
	_IMGclear(image, MAX_BRIGHTNESS);

	return image;
}

/**
 * @brief 画像情報構造体破棄
 *
 */
void _IMGfree_image(Image image)
{
	free(image->image);
	free(image);
}

/**
 * @brief 画像情報クリア
 *
 */
void _IMGclear(Image image, unsigned char value)
{
	memset(image->image, value, image->width*image->height);
}

/* int */
/* _IMGload_pgm(const char *fm_name, Image tempimg) */
/* { */
/*   FILE *fp; */
/*   char str[100]; */
/*   struct stat buf; */
/*   int ret=0; */

/*   // ファイル以外は不可 */
/*   if(stat(fm_name, &buf) == -1) { */
/*     perror(fm_name); */
/*     return -1; */
/*   } */
/*   if(!(buf.st_mode & S_IFREG)) { */
    
/*     return -1; */
/*   } */
     
/*   if((fp=fopen(fm_name, "r")) == NULL) { */
/*     fprintf(stderr, "file not found:%s", fm_name); */
/*     return -1; */
/*   } */
  
/*   fgets(str, 100, fp); /// P5 */
/*   fgets(str, 100, fp); /// #- action */
/*   //  fgets(str, 100, fp); /// blank */
/*   /\* */
/*   if(str[0]=='#') */
/*     ret = atoi(str[1]); */
/*   *\/ */
/*   fgets(str, 100, fp); /// width, height */
/*   fgets(str, 100, fp); /// depth(255) */

/*   fread(tempimg->image, 1, (tempimg->width)*(tempimg->height), fp); */
/*   fclose(fp); */

/*   return ret; */
/* } */


/* 画像データの出力 */
int _IMGsave_pgm(const char *fm_name, Image tempimg)
{
	FILE *fp;
	int x,y;

	//fp = fopen(file_name, "wb");
	fp = fopen(fm_name, "w");

	fputs( "P5\n", fp );

	fputs( "# Created by ato-a\n", fp );

	fprintf( fp, "%d %d\n", tempimg->width, tempimg->height );

	fprintf( fp, "%d\n", MAX_BRIGHTNESS );

	for ( y = 0; y < tempimg->height; y++ ) {
		for ( x = 0; x < tempimg->width; x++ ) {
			fputc( tempimg->image[ y*tempimg->width + x ], fp );
		}
	}
	fclose(fp);

	return 1;
}

/*! 画像の(x,y方向それぞれへの)拡大 mag_x倍 x mag_y倍
 */
void _IMGzoom(Image src, Image dst, double mag_x, double mag_y)
{
	int				i,				j;
	unsigned char	*simage,		*dimage;
	int				swidth,			sheight;
	int				dwidth,			dheight;
	double			src_double_x,	src_double_y;
	int				src_int_x,		src_int_y;

	mag_x = 1.0/mag_x;
	mag_y = 1.0/mag_y;

	simage = src->image;
	swidth = src->width;
	sheight = src->height;

	dimage = dst->image;
	dwidth = dst->width;
	dheight = dst->height;

	for(j=0,src_double_y=0.0; j<dheight; j++,src_double_y+=mag_y){
		src_int_y = (int)src_double_y;
		if(src_int_y >= sheight)
			continue;
		for(i=0, src_double_x=0.0; i<dwidth; i++,src_double_x+=mag_x){
			src_int_x = (int)src_double_x;
			if(src_int_x >= swidth)
				continue;
			dimage[(j*dwidth)+i] = simage[(src_int_y*swidth)+src_int_x];
		}
	}
}

/* YUV 2 Y */
int _IMGget_y(const Image src, Image dst)
{
	int i, j;

	if (( src->width != dst->width * 2 ) || ( src->height != dst->height * 2 )) {
		fprintf(stderr, "_IMGget_y: please cheak <src> and <dst> image size.\n");
		return -1;
	}

	for ( j=0; j < dst->height; j++ ) {
		for( i=0; i < dst->width; i++ ) {
			dst->image[ j*dst->width + i ] = src->image[ (j*2)*src->width + (i*2) ];
		}
	}
	return 1;
}

/**
 * @brief 画像を1/4サイズに縮めて鏡像(水平方向反転)にする
 *
 */
int _IMGhalf(const Image src, Image dst)
{
	int i, j;
	int n, m;

	// srcイメージとdstイメージのサイズを確認する。(srcサイズは、dstの縦横の2倍であること、あるいはdstサイズはsrcの1/2)
	if (( src->width != dst->width * 2 ) || ( src->height != dst->height * 2 )) {
		fprintf(stderr, "_IMGget_y: please cheak <src> and <dst> image size.\n");
		return -1;
	}

	for ( j=0; j < dst->height; j++ ) {	// dstの高さループ
		for( i=0; i < dst->width; i++ ) {	// dstの幅ループ
			n = (i*2);				// 0,2,4,6,・・・srcの奇数列ピクセルを間引く
			m = (j*2)*src->width;	// 0,2,4,6,・・・srcの奇数行ピクセルを間引く

			// 画像の右端からデータ格納・・・
			// ソースのコピー対象ピクセルと右・下・右下(間引かれるピクセル)のピクセル値の平均を入れる
			// ・・・左端から右端に格納するので鏡像になる
			dst->image[ j*dst->width + (dst->width-i-1) ] = 
													(unsigned int)( src->image[ m + n ] +
													src->image[ m + src->width + n ] +
													src->image[ m + n + 1 ] +
													src->image[ m + src->width + n + 1 ] ) / 4;
		}
	}
	return 1;
}
