/////////////////////////////////////////////////////////////
// CINEMA 4D SDK                                           //
/////////////////////////////////////////////////////////////
// (c) 1989-2004 MAXON Computer GmbH, all rights reserved  //
/////////////////////////////////////////////////////////////

#ifndef	__X4D_COLORS_H
#define	__X4D_COLORS_H

#include "ge_math.h"
#include "x4d_macros.h"																			// defines for platform independency

//----------------------------------------------------------------------------------------
// Colors and color spaces
//----------------------------------------------------------------------------------------

enum																												// Color spaces (color_space)
{
	CSPACE_FLAGS	= 	0xff00,																	// the upper 8 bits are for flags
	CSPACE_MASK		=	0x00ff,																		// the lower bits contain the color space id

	CSPACE_ALPHA_FLAG	= 0x0100,																// alpha flag

	CSPACE_UNKNOWN =	0x0000,

	CSPACE_RGB		=	0x0001,																		// RGB color space
	CSPACE_ARGB		=	0x0101,																		// RGB color space with alpha channel

	CSPACE_HSV		=	0x0002,																		// HSV color space
	CSPACE_HSL		=	0x0003,																		// HSL color space

	CSPACE_CMYK		=	0x0004,																		// CMYK color space

	CSPACE_YCbCr	=	0x0005,																		// YCbCr color space
	CSPACE_AYCbCr	=	0x0105,																		// YCbCr color space with alpha
	CSPACE_YCCK		=	0x0006,																		// YCbCrK color space

	CSPACE_GRAY		=	0x0007,																		// gray space
	CSPACE_AGRAY	=	0x0107,																		// gray with alpha

	CSPACE_PhotoYCC = 0x0008,																	// YCC color space (PhotoCD)
	CSPACE_APhotoYCC = 0x0108,																// YCC color space (PhotoCD) with alpha

	CSPACE_XYZ		= 	0x0010,																	// XYZ color space
	CSPACE_Yxy		= 	0x0011,																	// Yxy color space
	CSPACE_Lab		=	0x0012,																		// L*a*b* color space
	CSPACE_Luv		=	0x0013																		// L*u*v* color space
};

enum																												// number of components in the color table (flags)
{
	CSPACE_1COMPONENT		=	0x0001,
	CSPACE_2COMPONENTS	=	0x0002,
	CSPACE_3COMPONENTS	= 0x0003,
	CSPACE_4COMPONENTS	=	0x0004,
	CSPACE_5COMPONENTS	=	0x0005,
	CSPACE_6COMPONENTS	=	0x0006,
	CSPACE_7COMPONENTS	=	0x0007,
	CSPACE_COMP_MASK		=	0x000f															// mask for number of components
};

struct COLOR_RGB																						// RGB color value
{
	UWORD	reserved;
	UWORD	red;
	UWORD	green;
	UWORD	blue;
};

struct COLOR_ARGB																						// ARGB color value
{
	UWORD	alpha;
	UWORD	red;
	UWORD	green;
	UWORD	blue;
};

struct COLOR_HSL																						// HSL color value
{
	UWORD	reserved;
	UWORD	hue;
	UWORD	saturation;
	UWORD	lightness;
};

struct COLOR_HSV																						// HSV color value
{
	UWORD	reserved;
	UWORD	hue;
	UWORD	saturation;
	UWORD	value;
};

struct COLOR_CMYK																						// CMYK color value
{
	UWORD	cyan;
	UWORD	magenta;
	UWORD	yellow;
	UWORD	black;
};

struct COLOR_YCbCr																					// YCbCr color value
{
	UWORD	reserved;
	UWORD	Y;
	UWORD	Cb;
	UWORD	Cr;
};

struct COLOR_GRAY																						// gray value
{
	UWORD	reserved;
	UWORD	reserved1;																					// set to the same value as gray (compatibility with RGB)
	UWORD	reserved2;																					// set to the same value as gray (compatibility with RGB)
	UWORD	gray;
};

struct COLOR_AGRAY																					// gray with alpha
{
	UWORD	alpha;
	UWORD	reserved1;																					// set to the same value as gray (compatibility with RGB)
	UWORD	reserved2;																					// set to the same value as gray (compatibility with RGB)
	UWORD	gray;
};

