#include	"scalelin.h"

#if GE_LITTLE_ENDIAN

	#define	INTEL_SWAP16(value)	value = REVERSEu16(value)
	#define	INTEL_SWAP32(value)	value = REVERSEu32(value)

#else

	#define	INTEL_SWAP16(value)
	#define	INTEL_SWAP32(value)

#endif

//----------------------------------------------------------------------------------------
// Divisor to shift count table
//----------------------------------------------------------------------------------------
static Char	cnt_to_shifts[256] =
{
	0,
	1,
	-1,
	2,
	-1, -1, -1,
	3,
	-1, -1, -1, -1, -1, -1, -1,
	4,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	5,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	6,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	7,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	8
};

//----------------------------------------------------------------------------------------
// Grow a line (1 - 8 bits)
// Function result:		-
// e:									negative destination width = - dw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void grow_line_px1_8(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
										 Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
										 UInt32* src, UInt32* dst)
{
	Int32	 shift_bits;
	UInt32 src_word;
	UInt32 dst_word;

	shift_bits = 32 - bits;	// # of shifts to the right for the first pixel

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;
	src_bit_offset &= 31;
	dst_bit_offset &= 31;

	src_word = *src++;
	INTEL_SWAP32(src_word);
	src_word <<= src_bit_offset;
	dst_word	 = *dst;
	INTEL_SWAP32(dst_word);
	dst_word >>= (32 - dst_bit_offset);

	src_bit_offset -= 32;	// (negative) # of bits that have to be read
	dst_bit_offset -= 32;	// (negative) # of bits that have to be written

	while (cnt >= 0)
	{
		dst_word <<= bits;
		dst_word	|= src_word >> shift_bits;	// insert source pixel
		dst_bit_offset += bits;								// next destination bit offset

		if (dst_bit_offset == 0)							// destination word full?
		{
			INTEL_SWAP32(dst_word);
			*dst++ = dst_word;
			dst_bit_offset = -32;
		}

		e += sw;										// add source width to the discriminator

		if (e >= 0)									// read the next source pixel?
		{
			e -= dw;									// subtract destination width from the discriminator

			src_word <<= bits;				// next source pixel
			src_bit_offset += bits;		// next source bit offset

			if (src_bit_offset == 0)	// source word empty?
			{
				src_word = *src++;
				INTEL_SWAP32(src_word);
				src_bit_offset = -32;
			}
		}
		cnt--;
	}

	if (dst_bit_offset > -32)	// write the last destination word?
	{
		UInt32 mask;

		dst_bit_offset = -dst_bit_offset;
		dst_word <<= dst_bit_offset;
		mask = (1L << dst_bit_offset) - 1;
		INTEL_SWAP32(dst_word);
		INTEL_SWAP32(mask);
		dst_word |= *dst & mask;
		*dst++ = dst_word;
	}
}

