The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
/* Created by Anton Berezin <tobez@plab.ku.dk> */
#include "img_conv.h"

#ifdef __cplusplus
extern "C" {
#endif


#define var (( PImage) self)

#define minimum_ByteValue 0
#define maximum_ByteValue 255
#define minimum_ShortValue INT16_MIN
#define maximum_ShortValue INT16_MAX
#define minimum_LongValue INT32_MIN
#define maximum_LongValue INT32_MAX

#define macro_asis(SourceType,DestType)                                        \
void ic_##SourceType##_##DestType( Handle self,                           \
		Byte *dstData, PRGBColor dstPal, int dstType, int * dstPalSize, Bool palSize_only)   \
{                                                                              \
	SourceType *src = (SourceType*) var->data;                                   \
	DestType *dst = (DestType*) dstData;                                        \
	int y;                                                                      \
	int  width = var->w;                                                         \
	int srcLine = LINE_SIZE(width,var->type);                                   \
	int dstLine = LINE_SIZE(width,dstType);                                      \
	for ( y = 0; y < var->h; y++)                                                \
	{                                                                           \
		SourceType *s = src;                                                     \
		DestType *d = dst;                                                       \
		SourceType *stop = s + width;                                            \
		while ( s != stop) *d++ = (DestType)*s++;                                \
		src = (SourceType*)(((Byte*)src) + srcLine);                             \
		dst = (DestType*)(((Byte*)dst) + dstLine);                               \
	}                                                                           \
	memcpy( dstPal, map_RGB_gray, 256 * sizeof( RGBColor));                     \
}

#define macro_asis_toint(SourceType,DestType)                                        \
void ic_##SourceType##_##DestType( Handle self,                           \
		Byte *dstData, PRGBColor dstPal, int dstType, int * dstPalSize, Bool palSize_only)   \
{                                                                              \
	SourceType *src = (SourceType*) var->data;                                   \
	DestType *dst = (DestType*) dstData;                                        \
	int y;                                                                      \
	int  width = var->w;                                                         \
	int srcLine = LINE_SIZE(width,var->type);                                   \
	int dstLine = LINE_SIZE(width,dstType);                                      \
	for ( y = 0; y < var->h; y++)                                                \
	{                                                                           \
		SourceType *s = src;                                                     \
		DestType *d = dst;                                                       \
		SourceType *stop = s + width;                                            \
		while ( s != stop) *d++ = (DestType)(*s++ + 0.5);                        \
		src = (SourceType*)(((Byte*)src) + srcLine);                             \
		dst = (DestType*)(((Byte*)dst) + dstLine);                               \
	}                                                                           \
	memcpy( dstPal, map_RGB_gray, 256 * sizeof( RGBColor));                     \
}

#define macro_asis_complex(SourceType,DestType)                                        \
void ic_##SourceType##_##DestType##_complex( Handle self,                           \
		Byte *dstData, PRGBColor dstPal, int dstType, int * dstPalSize, Bool palSize_only)  \
{                                                                              \
	SourceType *src = (SourceType*) var->data;                                   \
	DestType *dst = (DestType*) dstData;                                        \
	int y;                                                                      \
	int  width = var->w;                                                         \
	int srcLine = LINE_SIZE(width,var->type);                                   \
	int dstLine = LINE_SIZE(width,dstType);                                      \
	for ( y = 0; y < var->h; y++)                                                \
	{                                                                           \
		SourceType *s = src;                                                     \
		DestType *d = dst;                                                       \
		SourceType *stop = s + width;                                            \
		while ( s != stop) { *d++ = (DestType)*s++; *d++ = 0; }                  \
		src = (SourceType*)(((Byte*)src) + srcLine);                             \
		dst = (DestType*)(((Byte*)dst) + dstLine);                               \
	}                                                                           \
	memcpy( dstPal, map_RGB_gray, 256 * sizeof( RGBColor));                     \
}

#define macro_asis_revcomplex(SourceType,DestType)                       \
void ic_##SourceType##_complex_##DestType( Handle self,                           \
		Byte *dstData, PRGBColor dstPal, int dstType, int * dstPalSize, Bool palSize_only)         \
{                                                                              \
	SourceType *src = (SourceType*) var->data;                                   \
	DestType *dst = (DestType*) dstData;                                        \
	int y;                                                                      \
	int  width = var->w;                                                         \
	int srcLine = LINE_SIZE(width,var->type);                                   \
	int dstLine = LINE_SIZE(width,dstType);                                      \
	for ( y = 0; y < var->h; y++)                                                \
	{                                                                           \
		SourceType *s = src;                                                     \
		DestType *d = dst;                                                       \
		SourceType *stop = s + width*2;                                          \
		while ( s != stop) { *d++ = (DestType)*s++; s++; }                        \
		src = (SourceType*)(((Byte*)src) + srcLine);                             \
		dst = (DestType*)(((Byte*)dst) + dstLine);                               \
	}                                                                           \
	memcpy( dstPal, map_RGB_gray, 256 * sizeof( RGBColor));                     \
}