struct COLOR_XYZ																						// XYZ color value
{
	UWORD	reserved;
	UWORD	X;
	UWORD	Y;
	UWORD	Z;
};

struct COLOR_Yxy																						// Yxy color value
{
	UWORD	reserved;
	UWORD	Y;
	UWORD	x;
	UWORD	y;
};

struct COLOR_Lab																						// L*a*b* color value
{
	UWORD	reserved;
	UWORD	L;																									// 0 is equivalent to 0.0, 0xffffU is equivalent to 1.0
	UWORD	a;																									// 0 is equivalent to  -1.0, 0x8000 is equivalent to 0.0, 0xffff is equivalent to 1.0
	UWORD	b;																									// 0 is equivalent to  -1.0, 0x8000 is equivalent to 0.0, 0xffff is equivalent to 1.0
};

struct COLOR_Luv																						// L*u*v* color value
{
	UWORD	reserved;
	UWORD	L;																									// 0 is equivalent to 0.0, 0xffffU is equivalent to 1.0
	UWORD	u;																									// 0 is equivalent to -1.0, 0x8000 is equivalent to 0.0, 0xffff is equivalent to 1.0
	UWORD	v;																									// 0 is equivalent to -1.0, 0x8000 is equivalent to 0.0, 0xffff is equivalent to 1.0
};

union COLOR_ENTRY
{
	COLOR_RGB		rgb;
	COLOR_ARGB	argb;
	COLOR_HSV		hsv;
	COLOR_HSL		hsl;
	COLOR_CMYK	cmyk;
	COLOR_YCbCr	ycc;
	COLOR_GRAY	gray;
	COLOR_AGRAY	agray;
	COLOR_XYZ		xyz;
	COLOR_Yxy		yxy;
	COLOR_Lab		lab;
	COLOR_Luv		luv;
};

//----------------------------------------------------------------------------------------
// Pixel formats
//----------------------------------------------------------------------------------------

// number of bits per component
#define	PX_DEPTH_8			0x30000000UL												// channel depth: 8 bits per component
#define	PX_DEPTH_16			0x40000000UL												// channel depth: 16 bits per component
#define	PX_DEPTH_32			0x50000000UL												// channel depth: 24 bits per component

// number of used pixel components
#define	PX_1COMP				0x01000000UL												// pixel consists of one used component: color index
#define	PX_2COMP				0x02000000UL												// pixel consists of two used components, e.g. AG
#define	PX_3COMP				0x03000000UL												// pixel consists of three used components, e.g. RGB, YCbCr, XYZ, Yxy, Lab, Luv
#define	PX_4COMP				0x04000000UL												// pixel consists of four used components, e.g. CMYK, ARGB
#define	PX_5COMP				0x05000000UL												// pixel consists of five used components
#define	PX_6COMP				0x06000000UL												// pixel consists of six used components
#define	PX_7COMP				0x07000000UL												// pixel consists of seven used components

// little endian flags
#define	PX_REVERSED			0x00800000UL												// pixel output is done in reversed byte order
#define	PX_CMPTREVERSED	0x00080000UL												// component order remains unchanged but multi-byte components are stored in reversed byte order

// rotation of pixel components
#define	PX_0LROTATE			0x00400000UL												// unused bits are on the left
#define	PX_1LROTATE			0x00500000UL												// rotate left by 1 component

#define	PX_0RROTATE			0x00000000UL												// unused bits are on the right
#define	PX_1RROTATE			0x00100000UL												// rotate right by one component

#define	PX_xFIRST				0x00400000UL												// xRGB: unused bits are left (PX_0LROTATE)
#define	PX_xLAST				0x00000000UL												// RGBx: unused bits are right (PX_0RROTATE)

// bit packing
#define	PX_FLOAT				0x00030000UL												// components are IEEE floats ...
#define	PX_PACKED				0x00020000UL												// components are packed (default case), one byte for red is followed by one for green and blue - the same goes for the next pixel
#define	PX_PLANES				0x00010000UL												// the bits of each component are stored in seperate planes (order: 0, 1, ..., n)

