/*===========================================
          DolphMorph（ドルフモーフ）

      モーフィング＆変形アニメ作成ソフト

  モーフィングアルゴリズム: EAST 1994
  インターフェース作成:     松内 良介 1994
===========================================*/
#if 0
	image.c

	IMAGE	*image_new(int width, int height)
	void	image_delete(IMAGE *im)
	IMAGE	*image_copy(IMAGE *im)
	int 	image_loadTIFF(IMAGE *im, char *filename)
	int		image_saveTIFF(IMAGE *im, char *filename)
	IMAGE	*image_createloadTIFF(char *filename)
	void	image_zoomdown(IMAGE *dest, IMAGE *src)
	void	image_zoomdownDark(IMAGE *dest, IMAGE *src, int bDark)
	void	image_getDispSize(IMAGE *im,int maxwid,int maxht,int *wid,int *ht)
	void	image_disp(IMAGE *im, int x, int y, int width, int height)
	void	image_dumpout(IMAGE *im, char *filename)
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winb.h>
#include <te.h>
#include <fntb.h>
#include <gui.h>
#include <egb.h>
#include <wgb.h>
#include <msdos.cf>

#include <ryosuke.h>
#include <usrlib.h>

#include "morph.h"
#include "points.h"
#include "egbmac.h"
#include "wgbmac.h"
#include "guisub.h"
#include "image.h"

IMAGE	*image_new(int width, int height)
{
	IMAGE *pi;
	if ((pi = TL_calloc(1,sizeof(IMAGE))) == NULL)
		return NULL;
	if ((pi->image = TL_calloc(2,width * height)) == NULL)
		{ TL_free(pi);  return NULL; }
	pi->width = width;
	pi->height = height;
	pi->virwid = width;
	pi->virht = height;
	return pi;
}

void	image_delete(IMAGE *im)
{
	TL_free(im->image);
	TL_free(im);
}

IMAGE	*image_copy(IMAGE *im)
{
	IMAGE *pi;
	if ((pi = TL_calloc(1,sizeof(IMAGE))) == NULL)
		return NULL;
	pi->width  = im->width;
	pi->height = im->height;
	pi->virwid = im->virwid;
	pi->virht  = im->virht;
	if ((pi->image = TL_calloc(2,im->width * im->height)) == NULL)
		{ TL_free(pi);  return NULL; }
	memcpy(pi->image, im->image, 2 * im->width * im->height);
	return pi;
}

	static IMAGE *_pi;
	static TIFFinfo tiffinfo;

	static int putimage(char *buf, int yofs, int ylen)
	{
		int i;
		for (i=0; i<ylen; i++)
		{
			memcpy( _pi->image + (_pi->width*2)*(yofs+i),
				    buf + (tiffinfo.xlen*2)*i,
				    _min(_pi->width,tiffinfo.xlen)*2 );
		}
		return 0;
	}

int image_loadTIFF(IMAGE *im, char *filename)
{
	_pi = im;
	if (TIFFgetinfo(filename, &tiffinfo) != 0)
		return -1;
	TIFFload_putimagefunc(putimage);
	im->virwid = _min(im->width,  tiffinfo.xlen);
	im->virht  = _min(im->height, tiffinfo.ylen);
	return TIFFload(filename,0,0);
}

	static int getimage(char *buf, int yofs, int ylen)
	{
		int i;
		for (i=0; i<ylen; i++)
		{
			memcpy( buf + (_pi->width*2)*i,
					_pi->image + (_pi->width*2)*(yofs+i),
				    _pi->width*2 );
		}
		return 0;
	}

int image_saveTIFF(IMAGE *im, char *filename)
{
	_pi = im;
	EGB_writePage(guiEgbPtr, 1);
	TIFFsave_getimagefunc(getimage);
	int ret;
	if ((ret = TIFFsave(filename,0,0,im->width,im->height,1)) != 0)
	{
		if (ret == -1)
			return ERROR_CANNOTOPEN;
		else if (ret == -2)
			return ERROR_NOMEMORY;
		else if (ret == -3)
			return ERROR_DISKFULL;
		else if (ret == -4)
			return ERROR_OTHER;
	}
	EGB_writePage(guiEgbPtr, 0);
	return 0;
}

int image_createloadTIFF(IMAGE **ppi, char *filename)
{
	IMAGE *im;
	int ret;
	if ((ret = TIFFgetinfo(filename, &tiffinfo)) != 0)
	{
		if (ret == -1)       return ERROR_CANNOTOPEN;
		else if (ret == -2)  return ERROR_INVALIDFORMAT;
		else                 return ERROR_NOMEMORY;
	}
	if (tiffinfo.pixelsize != MORPH_PIXELSIZE)
		return ERROR_INVALIDPIXELSIZE;
	if ((im = image_new(tiffinfo.xlen, tiffinfo.ylen)) == NULL)
		return ERROR_NOMEMORY;
	_pi = im;
	im->virwid = tiffinfo.xlen;
	im->virht  = tiffinfo.ylen;
	TIFFload_putimagefunc(putimage);
	TIFFload(filename,0,0);
	*ppi = im;
	return 0;
}

