#include <v_lib.h>

V_LOCAL	u32_t
u32_pack_float(vec_t src)
{
	if(src < 0)
		src = 0;
	else if(src > 1)
		src = 1;
	return (u32_t)(0xFFFFFFFF * (double)src);
}

#define	u32_unpack_float(src) ((vec_t)src / (vec_t)0xFFFFFFFF)

/*
V_LOCAL	u32_t
u32_pack_float(vec_t src)
{
	s32_t tmp;
	double dtmp = src;
	if(dtmp < -0x10000)
		dtmp = -0x10000;
	else if(dtmp > 0xFFFF)
		dtmp = 0xFFFF;
	tmp = (s32_t)(dtmp * 0x10000);
	return (u32_t)tmp;
}

vec_t u32_unpack_float(u32_t src)
{
	s32_t tmp = (s32_t)src;
	if(tmp < 0)
		return (tmp / (vec_t)0x10000);
	return (tmp / (vec_t)0xFFFF);
}
*/

vboolean	V_GLOBAL
tgaSaveGray32(char *file_name,matrix_p data)
{
	CALLER_NAME(tgaSaveGray32)
	DEBUG_MESSAGE_INCORRECT()
	vec_t *src, *endsrc;
	u32_t bits, width, height, r;
	u8_p buf, dst;
	if(!file_name || !*file_name || !data || !data->rows || !data->cols)
	{
		ERROR_GENERIC(incorrect_parameters);
		return false;
	}
	width = data->cols;
	height = data->rows;
	buf = (u8_p)memAlloc(data->cols * data->rows * 4);
	dst = buf;
	for(r = 0;r < height;r++)
	{
		src = data->cell[r];
		endsrc = src + width;
		while(src < endsrc)
		{
			bits = u32_pack_float(*src);
			dst[0] = (bits >> 24) & 0xFF;
			dst[1] = (bits >> 16) & 0xFF;
			dst[2] = (bits >> 8) & 0xFF;
			dst[3] = bits & 0xFF;
			src++;
			dst += 4;
		}
	}
	tgaSaveEx(file_name,width,height,buf,true);
	memFree(buf);
	return true;
}

matrix_p V_GLOBAL
tgaLoadGray32(char *file_name)
{
	CALLER_NAME(tgaLoadGray32)
	DEBUG_MESSAGE_INCORRECT()
	matrix_p result;
	vec_t *dst, *enddst;
	u32_t width, height, r, bits;
	u8_p buf, src;
	if(!file_name || !*file_name)
	{
		ERROR_GENERIC(incorrect_parameters);
		return NULL;
	}
	buf = tgaLoad(file_name,&width,&height);
	if(!buf)
		return NULL;
	result = matAlloc(height,width);
	src = buf;
	for(r = 0;r < height;r++)
	{
		dst = result->cell[r];
		enddst = dst + width;
		while(dst < enddst)
		{
			bits = (u32_t)(src[3]);
			bits |= (u32_t)(src[2]) << 8;
			bits |= (u32_t)(src[1]) << 16;
			bits |= (u32_t)(src[0]) << 24;
			*dst = u32_unpack_float(bits);
			dst++;
			src += 4;
		}
	}
	memFree(buf);
	return result;
}

int main()
{
	vec_t diff, maxdiff = 0;
	u32_t i, j, w = 512, h = 512;
	matrix_p data, other;
	logStartConsoleLog();
	logUpperLevel(LOG_TRACE);
	data = matAlloc(h,w);
	for(i = 0;i < h;i++)
	{
		vec_t alpha = sin(M_PI * i / h);
		for(j = 0;j < w;j++)
			data->cell[i][j] = 0.5 + 0.5 * alpha * sin(M_PI * j / w);
	}
	tgaSaveGray32("out.tga",data);
	other = tgaLoadGray32("out.tga");
	assert(other);
	for(i = 0;i < h;i++)
		for(j = 0;j < w;j++)
		{
			diff = v_abs(data->cell[i][j] - other->cell[i][j]);
			if(diff > maxdiff)
				maxdiff = diff;
		}
	printf("MAXDIFF %g\n",maxdiff);
	memFree(data);
	memFree(other);
	memPrintStats();
	return 0;
}