// number of used bits
#define	PX_USES1				0x00000100UL												// 1 bit of the pixel is used
#define	PX_USES2				0x00000200UL												// 2 bits of the pixel are used
#define	PX_USES3				0x00000300UL												// 3 bits of the pixel are used
#define	PX_USES4				0x00000400UL												// 4 bits of the pixel are used
#define	PX_USES8				0x00000800UL												// 8 bits of the pixel are used
#define	PX_USES15				0x00000f00UL												// 15 bits of the pixel are used
#define	PX_USES16				0x00001000UL												// 16 bits of the pixel are used
#define	PX_USES24				0x00001800UL												// 24 bits of the pixel are used
#define	PX_USES30				0x00001e00UL												// 30 bits of the pixel are used
#define	PX_USES32				0x00002000UL												// 32 bits of the pixel are used
#define	PX_USES48				0x00003000UL												// 48 bits of the pixel are used
#define	PX_USES64				0x00004000UL												// 64 bits of the pixel are used
#define	PX_USES96				0x00006000UL												// 96 bits of the pixel are used
#define	PX_USES128			0x00008000UL												// 128 bits of the pixel are used

// number of bits per pixel
#define	PX_1BIT					0x00000001UL												// pixel consists of 1 bit
#define	PX_2BIT					0x00000002UL												// pixel consists of 2 bits
#define	PX_3BIT					0x00000003UL												// pixel consists of 3 bits
#define	PX_4BIT					0x00000004UL												// pixel consists of 4 bits
#define	PX_8BIT					0x00000008UL												// pixel consists of 8 bits
#define	PX_16BIT				0x00000010UL												// pixel consists of 16 bits
#define	PX_24BIT				0x00000018UL												// pixel consists of 24 bits
#define	PX_32BIT				0x00000020UL												// pixel consists of 32 bits
#define	PX_48BIT				0x00000030UL												// pixel consists of 48 bits
#define	PX_64BIT				0x00000040UL												// pixel consists of 64 bits
#define	PX_96BIT				0x00000060UL												// pixel consists of 96 bits
#define	PX_128BIT				0x00000080UL												// pixel consists of 128 bits

// masks
#define	PX_DEPTH				0x70000000UL												// bits per component (a shift value)
#define	PX_CMPNTS				0x0f000000UL												// number of pixel components
#define	PX_FLAGS				0x00f80000UL												// flags (little endian, component rotation, ...)
#define	PX_RTDIR				0x00400000UL												// rotation direction
#define	PX_RTCMPNTS			0x00300000UL												// number of rotated pixel components
#define	PX_PACKING			0x00030000UL												// bit packing
#define	PX_USED					0x0000ff00UL												// number of used bits
#define	PX_BITS					0x000000ffUL												// total number of bits

//----------------------------------------------------------------------------------------
// easy access macros
//----------------------------------------------------------------------------------------
#define	get_PX_CMPNTBITS( px_format )	1L << ((( px_format ) & PX_DEPTH ) >> 28 )	// bits per component
#define	get_PX_CMPNTS( px_format )		((( px_format ) & PX_CMPNTS ) >> 24 )				// number of components
#define	get_PX_USED( px_format )			((( px_format ) & PX_USED ) >> 8 )					// number of used bits per pixel
#define	get_PX_BITS( px_format )			((( px_format ) & PX_BITS ))								// total number of bits per pixel
#define	get_PX_DEPTH( px_format )			((( px_format ) & PX_DEPTH ))								// 

#define	set_PX_CMPNTS( components )		(( components ) << 24 )
#define	set_PX_USED( used_bits )			(( used_bits ) << 8 )
#define	set_PX_BITS( total_bits )			(( total_bits ))

//----------------------------------------------------------------------------------------
// common Macintosh pixel formats (RGB)
//----------------------------------------------------------------------------------------
#define	PX_MAC1			( PX_DEPTH_8  + PX_1COMP + PX_PACKED + PX_USES1 + PX_1BIT )
#define	PX_MAC4			( PX_DEPTH_8  + PX_1COMP + PX_PACKED + PX_USES4 + PX_4BIT )
#define	PX_MAC8			( PX_DEPTH_8  + PX_1COMP + PX_PACKED + PX_USES8 + PX_8BIT )
#define	PX_MAC15		( PX_DEPTH_8  + PX_3COMP + PX_PACKED + PX_USES15 + PX_16BIT + PX_xFIRST )
#define	PX_MAC32		( PX_DEPTH_8  + PX_3COMP + PX_PACKED + PX_USES24 + PX_32BIT + PX_xFIRST )

