// PSD_READ.H
// Copyright © Joe Riedel, All Rights Reserved.
// Author: Joe Riedel.
#ifndef __PSD_READ_H__
#define __PSD_READ_H__

#ifdef __cplusplus
extern "C" {
#endif

// All this was taken straight from the psd docs.
// Note: this reader does not read the image resources block.

#define PSD_MODE_BITMAP			0
#define PSD_MODE_GRAYSCALE		1
#define PSD_MODE_INDEXED		2
#define PSD_MODE_RGB			3
#define PSD_MODE_CMYK			4
#define PSD_MODE_MULTICHANNEL	7
#define PSD_MODE_DUOTONE		8
#define PSD_MODE_LAB			9

#define PSD_HEADER_SIG			'8BPS'//('8'+('B'<<8)+('P'<<16)+('S'<<24))

#define LongWord unsigned long
#define Short unsigned short
#define Word unsigned int
#define Byte unsigned char

/* Master file header */

typedef struct PSDHeader_t {
	char Signature[4];	// Should be "8BPS"
	Short Version;		// Should be 1.
	char Reserved1[6];	// Padding 
	Word NumChannels;	// Number of data channels
	LongWord Width;		// Width in pixels
	LongWord Height;	// Height in pixels
	Short BitsPerChannel;	// Bits per pixel (Usually 8)
	Short Mode;			// Type of PSD file
} PSDHeader_t;

typedef struct PSDColorMode_t {
	LongWord Length;			/* Size of the data */
	Byte *ColorModeDataPtr;		/* Color mode data */
} PSDColorMode_t;

typedef struct PSDChannelLengthInfo_t {
	int ChannelID;			/* ID of the channel represented (signed) */
	LongWord Length;			/* Length of the info */
} PSDChannelLengthInfo_t;

typedef struct PSDLayerMaskData_t {
	LongWord Length;			/* Size of the structure (20 or 36) */
	LongWord Top, Left, Bottom, Right;	/* Dimensions of the mask */
	char DefaultColor;			/* Base color index */
	char Flags;					/* Mask flags */
	char Padd[2];				/* Not used */
} PSDLayerMaskData_t;

typedef struct PSDLayerChannelBlendRange_t {
	LongWord Src;		/* Start range */
	LongWord Dst;		/* Dest range */
} PSDLayerChannelBlendRange_t;

typedef struct PSDLayerBlendingRanges_t {
	LongWord Length;						/* Number of ranges present */
	PSDLayerChannelBlendRange_t GrayBlend;	/* Base greyscale blend */
	PSDLayerChannelBlendRange_t	*ChannelBlendRanges;	/* Ranges for each channel */
} PSDLayerBlendingRanges_t;

typedef struct PSDChannelImageData_t {
	int Compression;
	Byte *Data;
} PSDChannelImageData_t;

typedef struct PSDLayerRecord_t {
	int Top, Left, Bottom, Right;
	int NumChannels;
	PSDChannelLengthInfo_t*	ChannelLengthInfoPtr;
	char BlendModeSig[4];
	int BlendModeKey;
	Byte Opacity;
	Byte Clipping;
	Byte Flags;
	Byte Pad1;
	int	ExtraDataSize;
	PSDLayerMaskData_t LayerMaskData;
	PSDLayerBlendingRanges_t LayerBlendingRanges;
	char* Name;
	// Tacked our channel data here.
	PSDChannelImageData_t*	ChannelImageData;
} PSDLayerRecord_t;

typedef struct PSDLayerInfoSection_t {
	int Length;
	int NumLayers;
	PSDLayerRecord_t *LayerRecordsPtr;
} PSDLayerInfoSection_t;

/*****************************************************************
** PUBLICLY USED STRUCTS										**
*****************************************************************/
typedef struct PSDImageLayer_t
{
	char* Name;
	int Top, Left, Bottom, Right;	// Surrounding rect.
	int MaskTop, MaskLeft, MaskBottom, MaskRight;
	int Width, Height;
	int MaskWidth, MaskHeight;
	unsigned char* RGB;
	unsigned char* Alpha;
	unsigned char* Mask;
} PSDImageLayer_t;

typedef struct PSDImage_t
{
	int Width;
	int Height;
	int NumLayers;
	PSDImageLayer_t* Layers;

} PSDImage_t;

#define PSD_OK			0
#define PSD_FAIL		1

void FreePSDImage(PSDImage_t* PSD);

#define PSD_FLAG_RGB	0
#define PSD_FLAG_ALPHA	1
#define PSD_FLAG_MASK	2
#define PSD_FLAG_RGBA	3

typedef struct Image_t
{
	int x, y, width, height;
	int flags;
	unsigned char* data;
} Image_t;

Image_t* ImageNew(int w, int h, int bytes_pp);
void FreeImageData(Image_t* image);
void FreeImageStruct(Image_t* image);

Image_t* PSDMakeImageFromLayer(PSDImageLayer_t* Layer, int flags);

#define PSD_FLAGS_TO_BYTES_PP(flags) ( (flags) == PSD_FLAG_RGB ? 3 : (flags) == PSD_FLAG_ALPHA ? 1 : (flags) == PSD_FLAG_MASK ? 1 : (flags) == PSD_FLAG_RGBA ? 4 : 0 )

#define PSD_BAD_VERSION								1
#define PSD_BAD_HEADER								2
#define PSD_BAD_BLENDMODESIG						3
#define PSD_BAD_LAYERMASKRECORDSIZE					4
#define PSD_BAD_CHANNELNUM							5
#define PSD_BAD_ADJUSTMENTLAYERSIG					6
#define PSD_BAD_LAYERRECORDOVERRUN					7
#define PSD_BAD_UNSUPPORTEDCHANNELDEPTH				8
#define PSD_BAD_BLOCKLENGTH							9
#define PSD_BAD_ALLOCERROR							10
#define PSD_BAD_UNSUPPORTEDCHANNELCOMPRESSION		11
#define PSD_BAD_HEIGHT								12
#define PSD_BAD_WIDTH								13
#define PSD_BAD_RLESCANERROR						14
#define PSD_BAD_SCANLENGTHINCONSISTENCY				15
#define PSD_BAD_MISSINGCHANNEL						16


Word PSDReadFromByteStream(PSDImage_t* Image, const unsigned char* InStream, unsigned char** NewPos);

#ifdef __cplusplus
}
#endif

#endif