static void image_calcZoomParm(IMAGE *im, int maxwid,int maxht,
							   int *r, int *wid, int *ht)
/* ある画像を特定の大きさに縮小したとき、その縮小比と縦横サイズを求める */
{
  /* 縮小率を計算 */
	int	_r,r1,r2;
	r1 = (im->width  << 16) / maxwid;
	r2 = (im->height << 16) / maxht;
	_r = _max(r1,r2);
  /* 縮小後の縦横のサイズを計算 */
	int _wid, _ht;
	if (im->width * maxht > maxwid * im->height)
		_wid = maxwid, _ht = (im->height << 16) / _r;	/* 元画像が横長 */
	else
		_wid = (im->width << 16) / _r, _ht = maxht;		/* 元画像が縦長 */
  /* 計算結果を格納 */
	if (r != NULL)
		*r = _r;
	if (wid != NULL)
		*wid = _wid;
	if (ht != NULL)
		*ht = _ht;
}

void image_zoomdown(IMAGE *dest, IMAGE *src)
{
	int dx2,dy2,i,j;
	memset(dest->image, 0, dest->width*dest->height*2);
  /* 縮小率と、縮小後の画像サイズを計算 */
	int r,wid,ht;
	image_calcZoomParm(src,dest->width,dest->height, &r,&wid,&ht);
  /* 縮小転送 */
	int sx,sy,dx,dy;
	unsigned short *dp,*sp;
	for (dy=0,sy=0; dy < ht; dy++,sy+=r)
	{
		dp = &((unsigned short *)dest->image)[dest->width * dy];
		sp = &((unsigned short *)src->image)[src->width * ((sy+0x8000)>>16)];
		for (dx=0,sx=0; dx < wid; dx++,sx+=r)
			dp[dx] = sp[(sx+0x8000) >> 16];
	}
	dest->virwid = wid;
	dest->virht  = ht;
}

void image_zoomdownDark(IMAGE *dest, IMAGE *src, int bDark)
{
	int dx2,dy2,i,j;
	memset(dest->image, 0, dest->width*dest->height*2);
  /* 縮小率と、縮小後の画像サイズを計算 */
	int r,wid,ht;
	image_calcZoomParm(src,dest->width,dest->height, &r,&wid,&ht);
  /* 縮小転送 */
	int sx,sy,dx,dy;
	unsigned short *dp,*sp;
	for (dy=0,sy=0; dy < ht; dy++,sy+=r)
	{
		dp = &((unsigned short *)dest->image)[dest->width * dy];
		sp = &((unsigned short *)src->image)[src->width * ((sy+0x8000)>>16)];
		if (!bDark)
		{
			for (dx=0,sx=0; dx < wid; dx++,sx+=r)
				dp[dx] = sp[(sx+0x8000) >> 16];
		}
		else
		{
			for (dx=0,sx=0; dx < wid; dx++,sx+=r)
				dp[dx] = (sp[(sx+0x8000) >> 16] >> 1) & (15|(15<<5)|(15<<10));
		}
	}
	dest->virwid = wid;
	dest->virht  = ht;
}

void	image_getDispSize(IMAGE *im,int maxwid,int maxht,int *wid,int *ht)
/* im:表示のオリジナルとなる画像(or NULL) */
{
	if (im == NULL)
		{ *wid = *ht = 0;  return; }
  /* 縮小後の画像サイズを計算 */
	int _wid,_ht;
	image_calcZoomParm(im,(maxwid+1)/2,(maxht+1)/2, NULL,&_wid,&_ht);
	if (wid != NULL)
		*wid = _wid * 2;
	if (ht != NULL)
		*ht = _ht * 2;
}

void image_disp(IMAGE *im, int x, int y, int width, int height)
{
	RM_setOriginZero();
	if (im == NULL)
	{
		WGB_RBOXFILL(guiEgbPtr, x,y,width,height,WINBACK, 0);
		goto END;
	}
	WGB_RBOXFILL(guiEgbPtr, x,y,im->virwid*2,im->virht*2,0, 0);
	int marginWid, marginHt;
	marginWid = width - im->virwid*2;
	marginHt =  height - im->virht*2;
	if (marginWid > 0)
		WGB_RBOXFILL(guiEgbPtr, x+im->virwid*2,y,marginWid,height,WINBACK,0);
	if (marginHt > 0)
		WGB_RBOXFILL(guiEgbPtr, x,y+im->virht*2,width,marginHt,WINBACK, 0);
	RM_putblock32k(im->image, x/2, y/2, im->width, im->height);
   END:;
	RM_recoverOrigin();
}

void image_dumpout(IMAGE *im, char *filename)
/* デバッグのために画像データをベタ出力 */
{
	// printf("image_dumpout: [%s](%d,%d)\n", filename,im->width, im->height);
	FILE *fp;
	if ((fp = fopen(filename, "wb")) != NULL)
	{
		fwrite(im->image,2,im->width * im->height,fp);
		fclose(fp);
	}
}