//----------------------------------------------------------------------------------------
// common x86 pixel formats (RGB)
//----------------------------------------------------------------------------------------
#define	PX_VGA8			( PX_DEPTH_8  + PX_1COMP + PX_PACKED + PX_USES8 + PX_8BIT )
#define	PX_VGA15		( PX_DEPTH_8  + PX_3COMP + PX_PACKED + PX_USES15 + PX_16BIT + PX_REVERSED + PX_xFIRST )
#define	PX_VGA16		( PX_DEPTH_8  + PX_3COMP + PX_PACKED + PX_USES16 + PX_16BIT + PX_REVERSED )
#define	PX_VGA24		( PX_DEPTH_8  + PX_3COMP + PX_PACKED + PX_USES24 + PX_24BIT + PX_REVERSED )
#define	PX_VGA32		( PX_DEPTH_8  + PX_3COMP + PX_PACKED + PX_USES24 + PX_32BIT + PX_REVERSED + PX_xFIRST )

//----------------------------------------------------------------------------------------
// some RGB pixel formats
//----------------------------------------------------------------------------------------
#define	PX_xRGB15		( PX_DEPTH_8  + PX_3COMP + PX_PACKED + PX_USES15 + PX_16BIT + PX_xFIRST )
#define	PX_RGB24		( PX_DEPTH_8  + PX_3COMP + PX_PACKED + PX_USES24 + PX_24BIT )
#define	PX_xRGB24		( PX_DEPTH_8  + PX_3COMP + PX_PACKED + PX_USES24 + PX_32BIT + PX_xFIRST )
#define	PX_RGBx24		( PX_DEPTH_8  + PX_3COMP + PX_PACKED + PX_USES24 + PX_32BIT + PX_xLAST )

#if GE_LITTLE_ENDIAN																						// multi-byte components with little endian byte order
#define	PX_RGB48		( PX_DEPTH_16 + PX_3COMP + PX_PACKED + PX_USES48 + PX_48BIT + PX_CMPTREVERSED )
#define	PX_xRGB48		( PX_DEPTH_16 + PX_3COMP + PX_PACKED + PX_USES48 + PX_64BIT + PX_xFIRST + PX_CMPTREVERSED )
#define	PX_RGB96		( PX_DEPTH_32 + PX_3COMP + PX_FLOAT + PX_USES96 + PX_96BIT + PX_CMPTREVERSED )
#define	PX_xRGB96		( PX_DEPTH_32 + PX_3COMP + PX_FLOAT + PX_USES96 + PX_128BIT + PX_xFIRST + PX_CMPTREVERSED )
#else																												// multi-byte components with big endian byte order
#define	PX_RGB48		( PX_DEPTH_16 + PX_3COMP + PX_PACKED + PX_USES48 + PX_48BIT )
#define	PX_xRGB48		( PX_DEPTH_16 + PX_3COMP + PX_PACKED + PX_USES48 + PX_64BIT + PX_xFIRST )
#define	PX_RGB96		( PX_DEPTH_32 + PX_3COMP + PX_FLOAT + PX_USES96 + PX_96BIT )
#define	PX_xRGB96		( PX_DEPTH_32 + PX_3COMP + PX_FLOAT + PX_USES96 + PX_128BIT + PX_xFIRST )
#endif

//----------------------------------------------------------------------------------------
// pixel formats for RGB with alpha
//----------------------------------------------------------------------------------------
#define	PX_ARGB32		( PX_DEPTH_8  + PX_4COMP + PX_PACKED + PX_USES32 + PX_32BIT )
#define	PX_RGBA32		( PX_DEPTH_8  + PX_4COMP + PX_PACKED + PX_USES32 + PX_32BIT + PX_1LROTATE )	// ARGB rotated left by one component