#define macro_asis_revcomplex_toint(SourceType,DestType)                       \
void ic_##SourceType##_complex_##DestType( Handle self,                           \
		Byte *dstData, PRGBColor dstPal, int dstType, int * dstPalSize, Bool palSize_only)         \
{                                                                              \
	SourceType *src = (SourceType*) var->data;                                   \
	DestType *dst = (DestType*) dstData;                                        \
	int y;                                                                      \
	int  width = var->w;                                                         \
	int srcLine = LINE_SIZE(width,var->type);                                   \
	int dstLine = LINE_SIZE(width,dstType);                                      \
	for ( y = 0; y < var->h; y++)                                                \
	{                                                                           \
		SourceType *s = src;                                                     \
		DestType *d = dst;                                                       \
		SourceType *stop = s + width*2;                                          \
		while ( s != stop) { *d++ = (DestType)(*s++ + 0.5); s++; }                \
		src = (SourceType*)(((Byte*)src) + srcLine);                            \
		dst = (DestType*)(((Byte*)dst) + dstLine);                               \
	}                                                                           \
	memcpy( dstPal, map_RGB_gray, 256 * sizeof( RGBColor));                     \
}

#define macro_int_int(SourceType,MidType,DestType)                             \
void rs_##SourceType##_##DestType( Handle self,                                \
	Byte * dstData, int dstType,                                              \
	double srcLo, double srcHi, double dstLo, double dstHi)                   \
{                                                                              \
	SourceType *src = (SourceType*) var->data;                                   \
	DestType *dst = (DestType*) dstData;                                        \
	int y;                                                                      \
	MidType aNumerator      = dstHi - dstLo;                                       \
	MidType bNumerator      = dstLo * srcHi - dstHi * srcLo;                       \
	MidType denominator     = srcHi - srcLo;                                       \
	int  width = var->w;                                                         \
	int srcLine = LINE_SIZE(width,var->type);                                   \
	int dstLine = LINE_SIZE(width,dstType);                                      \
	if ( denominator == 0 || dstHi == dstLo)                                    \
	{                                                                           \
		DestType v = (dstLo<minimum_##DestType##Value) ? minimum_##DestType##Value : \
			((dstLo>maximum_##DestType##Value) ? maximum_##DestType##Value : dstLo); \
		for ( y = 0; y < var->h; y++)                                             \
		{                                                                        \
			DestType *d = dst;                                                    \
			DestType *stop = d + width;                                           \
			while ( d != stop) *d++=v;                                            \
			dst = (DestType*)(((Byte*)dst) + dstLine);                            \
		}                                                                        \
		return;                                                                  \
	}                                                                           \
	for ( y = 0; y < var->h; y++)                                                \
	{                                                                           \
		SourceType *s = src;                                                     \
		DestType *d = dst;                                                       \
		SourceType *stop = s + width;                                            \
		MidType v;                                                                  \
		while ( s != stop)                                                       \
		{                                                                        \
			v = (aNumerator**s+++bNumerator)/denominator;                         \
			v = (v<minimum_##DestType##Value) ? minimum_##DestType##Value :       \
				((v>maximum_##DestType##Value) ? maximum_##DestType##Value : v);  \
			*d++ = v;                                                             \
		}                                                                        \
		src = (SourceType*)(((Byte*)src) + srcLine);                             \
		dst = (DestType*)(((Byte*)dst) + dstLine);                               \
	}                                                                           \
}

#define macro_float_float__int_float(SourceType,DestType)                      \
void rs_##SourceType##_##DestType( Handle self,                                \
	Byte * dstData,  int dstType,                                             \
	double srcLo, double srcHi, double dstLo, double dstHi)                   \
{                                                                              \
	SourceType* src = (SourceType*) var->data;                                   \
	DestType* dst = (DestType*) dstData;                                        \
	int y;                                                                      \
	double a, b;                                                                \
	int  width = var->w;                                                         \
	int srcLine = LINE_SIZE(width,var->type);                                   \
	int dstLine = LINE_SIZE(width,dstType);                                      \
	if ( srcHi == srcLo || dstHi == dstLo)                                      \
	{                                                                           \
		for ( y = 0; y < var->h; y++)                                             \
		{                                                                        \
			DestType *d = dst;                                                    \
			DestType *stop = d + width;                                           \
			while ( d != stop) *d++=dstLo;                                        \
			dst = (DestType*)(((Byte*)dst) + dstLine);                            \
		}                                                                        \
		return;                                                                  \
	}                                                                           \
	a = ((double)dstHi - (double)dstLo) / ((double)srcHi - (double)srcLo);      \
	b = ((double)dstLo*(double)srcHi -                                          \
		(double)dstHi*(double)srcLo)/((double)srcHi-(double)srcLo);              \
	for ( y = 0; y < var->h; y++)                                                \
	{                                                                           \
		SourceType* s = src;                                                     \
		DestType* d = dst;                                                       \
		SourceType* stop = s + width;                                            \
		while ( s != stop) *d++=a**s+++b;                                        \
		src = (SourceType*)(((Byte*)src) + srcLine);                             \
		dst = (DestType*)(((Byte*)dst) + dstLine);                               \
	}                                                                           \
}

#define macro_float_int(SourceType,DestType)                                   \
void rs_##SourceType##_##DestType( Handle self,                                \
	Byte * dstData, int dstType,                                              \
	double srcLo, double srcHi, double dstLo, double dstHi)                   \
{                                                                              \
	SourceType* src = (SourceType*) var->data;                                   \
	DestType* dst = (DestType*) dstData;                                        \
	int y;                                                                      \
	double a, b;                                                                \
	int  width = var->w;                                                         \
	int srcLine = LINE_SIZE(width,var->type);                                   \
	int dstLine = LINE_SIZE(width,dstType);                                      \
	if ( srcHi == srcLo || dstHi == dstLo)                                      \
	{                                                                           \
		DestType v = (dstLo<minimum_##DestType##Value) ? minimum_##DestType##Value : \
			((dstLo>maximum_##DestType##Value) ? maximum_##DestType##Value : dstLo) \
			+ 0.5;                                                                \
		for ( y = 0; y < var->h; y++)                                             \
		{                                                                        \
			DestType *d = dst;                                                    \
			DestType *stop = d + width;                                           \
			while ( d != stop) *d++=v;                                            \
			dst = (DestType*)(((Byte*)dst) + dstLine);                            \
		}                                                                        \
		return;                                                                  \
	}                                                                           \
	a = ((double)dstHi - (double)dstLo) / ((double)srcHi - (double)srcLo);      \
	b = ((double)dstLo*(double)srcHi -                                          \
		(double)dstHi*(double)srcLo)/((double)srcHi-(double)srcLo);              \
	for ( y = 0; y < var->h; y++)                                                \
	{                                                                           \
		SourceType* s = src;                                                     \
		DestType* d = dst;                                                       \
		SourceType* stop = s + width;                                            \
		SourceType v;                                                            \
		while ( s != stop)                                                       \
		{                                                                        \
			v = a**s+++b;                                                         \
			v = (v<minimum_##DestType##Value) ? minimum_##DestType##Value :       \
				((v>maximum_##DestType##Value) ? maximum_##DestType##Value : v);  \
			*d++ = v + .5;                                                        \
		}                                                                        \
		src = (SourceType*)(((Byte*)src) + srcLine);                             \
		dst = (DestType*)(((Byte*)dst) + dstLine);                               \
	}                                                                           \
}

macro_int_int( Byte, int, Byte)
macro_int_int( Short, long, Short)
macro_int_int( Long, int64_t, Long)
macro_float_float__int_float( float, float)
macro_float_float__int_float( double, double)

macro_int_int( Short, long, Byte)
macro_int_int( Long, int64_t, Byte)
macro_float_int(float, Byte)
macro_float_int(double, Byte)

macro_asis(Byte,Short)
macro_asis(Byte,Long)
macro_asis(Byte,float)
macro_asis(Byte,double)
macro_asis(Short,Byte)
macro_asis(Short,Long)
macro_asis(Short,float)
macro_asis(Short,double)
macro_asis(Long,Byte)
macro_asis(Long,Short)
macro_asis(Long,float)
macro_asis(Long,double)
macro_asis_toint(float,Byte)
macro_asis_toint(float,Short)
macro_asis_toint(float,Long)
macro_asis(float,double)
macro_asis_toint(double,Byte)
macro_asis_toint(double,Short)
macro_asis_toint(double,Long)
macro_asis(double,float)

macro_asis_complex(Byte,float)
macro_asis_complex(Byte,double)
macro_asis_complex(Short,float)
macro_asis_complex(Short,double)   
macro_asis_complex(Long,float)   
macro_asis_complex(Long,double)   
macro_asis_complex(float,float)   
macro_asis_complex(float,double)   
macro_asis_complex(double,float)   
macro_asis_complex(double,double)   

macro_asis_revcomplex(double,double)
macro_asis_revcomplex(double,float)
macro_asis_revcomplex_toint(double,Long)
macro_asis_revcomplex_toint(double,Short)
macro_asis_revcomplex_toint(double,Byte)
macro_asis_revcomplex(float,double)
macro_asis_revcomplex(float,float)
macro_asis_revcomplex_toint(float,Long)
macro_asis_revcomplex_toint(float,Short)
macro_asis_revcomplex_toint(float,Byte)
	
#ifdef __cplusplus
}
#endif