//----------------------------------------------------------------------------------------
// Grow a line (16 bits)
// Function result:		-
// e:									negative destination width = - dw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void grow_line_px16(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
										Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
										UInt16* src, UInt16* dst)
{
	UInt32 src_word;

	(void) bits;

	src = (UInt16*) ((UChar*) src + (src_bit_offset >> 3));
	dst = (UInt16*) ((UChar*) dst + (dst_bit_offset >> 3));

	src_word = *src++;

	while (cnt >= 0)
	{
		*dst++ = src_word;

		e += sw;

		if (e >= 0)
		{
			e -= dw;
			src_word = *src++;
		}
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Grow a line (24 bits)
// Function result:		-
// e:									negative destination width = - dw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void grow_line_px24(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
										Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
										UChar* src, UChar* dst)
{
	UChar	src_c0;
	UChar	src_c1;
	UChar	src_c2;

	(void) bits;

	src += src_bit_offset >> 3;
	dst += dst_bit_offset >> 3;

	src_c0 = *src++;
	src_c1 = *src++;
	src_c2 = *src++;

	while (cnt >= 0)
	{
		*dst++ = src_c0;
		*dst++ = src_c1;
		*dst++ = src_c2;

		e += sw;

		if (e >= 0)
		{
			e -= dw;
			src_c0 = *src++;
			src_c1 = *src++;
			src_c2 = *src++;
		}
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Grow a line (32 bits)
// Function result:		-
// e:									negative destination width = - dw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void grow_line_px32(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
										Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
										UInt32* src, UInt32* dst)
{
	UInt32 src_word;

	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;
	src_word = *src++;

	while (cnt >= 0)
	{
		*dst++ = src_word;

		e += sw;

		if (e >= 0)
		{
			e -= dw;
			src_word = *src++;
		}
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Grow a line (48 bits)
// Function result:		-
// e:									negative destination width = - dw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void grow_line_px48(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
										Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
										PIX_W* src, PIX_W* dst)
{
	PIX_W	src_c0;
	PIX_W	src_c1;
	PIX_W	src_c2;

	(void) bits;

	src += src_bit_offset >> 4;
	dst += dst_bit_offset >> 4;

	src_c0 = *src++;
	src_c1 = *src++;
	src_c2 = *src++;

	while (cnt >= 0)
	{
		*dst++ = src_c0;
		*dst++ = src_c1;
		*dst++ = src_c2;

		e += sw;

		if (e >= 0)
		{
			e -= dw;
			src_c0 = *src++;
			src_c1 = *src++;
			src_c2 = *src++;
		}
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Grow a line (64 bits)
// Function result:		-
// e:									negative destination width = - dw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void grow_line_px64(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
										Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
										UInt32* src, UInt32* dst)
{
	UInt32 src_word0;
	UInt32 src_word1;

	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;
	src_word0 = *src++;
	src_word1 = *src++;

	while (cnt >= 0)
	{
		*dst++ = src_word0;
		*dst++ = src_word1;

		e += sw;

		if (e >= 0)
		{
			e -= dw;
			src_word0 = *src++;
			src_word1 = *src++;
		}
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Grow a line (96 bits)
// Function result:		-
// e:									negative destination width = - dw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void grow_line_px96(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
										Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
										PIX_F* src, PIX_F* dst)
{
	PIX_F	src_c0;
	PIX_F	src_c1;
	PIX_F	src_c2;

	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	src_c0 = *src++;
	src_c1 = *src++;
	src_c2 = *src++;

	while (cnt >= 0)
	{
		*dst++ = src_c0;
		*dst++ = src_c1;
		*dst++ = src_c2;

		e += sw;

		if (e >= 0)
		{
			e -= dw;
			src_c0 = *src++;
			src_c1 = *src++;
			src_c2 = *src++;
		}
		cnt--;
	}
}


//----------------------------------------------------------------------------------------
// Grow a line (128 bits)
// Function result:		-
// e:									negative destination width = - dw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void grow_line_px128(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
										 Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
										 PIX_F* src, PIX_F* dst)
{
	PIX_F	src_word0;
	PIX_F	src_word1;
	PIX_F	src_word2;
	PIX_F	src_word3;

	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;
	src_word0 = *src++;
	src_word1 = *src++;
	src_word2 = *src++;
	src_word3 = *src++;

	while (cnt >= 0)
	{
		*dst++ = src_word0;
		*dst++ = src_word1;
		*dst++ = src_word2;
		*dst++ = src_word3;

		e += sw;

		if (e >= 0)
		{
			e -= dw;
			src_word0 = *src++;
			src_word1 = *src++;
			src_word2 = *src++;
			src_word3 = *src++;
		}
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (1 - 8 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_px1_8(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
											 Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
											 UInt32* src, UInt32* dst)
{
	Int32	 shift_bits;
	UInt32 src_word;
	UInt32 dst_word;

	shift_bits = 32 - bits;	// # of shifts to the right for the first pixel

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;
	src_bit_offset &= 31;
	dst_bit_offset &= 31;

	src_word = *src++;
	INTEL_SWAP32(src_word);
	src_word <<= src_bit_offset;
	dst_word	 = *dst;
	INTEL_SWAP32(dst_word);
	dst_word >>= (32 - dst_bit_offset);

	src_bit_offset -= 32;	// (negative) # of bits that have to be read
	dst_bit_offset -= 32;	// (negative) # of bits that have to be written

	while (cnt >= 0)
	{
		UInt32 src_value;

		src_value = 0;

		while (e < 0)	// read another source pixel?
		{
			UInt32 tmp;

			if (src_bit_offset == 0)
			{
				src_word = *src++;
				INTEL_SWAP32(src_word);
				src_bit_offset = -32;
			}

			tmp =	src_word >> shift_bits;	// source pixel
			if (tmp > src_value)
				src_value = tmp;

			src_word <<= bits;
			src_bit_offset += bits;

			e += dw;
		}

		dst_word <<= bits;
		dst_word	|= src_value;	// insert source pixel
		dst_bit_offset += bits;

		if (dst_bit_offset == 0)
		{
			INTEL_SWAP32(dst_word);
			*dst++ = dst_word;
			dst_bit_offset = -32;
		}

		e -= sw;

		cnt--;
	}

	if (dst_bit_offset > -32)
	{
		UInt32 mask;

		dst_bit_offset = -dst_bit_offset;
		dst_word <<= dst_bit_offset;
		mask = (1L << dst_bit_offset) - 1;
		INTEL_SWAP32(dst_word);
		INTEL_SWAP32(mask);
		dst_word |= *dst & mask;
		*dst++ = dst_word;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (8 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_A8(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
										Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
										UChar* src, UChar* dst)
{
	(void) bits;

	src += src_bit_offset >> 3;
	dst += dst_bit_offset >> 3;

	while (cnt >= 0)
	{
		Int32	 shifts;
		Int32	 src_cnt;
		UInt32 src_gray;

		src_cnt	 = 0;
		src_gray = 0;

		while (e < 0)
		{
			src_gray += *src++;
			src_cnt++;

			e += dw;
		}

		shifts = -1;
		if (src_cnt < 256)
			shifts = cnt_to_shifts[src_cnt - 1];

		if (shifts >= 0)	// can we shift?
			src_gray >>= shifts;
		else							// we have to divide
			src_gray /= src_cnt;

		*dst++ = (UChar) src_gray;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (16 bits, 3 components ˆ 5 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_xABC15(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
												Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
												UInt16* src, UInt16* dst)
{
	(void) bits;

	src += src_bit_offset >> 4;
	dst += dst_bit_offset >> 4;

	while (cnt >= 0)
	{
		UInt32 src_word;
		UInt32 dst_word;
		Int32	 shifts;
		Int32	 src_cnt;
		UInt32 src_red;
		UInt32 src_green;
		UInt32 src_blue;

		src_cnt = 0;
		src_red = 0;
		src_green = 0;
		src_blue	= 0;

		while (e < 0)
		{
			src_word = *src++;
			INTEL_SWAP16(src_word);

			src_cnt++;
			src_red += (src_word >> 10) & 0x001fL;
			src_green += (src_word >> 5) & 0x001fL;
			src_blue	+= src_word & 0x001fL;

			e += dw;
		}

		shifts = -1;
		if (src_cnt < 256)
			shifts = cnt_to_shifts[src_cnt - 1];

		if (shifts >= 0)
		{
			src_red >>= shifts;
			src_green >>= shifts;
			src_blue	>>= shifts;
		}
		else
		{
			src_red /= src_cnt;
			src_green /= src_cnt;
			src_blue	/= src_cnt;
		}

		dst_word = (src_red << 10) | (src_green << 5) | src_blue;
		INTEL_SWAP16(dst_word);
		*dst++ = (UInt16) dst_word;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (16 bits, 2 independent components ˆ 8 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_AB16(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
											Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
											UInt16* src, UInt16* dst)
{
	(void) bits;

	src += src_bit_offset >> 4;
	dst += dst_bit_offset >> 4;

	while (cnt >= 0)
	{
		UInt32 src_word;
		UInt32 dst_word;
		Int32	 shifts;
		Int32	 src_cnt;
		UInt32 src_a;
		UInt32 src_b;

		src_cnt = 0;
		src_a = 0;
		src_b = 0;

		while (e < 0)
		{
			src_word = *src++;
			INTEL_SWAP16(src_word);

			src_cnt++;
			src_a += (src_word >> 8) & 0x00ffL;
			src_b += src_word & 0x00ffL;

			e += dw;
		}

		shifts = -1;
		if (src_cnt < 256)
			shifts = cnt_to_shifts[src_cnt - 1];

		if (shifts >= 0)
		{
			src_a >>= shifts;
			src_b >>= shifts;
		}
		else
		{
			src_a /= src_cnt;
			src_b /= src_cnt;
		}

		dst_word = (src_a << 8) | src_b;
		INTEL_SWAP16(dst_word);
		*dst++ = (UInt16) dst_word;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (16 bits, 2 components ˆ 8 bits, first one is alpha)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_AG16(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
											Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
											UInt16* src, UInt16* dst)
{
	(void) bits;

	src += src_bit_offset >> 4;
	dst += dst_bit_offset >> 4;

	while (cnt >= 0)
	{
		UInt32 src_word;
		UInt32 dst_word;
		Int32	 src_cnt;
		UInt32 src_alpha;
		UInt32 src_gray;

		src_cnt = 0;
		src_alpha = 0;
		src_gray	= 0;

		while (e < 0)
		{
			UInt32 alpha;

			src_word = *src++;
			INTEL_SWAP16(src_word);

			src_cnt++;
			alpha = (src_word >> 8) & 0x00ffL;
			src_alpha += alpha;
			src_gray	+= (src_word & 0x00ffL) * alpha;

			e += dw;
		}

		dst_word = (src_alpha / src_cnt) << 8;

		if (src_alpha)
		{
			src_gray /= src_alpha;
			dst_word |= src_gray;
		}

		INTEL_SWAP16(dst_word);
		*dst++ = (UInt16) dst_word;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (24 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_ABC24(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
											 Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
											 UChar* src, UChar* dst)
{
	(void) bits;

	src += src_bit_offset >> 3;
	dst += dst_bit_offset >> 3;

	while (cnt >= 0)
	{
		Int32	 shifts;
		Int32	 src_cnt;
		UInt32 src_red;
		UInt32 src_green;
		UInt32 src_blue;

		src_cnt = 0;
		src_red = 0;
		src_green = 0;
		src_blue	= 0;

		while (e < 0)
		{
			src_cnt++;
			src_red += *src++;
			src_green += *src++;
			src_blue	+= *src++;

			e += dw;
		}

		shifts = -1;
		if (src_cnt < 256)
			shifts = cnt_to_shifts[src_cnt - 1];

		if (shifts >= 0)
		{
			src_red >>= shifts;
			src_green >>= shifts;
			src_blue	>>= shifts;
		}
		else
		{
			src_red /= src_cnt;
			src_green /= src_cnt;
			src_blue	/= src_cnt;
		}

		*dst++ = src_red;
		*dst++ = src_green;
		*dst++ = src_blue;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (32 bits, 3 components ˆ 8 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_xABC24(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
												Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
												UInt32* src, UInt32* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		UInt32 src_word;
		UInt32 dst_word;
		Int32	 shifts;
		Int32	 src_cnt;
		UInt32 src_red;
		UInt32 src_green;
		UInt32 src_blue;

		src_cnt = 0;
		src_red = 0;
		src_green = 0;
		src_blue	= 0;

		while (e < 0)
		{
			src_word = *src++;
			INTEL_SWAP32(src_word);

			src_cnt++;
			src_red += (src_word >> 16) & 0x000000ffL;
			src_green += (src_word >> 8) & 0x000000ffL;
			src_blue	+= src_word & 0x000000ffL;

			e += dw;
		}

		shifts = -1;
		if (src_cnt < 256)
			shifts = cnt_to_shifts[src_cnt - 1];

		if (shifts >= 0)
		{
			src_red >>= shifts;
			src_green >>= shifts;
			src_blue	>>= shifts;
		}
		else
		{
			src_red /= src_cnt;
			src_green /= src_cnt;
			src_blue	/= src_cnt;
		}

		dst_word = (src_red << 16) | (src_green << 8) | src_blue;
		INTEL_SWAP32(dst_word);
		*dst++ = dst_word;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (32 bits, 4 independent components ˆ 8 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_ABCD32(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
												Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
												UInt32* src, UInt32* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		UInt32 src_word;
		UInt32 dst_word;
		Int32	 shifts;
		Int32	 src_cnt;
		UInt32 src_a;
		UInt32 src_b;
		UInt32 src_c;
		UInt32 src_d;

		src_cnt = 0;
		src_a = 0;
		src_b = 0;
		src_c = 0;
		src_d = 0;

		while (e < 0)
		{
			src_word = *src++;
			INTEL_SWAP32(src_word);

			src_cnt++;
			src_a += (src_word >> 24) & 0x000000ffL;
			src_b += (src_word >> 16) & 0x000000ffL;
			src_c += (src_word >> 8) & 0x000000ffL;
			src_d += src_word & 0x000000ffL;

			e += dw;
		}

		shifts = -1;
		if (src_cnt < 256)
			shifts = cnt_to_shifts[src_cnt - 1];

		if (shifts >= 0)
		{
			src_a >>= shifts;
			src_b >>= shifts;
			src_c >>= shifts;
			src_d >>= shifts;
		}
		else
		{
			src_a /= src_cnt;
			src_b /= src_cnt;
			src_c /= src_cnt;
			src_d /= src_cnt;
		}

		dst_word = (src_a << 24) | (src_b << 16) | (src_c << 8) | src_d;
		INTEL_SWAP32(dst_word);
		*dst++ = dst_word;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (32 bits, 4 components ˆ 8 bits, first one is alpha)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_ARGB32(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
												Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
												UInt32* src, UInt32* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		UInt32 src_word;
		UInt32 dst_word;
		Int32	 src_cnt;
		UInt32 src_alpha;
		UInt32 src_red;
		UInt32 src_green;
		UInt32 src_blue;

		src_cnt = 0;
		src_alpha = 0;
		src_red = 0;
		src_green = 0;
		src_blue	= 0;

		while (e < 0)
		{
			UInt32 alpha;

			src_word = *src++;
			INTEL_SWAP32(src_word);

			src_cnt++;
			alpha = (src_word >> 24) & 0x000000ffL;
			src_alpha += alpha;
			src_red += ((src_word >> 16) & 0x000000ffL) * alpha;
			src_green += ((src_word >> 8) & 0x000000ffL) * alpha;
			src_blue	+= (src_word & 0x000000ffL) * alpha;

			e += dw;
		}

		dst_word = ((src_alpha / src_cnt) << 24);

		if (src_alpha)
		{
			src_red /= src_alpha;
			src_green /= src_alpha;
			src_blue	/= src_alpha;
			dst_word	|= (src_red << 16) | (src_green << 8) | src_blue;
		}

		INTEL_SWAP32(dst_word);
		*dst++ = dst_word;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (32 bits, 2 components ˆ 16 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_AB32(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
											Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
											UInt32* src, UInt32* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		UInt32 src_word;
		UInt32 dst_word;
		Int32	 shifts;
		Int32	 src_cnt;
		UInt32 src_c0;
		UInt32 src_c1;

		src_cnt = 0;
		src_c0	= 0;
		src_c1	= 0;

		while (e < 0)
		{
			src_word = *src++;
			INTEL_SWAP32(src_word);

			src_c0 += (src_word >> 16) & 0x0000ffffL;
			src_c1 += src_word & 0x0000ffffL;
			src_cnt++;

			e += dw;
		}

		shifts = -1;
		if (src_cnt < 256)
			shifts = cnt_to_shifts[src_cnt - 1];

		if (shifts >= 0)
		{
			src_c0 >>= shifts;
			src_c1 >>= shifts;
		}
		else
		{
			src_c0 /= src_cnt;
			src_c1 /= src_cnt;
		}

		dst_word = (src_c0 << 16) | src_c1;
		INTEL_SWAP32(dst_word);
		*dst++ = dst_word;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (64 bits, 2 components ˆ 32 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_AB64(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
											Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
											PIX_F* src, PIX_F* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		Int32	src_cnt;
		PIX_F	src_c0;
		PIX_F	src_c1;
		PIX_F	multiplier;

		src_cnt = 0;
		src_c0	= 0;
		src_c1	= 0;

		while (e < 0)
		{
			src_c0 += *src++;
			src_c1 += *src++;
			src_cnt++;

			e += dw;
		}

		multiplier = 1.0 / src_cnt;
		*dst++ = src_c0 * multiplier;
		*dst++ = src_c1 * multiplier;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (16 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_A16(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
										 Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
										 PIX_W* src, PIX_W* dst)
{
	(void) bits;

	src += src_bit_offset >> 4;
	dst += dst_bit_offset >> 4;

	while (cnt >= 0)
	{
		Int32	 shifts;
		Int32	 src_cnt;
		UInt32 src_gray;

		src_cnt	 = 0;
		src_gray = 0;

		while (e < 0)
		{
			src_gray += *src++;
			src_cnt++;

			e += dw;
		}

		shifts = -1;
		if (src_cnt < 256)
			shifts = cnt_to_shifts[src_cnt - 1];

		if (shifts >= 0)	// can we shift?
			src_gray >>= shifts;
		else							// we have to divide
			src_gray /= src_cnt;

		*dst++ = (PIX_W) src_gray;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (32 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_A32(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
										 Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
										 PIX_F* src, PIX_F* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		Int32	src_cnt;
		PIX_F	src_gray;

		src_cnt	 = 0;
		src_gray = 0;

		while (e < 0)
		{
			src_gray += *src++;
			src_cnt++;

			e += dw;
		}

		*dst++ = src_gray / src_cnt;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (32 bits, 2 components ˆ 16 bits, first one is alpha)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_AG32(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
											Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
											UInt32* src, UInt32* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		UInt32 src_word;
		UInt32 dst_word;
		Int32	 src_cnt;
		UInt32 src_alpha;
		Int64	 src_gray;

		src_cnt = 0;
		src_alpha = 0;
		src_gray	= 0;

		while (e < 0)
		{
			UInt32 alpha;

			src_word = *src++;
			src_cnt++;
#if GE_LITTLE_ENDIAN
			alpha = src_word & 0x0000ffffUL;
			src_gray += ((src_word >> 16) & 0x0000ffffUL) * alpha;
#else
			alpha = (src_word >> 16) & 0x0000ffffUL;
			src_gray += (src_word & 0x0000ffffUL) * alpha;
#endif
			src_alpha += alpha;

			e += dw;
		}

#if GE_LITTLE_ENDIAN
		dst_word = src_alpha / src_cnt;

		if (src_alpha)
			dst_word |= ((UInt32) (src_gray / src_alpha)) << 16;
#else
		dst_word = (src_alpha / src_cnt) << 16;

		if (src_alpha)
			dst_word |= (UInt32) (src_gray / src_alpha);
#endif
		*dst++ = dst_word;

		e -= sw;
		cnt--;
	}
}


//----------------------------------------------------------------------------------------
// Shrink a line (64 bits, 2 components ˆ 32 bits, first one is alpha)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_AG64(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
											Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
											PIX_F* src, PIX_F* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		Int32	src_cnt;
		PIX_F	src_alpha;
		PIX_F	src_gray;

		src_cnt = 0;
		src_alpha = 0;
		src_gray	= 0;

		while (e < 0)
		{
			PIX_F	alpha;

			src_cnt++;
			alpha = *src++;
			src_alpha += alpha;
			src_gray	+= *src++ *alpha;

			e += dw;
		}

		*dst++ = src_alpha / src_cnt;

		if (src_alpha > 0.0)
			src_gray /= src_alpha;
		else
			src_gray = 0;

		*dst++ = src_gray;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (48 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_ABC48(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
											 Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
											 PIX_W* src, PIX_W* dst)
{
	(void) bits;

	src += src_bit_offset >> 4;
	dst += dst_bit_offset >> 4;

	while (cnt >= 0)
	{
		Int32	 shifts;
		Int32	 src_cnt;
		UInt32 src_red;
		UInt32 src_green;
		UInt32 src_blue;

		src_cnt = 0;
		src_red = 0;
		src_green = 0;
		src_blue	= 0;

		while (e < 0)
		{
			src_cnt++;
			src_red += *src++;
			src_green += *src++;
			src_blue	+= *src++;

			e += dw;
		}

		shifts = -1;
		if (src_cnt < 256)
			shifts = cnt_to_shifts[src_cnt - 1];

		if (shifts >= 0)
		{
			src_red >>= shifts;
			src_green >>= shifts;
			src_blue	>>= shifts;
		}
		else
		{
			src_red /= src_cnt;
			src_green /= src_cnt;
			src_blue	/= src_cnt;
		}

		*dst++ = src_red;
		*dst++ = src_green;
		*dst++ = src_blue;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (64 bits, 3 components ˆ 16 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_xABC48(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
												Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
												UInt32* src, UInt32* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		UInt32 src_word;
		UInt32 dst_word;
		Int32	 shifts;
		Int32	 src_cnt;
		UInt32 src_red;
		UInt32 src_green;
		UInt32 src_blue;

		src_cnt = 0;
		src_red = 0;
		src_green = 0;
		src_blue	= 0;

		while (e < 0)
		{
			src_word = *src++;
			INTEL_SWAP32(src_word);

			src_cnt++;
			src_red += src_word & 0x0000ffffL;

			src_word = *src++;
			INTEL_SWAP32(src_word);

			src_green += (src_word >> 16) & 0x0000ffffL;
			src_blue	+= src_word & 0x0000ffffL;

			e += dw;
		}

		shifts = -1;
		if (src_cnt < 256)
			shifts = cnt_to_shifts[src_cnt - 1];

		if (shifts >= 0)
		{
			src_red >>= shifts;
			src_green >>= shifts;
			src_blue	>>= shifts;
		}
		else
		{
			src_red /= src_cnt;
			src_green /= src_cnt;
			src_blue	/= src_cnt;
		}

		dst_word = src_red;
		INTEL_SWAP32(dst_word);
		*dst++ = dst_word;

		dst_word = (src_green << 16) | src_blue;
		INTEL_SWAP32(dst_word);
		*dst++ = dst_word;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (96 bits, 3 components ˆ 32 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_ABC96(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
											 Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
											 PIX_F* src, PIX_F* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		Int32	src_cnt;
		PIX_F	src_red;
		PIX_F	src_green;
		PIX_F	src_blue;
		PIX_F	multiplier;

		src_cnt = 0;
		src_red = 0;
		src_green = 0;
		src_blue	= 0;

		while (e < 0)
		{
			src_red += *src++;
			src_green += *src++;
			src_blue	+= *src++;
			src_cnt++;

			e += dw;
		}

		multiplier = 1.0 / src_cnt;
		*dst++ = src_red * multiplier;
		*dst++ = src_green * multiplier;
		*dst++ = src_blue * multiplier;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (128 bits, 3 components ˆ 32 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_xABC96(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
												Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
												PIX_F* src, PIX_F* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		Int32	src_cnt;
		PIX_F	src_red;
		PIX_F	src_green;
		PIX_F	src_blue;
		PIX_F	multiplier;

		src_cnt = 0;
		src_red = 0;
		src_green = 0;
		src_blue	= 0;

		while (e < 0)
		{
			src++;
			src_red += *src++;
			src_green += *src++;
			src_blue	+= *src++;
			src_cnt++;

			e += dw;
		}

		multiplier = 1.0 / src_cnt;
		*dst++ = 0;
		*dst++ = src_red * multiplier;
		*dst++ = src_green * multiplier;
		*dst++ = src_blue * multiplier;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (64 bits, 4 independant components ˆ 16 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_ABCD64(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
												Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
												UInt32* src, UInt32* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		UInt32 src_word;
		UInt32 dst_word;
		Int32	 shifts;
		Int32	 src_cnt;
		UInt32 src_c0;
		UInt32 src_c1;
		UInt32 src_c2;
		UInt32 src_c3;

		src_cnt = 0;
		src_c0	= 0;
		src_c1	= 0;
		src_c2	= 0;
		src_c3	= 0;

		while (e < 0)
		{
			src_word = *src++;
			INTEL_SWAP32(src_word);

			src_cnt++;
			src_c0 += (src_word >> 16) & 0x0000ffffL;
			src_c1 += src_word & 0x0000ffffL;

			src_word = *src++;
			INTEL_SWAP32(src_word);

			src_c2 += (src_word >> 16) & 0x0000ffffL;
			src_c3 += src_word & 0x0000ffffL;

			e += dw;
		}

		shifts = -1;
		if (src_cnt < 256)
			shifts = cnt_to_shifts[src_cnt - 1];

		if (shifts >= 0)
		{
			src_c0 >>= shifts;
			src_c1 >>= shifts;
			src_c2 >>= shifts;
			src_c3 >>= shifts;
		}
		else
		{
			src_c0 /= src_cnt;
			src_c1 /= src_cnt;
			src_c2 /= src_cnt;
			src_c3 /= src_cnt;
		}

		dst_word = (src_c0 << 16) | src_c1;
		INTEL_SWAP32(dst_word);
		*dst++ = dst_word;

		dst_word = (src_c2 << 16) | src_c3;
		INTEL_SWAP32(dst_word);
		*dst++ = dst_word;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (128 bits, 4 components ˆ 32 bits)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_ABCD128(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
												 Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
												 PIX_F* src, PIX_F* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		Int32	src_cnt;
		PIX_F	src_c0;
		PIX_F	src_c1;
		PIX_F	src_c2;
		PIX_F	src_c3;
		PIX_F	multiplier;

		src_cnt = 0;
		src_c0	= 0;
		src_c1	= 0;
		src_c2	= 0;
		src_c3	= 0;

		while (e < 0)
		{
			src_c0 += *src++;
			src_c1 += *src++;
			src_c2 += *src++;
			src_c3 += *src++;
			src_cnt++;

			e += dw;
		}

		multiplier = 1.0 / src_cnt;
		*dst++ = src_c0 * multiplier;
		*dst++ = src_c1 * multiplier;
		*dst++ = src_c2 * multiplier;
		*dst++ = src_c3 * multiplier;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (64 bits, 4 components ˆ 16 bits, first one is alpha)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_ARGB64(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
												Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
												UInt32* src, UInt32* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		UInt32 src_word;
		UInt32 dst_word;
		Int32	 src_cnt;
		UInt32 src_alpha;
		Int64	 src_red;
		Int64	 src_green;
		Int64	 src_blue;

		src_cnt = 0;
		src_alpha = 0;
		src_red = 0;
		src_green = 0;
		src_blue	= 0;

		while (e < 0)
		{
			UInt32 alpha;

			src_cnt++;

#if GE_LITTLE_ENDIAN
			src_word = *src++;
			alpha = src_word & 0x0000ffffL;
			src_alpha += alpha;
			src_red += ((src_word >> 16) & 0x0000ffffL) * alpha;

			src_word	 = *src++;
			src_green += (src_word & 0x0000ffffL) * alpha;
			src_blue	+= ((src_word >> 16) & 0x0000ffffL) * alpha;
#else
			src_word = *src++;
			alpha = (src_word >> 16) & 0x0000ffffL;
			src_alpha += alpha;
			src_red += (src_word & 0x0000ffffL) * alpha;

			src_word	 = *src++;
			src_green += ((src_word >> 16) & 0x0000ffffL) * alpha;
			src_blue	+= (src_word & 0x0000ffffL) * alpha;
#endif
			e += dw;
		}

#if GE_LITTLE_ENDIAN
		dst_word = src_alpha / src_cnt;

		if (src_alpha)
		{
			dst_word |= ((UInt32) (src_red / src_alpha)) << 16;
			*dst++ = dst_word;

			dst_word	= (UInt32) (src_green / src_alpha);
			dst_word |= ((UInt32) (src_blue / src_alpha)) << 16;
		}
		else
		{
			*dst++ = dst_word;
			dst_word = 0;
		}
#else
		dst_word = (src_alpha / src_cnt) << 16;

		if (src_alpha)
		{
			dst_word |= (UInt32) (src_red / src_alpha);

			*dst++ = dst_word;

			dst_word	= ((UInt32) (src_green / src_alpha)) << 16;
			dst_word |= (UInt32) (src_blue / src_alpha);
		}
		else
		{
			*dst++ = dst_word;
			dst_word = 0;
		}
#endif
		*dst++ = dst_word;

		e -= sw;
		cnt--;
	}
}

//----------------------------------------------------------------------------------------
// Shrink a line (128 bits, 4 components ˆ 32 bits, first one is alpha)
// Function result:		-
// e:									negative source width = - sw (discriminator start value)
// sw:								source width (error for a step to the next destination pixel)
// dw:								destination width (error for a step to the next source pixel)
// cnt:								number of output pixels - 1
// bits:							bits per pixel
// src_bit_offset:		number of unused (left) bits in the first source word
// dst_bit_offset:		number of unused (left) bits in the first destination word
// src:								source address
// dst:								destination address
//----------------------------------------------------------------------------------------
void shrink_line_ARGB128(Int32 e, Int32 sw, Int32 dw, Int32 cnt,
												 Int32 bits, Int32 src_bit_offset, Int32 dst_bit_offset,
												 PIX_F* src, PIX_F* dst)
{
	(void) bits;

	src += src_bit_offset >> 5;
	dst += dst_bit_offset >> 5;

	while (cnt >= 0)
	{
		Int32	src_cnt;
		PIX_F	src_alpha;
		PIX_F	src_red;
		PIX_F	src_green;
		PIX_F	src_blue;
		PIX_F	multiplier;

		src_cnt = 0;
		src_alpha = 0;
		src_red = 0;
		src_green = 0;
		src_blue	= 0;

		while (e < 0)
		{
			PIX_F	alpha;

			src_cnt++;
			alpha = *src++;
			src_alpha += alpha;
			src_red += *src++ *alpha;
			src_green += *src++ *alpha;
			src_blue	+= *src++ *alpha;

			e += dw;
		}

		*dst++ = src_alpha / src_cnt;

		multiplier = 0;
		if (src_alpha > 0.0)
			multiplier = 1.0 / src_alpha;

		*dst++ = src_red * multiplier;
		*dst++ = src_green * multiplier;
		*dst++ = src_blue * multiplier;

		e -= sw;
		cnt--;
	}
}