#if GE_LITTLE_ENDIAN																						// multi-byte components with little endian byte order
#define	PX_ARGB64		( PX_DEPTH_16 + PX_4COMP + PX_PACKED + PX_USES64 + PX_64BIT + PX_CMPTREVERSED )
#define	PX_ARGB128	( PX_DEPTH_32 + PX_4COMP + PX_FLOAT + PX_USES128+ PX_128BIT + PX_CMPTREVERSED )
#define	PX_RGBA64		( PX_DEPTH_16 + PX_4COMP + PX_PACKED + PX_USES64 + PX_64BIT + PX_1LROTATE + PX_CMPTREVERSED )
#define	PX_RGBA128	( PX_DEPTH_32 + PX_4COMP + PX_FLOAT + PX_USES128+ PX_128BIT + PX_1LROTATE + PX_CMPTREVERSED )
#else																												// multi-byte components with big endian byte order
#define	PX_ARGB64		( PX_DEPTH_16 + PX_4COMP + PX_PACKED + PX_USES64 + PX_64BIT )
#define	PX_ARGB128	( PX_DEPTH_32 + PX_4COMP + PX_FLOAT + PX_USES128+ PX_128BIT )
#define	PX_RGBA64		( PX_DEPTH_16 + PX_4COMP + PX_PACKED + PX_USES64 + PX_64BIT + PX_1LROTATE )
#define	PX_RGBA128	( PX_DEPTH_32 + PX_4COMP + PX_FLOAT + PX_USES128+ PX_128BIT + PX_1LROTATE )
#endif

//----------------------------------------------------------------------------------------
// pixel formats for gray
//----------------------------------------------------------------------------------------
#define	PX_GRAY8		( PX_DEPTH_8  + PX_1COMP + PX_PACKED + PX_USES8 + PX_8BIT )

#if GE_LITTLE_ENDIAN																						// multi-byte components with little endian byte order
#define	PX_GRAY16		( PX_DEPTH_16 + PX_1COMP + PX_PACKED + PX_USES16 + PX_16BIT )
#define	PX_GRAY32		( PX_DEPTH_32 + PX_1COMP + PX_FLOAT + PX_USES32 + PX_32BIT )
#else																												// multi-byte components with big endian byte order
#define	PX_GRAY16		( PX_DEPTH_16 + PX_1COMP + PX_PACKED + PX_USES16 + PX_16BIT )
#define	PX_GRAY32		( PX_DEPTH_32 + PX_1COMP + PX_FLOAT + PX_USES32 + PX_32BIT )
#endif

//----------------------------------------------------------------------------------------
// pixel formats for gray with alpha
//----------------------------------------------------------------------------------------
#define	PX_AGRAY16	( PX_DEPTH_8  + PX_2COMP + PX_PACKED + PX_USES16 + PX_16BIT )
#define	PX_GRAYA16	( PX_DEPTH_8  + PX_2COMP + PX_PACKED + PX_USES16 + PX_16BIT + PX_1LROTATE )	// AGRAY rotated left by one component

#if GE_LITTLE_ENDIAN																						// multi-byte components with little endian byte order
#define	PX_AGRAY32	( PX_DEPTH_16 + PX_2COMP + PX_PACKED + PX_USES32 + PX_32BIT + PX_CMPTREVERSED )
#define	PX_AGRAY64	( PX_DEPTH_32 + PX_2COMP + PX_FLOAT + PX_USES64 + PX_64BIT + PX_CMPTREVERSED )
#define	PX_GRAYA32	( PX_DEPTH_16 + PX_2COMP + PX_PACKED + PX_USES32 + PX_32BIT + PX_1LROTATE + PX_CMPTREVERSED )
#define	PX_GRAYA64	( PX_DEPTH_32 + PX_2COMP + PX_FLOAT + PX_USES64 + PX_64BIT + PX_1LROTATE + PX_CMPTREVERSED )
#else																												// multi-byte components with big endian byte order
#define	PX_AGRAY32	( PX_DEPTH_16 + PX_2COMP + PX_PACKED + PX_USES32 + PX_32BIT )
#define	PX_AGRAY64	( PX_DEPTH_32 + PX_2COMP + PX_FLOAT + PX_USES64 + PX_64BIT )
#define	PX_GRAYA32	( PX_DEPTH_16 + PX_2COMP + PX_PACKED + PX_USES32 + PX_32BIT + PX_1LROTATE )
#define	PX_GRAYA64	( PX_DEPTH_32 + PX_2COMP + PX_FLOAT + PX_USES64 + PX_64BIT + PX_1LROTATE )
#endif
#endif
