// PSD_READ.C
// Copyright © 2000 Joe Riedel, All Rights Reserved.
// Author: Joe Riedel.
#include <stdlib.h>
#include <string.h>
#include "psd_read.h"

#define AllocAPointer(size) (malloc(size))
#define DeallocAPointer(ptr) (free(ptr))

#ifdef _WIN32

#define LoadMotoShort( num ) (short)( ((((unsigned)(num))>>8)&0xff) + (((num)<<8)&0xff00) )
#define LoadMotoShortPtr( ptr ) (short)( LoadMotoShort( *((unsigned short *)(ptr)) ) )

#define LoadMotoLong( num )  ( (((unsigned)(num))>>24)+(((num)>>8)&0xff00)+(((num)&0xff00)<<8)+((num)<<24) )
#define LoadMotoLongPtr( ptr ) ( LoadMotoLong( *((unsigned int *)(ptr))) )

#elif macintosh

#define LoadMotoShort( num ) (num)
#define LoadMotoShortPtr( ptr ) ( *(ptr) )

#define LoadMotoLong( num ) ( num )
#define LoadMotoLongPtr( ptr ) ( *(ptr) )

#endif

#define NonFatal( msg )

void* AllocAPointerClear( int size )
{
	void* ptr = AllocAPointer( size );
	if( ptr ) {
		memset( ptr, 0, size );
	}
	return ptr;
}

#define FastMemSet memset
#define FastMemCpy memcpy
#define PSDImageDestroy FreePSDImage
#define FASTCALL

static const char PSDFileHeader[] = "8BPS";		/* Main header for a PSD file */

/**********************************

	Extract the header of a PSD file

**********************************/

static const Byte *PSDReadHeader(PSDHeader_t* Header,const Byte *Stream)
{
	const char *Msg;
	
	FastMemSet(Header,0,sizeof(PSDHeader_t));		/* Init the buffer */
	
	((LongWord *)&Header->Signature[0])[0] = ((LongWord *)Stream)[0];	/* Copy 4 bytes */
	Header->Version = LoadMotoShortPtr((Short*)(Stream+4));
	Header->NumChannels = LoadMotoShortPtr((Short*)(Stream+12));
	Header->Height = LoadMotoLongPtr((LongWord*)(Stream+14));
	Header->Width = LoadMotoLongPtr((LongWord*)(Stream+18));
	Header->BitsPerChannel = LoadMotoShortPtr((Short*)(Stream+22));
	Header->Mode = LoadMotoShortPtr((Short*)(Stream+24));
	
	/* Now check the header for validity */
	
	if (memcmp(Header->Signature,PSDFileHeader,4)) {					/* String match? */
		Msg = "PSD Head is bad";
	} else if (Header->Version != 1) {
		Msg = "PSD Version is not 1";
	} else if (Header->BitsPerChannel != 8) {
		Msg = "PSD is not 8 bits per channel";
	} else {
		return Stream+26;
	}
	NonFatal(Msg);
	return 0;
}

/**********************************

	Skip past the color data structure

**********************************/

static const Byte *PSDSkipColorData(const Byte *Stream)
{
	LongWord Size;
	
	Size = LoadMotoLongPtr((LongWord*)Stream);	/* Get the size of this chunk */
	return &Stream[Size+4];
}

/**********************************

	Skip past the image resource data structure

**********************************/

static const Byte * PSDSkipImageResources(const Byte *Stream)
{
	LongWord Size;
	
	Size = LoadMotoLongPtr((LongWord*)Stream);	/* Get the size of this chunk */
	return &Stream[Size+4];
}

/**********************************

	Skip past the image resource data structure

**********************************/

static const Byte *PSDReadChannelLengthInfo(PSDChannelLengthInfo_t* ChannelInfo,const Byte *Stream)
{
	ChannelInfo->ChannelID = LoadMotoShortPtr((short*)Stream);
	ChannelInfo->Length = LoadMotoLongPtr((LongWord*)(Stream+2));
	return Stream+6;
}

/**********************************

	Parse the mask range data

**********************************/

static const Byte *PSDReadLayerMaskData(PSDLayerMaskData_t* LayerMask,const Byte *Stream)
{
	LongWord Length;
	
	FastMemSet(LayerMask,0,sizeof(PSDLayerMaskData_t));
	
	Length = LoadMotoLongPtr((LongWord*)Stream);
	if (!Length) {
		return Stream+4;
	}
	LayerMask->Length = Length;
	// Load other fields.
	if (Length != 36 && Length != 20) {
		NonFatal("PSD Bad layer mask record size");
		return 0;
	}
	LayerMask->Top = LoadMotoLongPtr((LongWord*)(Stream+4));
	LayerMask->Left = LoadMotoLongPtr((LongWord*)(Stream+8));
	LayerMask->Bottom = LoadMotoLongPtr((LongWord*)(Stream+12));
	LayerMask->Right = LoadMotoLongPtr((LongWord*)(Stream+16));
	LayerMask->DefaultColor = Stream[20];
	LayerMask->Flags = Stream[21];
	return Stream+Length+4;
}

/**********************************

	Extract a pascal string from the data stream

**********************************/

static const Byte *PSDReadPascalString(char** StringPtr,const Byte *Stream)
{
	char* String;
	Word Length;
	
	Length = Stream[0]+1;					/* Get the buffer length */
	String = (char*)AllocAPointer(Length);
	StringPtr[0] = String;					/* Return the pointer */
	if (!String) {
		return 0;							/* Crap */
	}
	//PStr2CStr(String,(const char *)Stream);	/* Convert to "C" string */
	strncpy( String, (const char*)&Stream[1], Length-1);
	String[Length-1] = 0;
	
	Stream+=Length;							/* Parse past the string */
	return Stream;							/* Return the new index */
}

/**********************************

	Extract the blending ranges for this layer

**********************************/

static const Byte *PSDReadLayerBlendingRanges(PSDLayerBlendingRanges_t* BlendRanges, PSDLayerRecord_t* LayerRecord,const Byte* Stream)
{
	int i;
	Word NumChannels;
	PSDLayerChannelBlendRange_t *DestPtr;
	
	FastMemSet(BlendRanges,0,sizeof(PSDLayerBlendingRanges_t));		/* Init my structure */
	NumChannels = 0;			/* Init the channel count */
	for(i = 0; i < LayerRecord->NumChannels; i++) {
		if (LayerRecord->ChannelLengthInfoPtr[i].ChannelID != -2) {		/* Not invalid? */
			NumChannels++;		/* Increase the count */
		}
	}
	if (!NumChannels) {
		NonFatal("PSD Bad blending channel number");
		return 0;
	}
	DestPtr = (PSDLayerChannelBlendRange_t*)AllocAPointerClear(sizeof(PSDLayerChannelBlendRange_t)*NumChannels);
	if (!DestPtr) {		/* No memory?? */
		return 0;								/* I am screwed */
	}
	BlendRanges->ChannelBlendRanges = DestPtr;
	BlendRanges->Length = LoadMotoLongPtr((LongWord*)Stream);
	BlendRanges->GrayBlend.Src = LoadMotoLongPtr((LongWord*)(Stream+4));
	BlendRanges->GrayBlend.Dst = LoadMotoLongPtr((LongWord*)(Stream+8));
	Stream+=12;

	/* Load each channel blend. */
	do {
		DestPtr->Src = LoadMotoLongPtr((LongWord*)Stream);		/* Copy the range */
		DestPtr->Dst = LoadMotoLongPtr((LongWord*)(Stream+4));
		++DestPtr;			/* Next structure entry */
		Stream+=8;			/* 8 bytes accepted */
	} while (--NumChannels);
	return Stream;			/* Return the new pointer */
}

/**********************************

	Copy literal data

**********************************/

static const Byte * PSDDecodeUncompressedBlock(Byte* Output,LongWord BlockLength,const Byte* Stream)
{
	FastMemCpy(Output, Stream, BlockLength);
	return Stream + BlockLength;
}

/**********************************

	Decompress data using RLE compression

**********************************/

static const Byte *PSDDecodeRLEBlock(PSDLayerRecord_t* LayerRecord,Byte* Output, int BlockLength, int ChannelID,const Byte* Stream)
{
	// Decodes an RLE block.
	int i, y;
	int width, height;
	int inscans;
	Word martin;
	Word replicant;
	Short *scancounts;		/* Number of bytes per scan line */
	Short TempScan[1024];	/* Fast buffer */

	/* Get the dimensions of this record */
	if (ChannelID != -2) {
		height = LayerRecord->Bottom-LayerRecord->Top;
		width  = LayerRecord->Right-LayerRecord->Left;
	} else {
		height = LayerRecord->LayerMaskData.Bottom-LayerRecord->LayerMaskData.Top;
		width  = LayerRecord->LayerMaskData.Right-LayerRecord->LayerMaskData.Left;
	}

	/* Ok, am I screwed? */
	
	if (height<=0 || width<=0) {
		return Stream+BlockLength;		/* Not an error, but I will skip the bad data */
	}

	if (height>1024) {					/* Too big for internal stack */
		scancounts = (Short*)AllocAPointer(sizeof(Short)*height);
		if (!scancounts) {
			return 0;			/* I must be allocating a god-awful buffer! */
		}
	} else {
		scancounts = TempScan;
	}
	i = 0;
	do {
		scancounts[i] = LoadMotoShortPtr((Short*)Stream);
		Stream+=2;
	} while (++i<height);
	
	y = 0;
	do {
		int current; 
		inscans=0;		/* Reset the counters */
		current = scancounts[y];
		if (inscans < current) {
			do {
				martin = Stream[0];		/* Get the token */
				++Stream;				/* Accept it */
				++inscans;				/* Accept from the stream */
				if (martin < 128) {
					++martin;			/* 1-128 */
					inscans+=martin;
					do {
						Output[0] = Stream[0];	/* Explicit copy */
						++Stream;
						++Output;
					} while (--martin);			/* All done? */
				} else {
					replicant = Stream[0];		/* Byte to copy */
					++Stream;
					++inscans;
					martin = 257-martin;		/* 2-129 */
					do {
						Output[0] = replicant;	/* Fill the data */
						++Output;
					} while (--martin);			/* All done? */
				}
			} while (inscans < current);
		}
		if (inscans > ((current+1)&~1)) {
			NonFatal("PSD Bad scan length consistency");
			if (scancounts!=TempScan) {
				DeallocAPointer(scancounts);		/* Release my buffer */
			}
			return 0;			/* You are screwed */
		}
	} while (++y<height);
	if (scancounts!=TempScan) {
		DeallocAPointer(scancounts);				/* Relese my buffer */
	}
	return Stream;									/* Return current running pointer */
}

/**********************************

	Decompress a channel.
	Can use RLE or literal data

**********************************/

static const Byte *PSDDecodeChannel(PSDHeader_t* Header, PSDLayerRecord_t* LayerRecord, PSDChannelImageData_t* ChannelImage, PSDChannelLengthInfo_t* ChannelInfo,const Byte* Stream)
{
	int size;
	int type;

	ChannelImage->Data = 0;			/* Init the pointer */
	if (ChannelInfo->ChannelID != -2) {
		size = (LayerRecord->Bottom-LayerRecord->Top)*(LayerRecord->Right-LayerRecord->Left)*((Header->BitsPerChannel+7)>>3);
	} else {
		size = (LayerRecord->LayerMaskData.Bottom-LayerRecord->LayerMaskData.Top)*(LayerRecord->LayerMaskData.Right-LayerRecord->LayerMaskData.Left)*((Header->BitsPerChannel+7)>>3);
	}

	if(size > 0) {
		ChannelImage->Data = (Byte*)AllocAPointer(size);
		if (!ChannelImage->Data) {
			return 0;
		}
	}
	type = LoadMotoShortPtr((short*)Stream);
	Stream+=2;
	if (!size) {
		return Stream;		/* Don't bother */
	}

	switch(type) {
	case 0:			// Uncompressed;
		Stream = PSDDecodeUncompressedBlock(ChannelImage->Data,ChannelInfo->Length-2,Stream);
		break;
	case 1:			/* RLE compression */
		Stream = PSDDecodeRLEBlock(LayerRecord, ChannelImage->Data, ChannelInfo->Length-2, ChannelInfo->ChannelID,Stream);
		break;
	default:
		NonFatal("PSD Unsupported compression");
		return 0;
	}
	return Stream;
}

/**********************************

	Convert an RGB pixel array into a Burgerlib format

**********************************/

static int PSDCodeRGBChannels(PSDHeader_t* Header, PSDLayerRecord_t* LayerRecord, PSDImageLayer_t* PSDLayer)
{
	// find the 3 channel, r=0, g=1, b=2.
	Byte* r, *g, *b, *rgb;
	int i;
	int numbytes;

	if (Header->BitsPerChannel != 8) {
		NonFatal("PSD Bad channel depth (Not 8 bits)");
		return TRUE;
	}

	if (!LayerRecord->ChannelImageData) {		/* No data? */
		return FALSE;							/* It's ok */
	}

	/* Now, let's find the R,G and B channels */
	/* They are not always in the same order */
	
	r=g=b=0;
	for(i = 0; i < LayerRecord->NumChannels; i++) {
		switch(LayerRecord->ChannelLengthInfoPtr[i].ChannelID) {
		case 0:
			r = LayerRecord->ChannelImageData[i].Data;
			break;
		case 1:
			g = LayerRecord->ChannelImageData[i].Data;
			break;
		case 2:
			b = LayerRecord->ChannelImageData[i].Data;
			break;
		}
		if (r&&g&&b) {		/* Did I find them already? */
			break;
		}
	}

	if(!r||!g||!b) {
		NonFatal("PSD Missing an R,G or B channel");
		return TRUE;
	}
	// This image will be 24 bit color because we force things to be 8 bits per channel.
	
	numbytes = PSDLayer->Width*PSDLayer->Height;
	rgb = (Byte*)AllocAPointer(numbytes*3);		/* If numbytes==0, then the pointer is zero! */
	PSDLayer->RGB = rgb;
	if (!rgb) {
		return TRUE;		/* You are screwed again */
	}
	
	do {
		rgb[0] = r[0];		/* Merge the three layers into a single 24 bit image */
		rgb[1] = g[0];
		rgb[2] = b[0];
		++r;
		++g;
		++b;
		rgb+=3;
	} while (--numbytes);
	return FALSE;
}

/**********************************

	Convert the alpha channel from the PSD to my data

**********************************/

static int PSDCodeAlphaChannel(PSDHeader_t* Header, PSDLayerRecord_t* LayerRecord, PSDImageLayer_t* PSDLayer)
{
	int i;
	Byte* alpha;
	int numbytes;

	if (!LayerRecord->ChannelImageData) {		/* No alpha? */
		return FALSE;
	}

	// find the alpha channel.
	alpha = 0;
	for(i = 0; i < LayerRecord->NumChannels; i++) {
		switch(LayerRecord->ChannelLengthInfoPtr[i].ChannelID) {	/* Scan for Alpha */
		case -1:
			alpha=LayerRecord->ChannelImageData[i].Data;			/* Ah ha! */
			break;
		}
	}
	if(!alpha) {
		NonFatal("PSD Missing alpha channel");
		return TRUE;
	}

	// direct copy.
	numbytes = PSDLayer->Width*PSDLayer->Height;
	PSDLayer->Alpha = (Byte*)AllocAPointer(numbytes);
	if (!PSDLayer->Alpha) {
		return TRUE;
	}
	FastMemCpy(PSDLayer->Alpha, alpha, numbytes);		/* Copy the data */
	return FALSE;
}

/**********************************

	Convert the mask channel from the PSD to my data

**********************************/

static int PSDCodeMaskChannel(PSDHeader_t* Header, PSDLayerRecord_t* LayerRecord, PSDImageLayer_t* PSDLayer)
{
	int i;
	Byte* mask;
	int numbytes;

	if (!LayerRecord->ChannelImageData) {		/* No mask found? */
		return FALSE;
	}

	// find mask channel.
	mask = 0;
	for(i = 0; i < LayerRecord->NumChannels; i++) {
		switch(LayerRecord->ChannelLengthInfoPtr[i].ChannelID) {
		case -2:
			mask=LayerRecord->ChannelImageData[i].Data;		/* Ah ha! */
			break;
		}
	}
	if (!mask) {
		NonFatal("PSD Missing the mask channel");
		return TRUE;
	}
	// direct copy.
	numbytes = PSDLayer->MaskWidth*PSDLayer->MaskHeight;
	PSDLayer->Mask = (Byte*)AllocAPointer(numbytes);
	if (!PSDLayer->Mask) {
		return TRUE;
	}
	FastMemCpy(PSDLayer->Mask, mask, numbytes);
	return FALSE;
}

/**********************************

	Grab bitmap data from the PSD image

**********************************/

static const Byte *PSDReadChannelImageData(PSDHeader_t* Header, PSDLayerInfoSection_t* LayerSection,const Byte* Stream)
{
	/* 
	** The PSD contains channel image data for each channel in order of
	** each layer.
	*/

	int i;
	int channel;
	PSDLayerRecord_t* LayerRecord;

	for (i = 0; i < LayerSection->NumLayers; i++) {
		LayerRecord = &LayerSection->LayerRecordsPtr[i];
		LayerRecord->ChannelImageData = (PSDChannelImageData_t*)AllocAPointer(sizeof(PSDChannelImageData_t)*LayerRecord->NumChannels);
		if (!LayerRecord->ChannelImageData) {
			return 0;
		}

		FastMemSet(LayerRecord->ChannelImageData, 0, sizeof(PSDChannelImageData_t)*LayerRecord->NumChannels);

		// Read each channel.
		for(channel = 0; channel < LayerRecord->NumChannels; channel++) {
			Stream = PSDDecodeChannel(Header, LayerRecord, &LayerRecord->ChannelImageData[channel], &LayerRecord->ChannelLengthInfoPtr[channel],Stream);
			if (!Stream) {
				return Stream;
			}
		}
	}
	return Stream;
}

/**********************************

	Get a layer record from the PSD stream

**********************************/

static const Byte *PSDReadLayerRecord(PSDLayerRecord_t* LayerRecord,const Byte *Stream)
{
	int i;
	int read_so_far;
	const Byte *mark1;

	LayerRecord->Top = LoadMotoLongPtr((LongWord*)Stream);
	LayerRecord->Left = LoadMotoLongPtr((LongWord*)(Stream+4));
	LayerRecord->Bottom = LoadMotoLongPtr((LongWord*)(Stream+8));
	LayerRecord->Right = LoadMotoLongPtr((LongWord*)(Stream+12));
	LayerRecord->NumChannels = LoadMotoShortPtr((short*)(Stream+16));
	Stream += 18;
	
	LayerRecord->ChannelLengthInfoPtr = (PSDChannelLengthInfo_t*)AllocAPointerClear(sizeof(PSDChannelLengthInfo_t)*LayerRecord->NumChannels);
	if (!LayerRecord->ChannelLengthInfoPtr) {
		return 0;
	}
	for (i = 0; i < LayerRecord->NumChannels; i++) {
		Stream = PSDReadChannelLengthInfo(&LayerRecord->ChannelLengthInfoPtr[i],Stream);
		if (!Stream) {
			return Stream;
		}
	}

	((LongWord *)&LayerRecord->BlendModeSig[0])[0] = ((LongWord *)Stream)[0];
	if (memcmp(LayerRecord->BlendModeSig,"8BIM",4)) {
		NonFatal("PSD BAD Blend mode signature");
		return 0;
	}
	LayerRecord->BlendModeKey = LoadMotoLongPtr((LongWord*)(Stream+4));
	LayerRecord->Opacity = Stream[8];
	LayerRecord->Clipping = Stream[9];
	LayerRecord->Flags = Stream[10];
	LayerRecord->ExtraDataSize = LoadMotoLongPtr((LongWord*)(Stream+12));
	Stream += 16;	
	mark1 = Stream;
	// Read mask data.
	Stream = PSDReadLayerMaskData(&LayerRecord->LayerMaskData,Stream);
	if (Stream) {
		// Read blend ranges.
		Stream = PSDReadLayerBlendingRanges(&LayerRecord->LayerBlendingRanges, LayerRecord, Stream);
		if (Stream) {
			// Name
			Stream = PSDReadPascalString(&LayerRecord->Name,Stream);
			if (Stream) {
				read_so_far = Stream-mark1;

				if (read_so_far > LayerRecord->ExtraDataSize) {
					NonFatal("PSD Layer data overrun");
					Stream = 0;
				} else if (read_so_far < LayerRecord->ExtraDataSize) {
					Stream += (LayerRecord->ExtraDataSize-read_so_far);
				}
			}
		}
	}
	return Stream;
}

/**********************************

	Grab a layer's information section

**********************************/

static const Byte *PSDReadLayerInfoSection(PSDLayerInfoSection_t* LayerSection,const Byte* Stream)
{
	int n;
	int i;
	int LayerInfoLength;
	int SectionLength;

	SectionLength = LoadMotoLongPtr((LongWord*)Stream);
	// Load the layer info block.
	LayerInfoLength = LoadMotoLongPtr((LongWord*)(Stream+4));
	n = LoadMotoShortPtr((short*)(Stream+8));

	Stream+=10;
	// Abs?
	if(n < 0) {
		n = -n;
	}
	LayerSection->NumLayers = n;
	LayerSection->LayerRecordsPtr = (PSDLayerRecord_t*)AllocAPointerClear(sizeof(PSDLayerRecord_t)*LayerSection->NumLayers);
	if (!LayerSection->LayerRecordsPtr) {
		return 0;
	}
	for(i = 0; i < LayerSection->NumLayers; i++) {
		Stream = PSDReadLayerRecord(&LayerSection->LayerRecordsPtr[i],Stream);
		if (!Stream) {
			break;
		}
	}
	return Stream;
}

/**********************************

	Dispose of a layer's information section

**********************************/

static void FreePSDLayerInfoSectionBlock(PSDLayerInfoSection_t* LayerSection)
{
	int i, k;
	PSDLayerRecord_t* LayerRecord;

	LayerRecord = LayerSection->LayerRecordsPtr;
	for(i = 0; i < LayerSection->NumLayers; i++) {
		// Free all channel data.
		if (LayerRecord->ChannelImageData) {			/* Sanity check */
			for(k = 0; k < LayerRecord->NumChannels; k++) {
				DeallocAPointer(LayerRecord->ChannelImageData[k].Data);
			}
			DeallocAPointer(LayerRecord->ChannelImageData);
		}
		DeallocAPointer(LayerRecord->ChannelLengthInfoPtr);
		DeallocAPointer(LayerRecord->LayerBlendingRanges.ChannelBlendRanges);
		DeallocAPointer(LayerRecord->Name);
		++LayerRecord;
	}
	DeallocAPointer(LayerSection->LayerRecordsPtr);
	FastMemSet(LayerSection,0,sizeof(PSDLayerInfoSection_t));
}

/**********************************

	Taking an image from memory, parse out
	a PSD file and store it in a PSDImage_t struct

**********************************/

Word FASTCALL PSDReadFromByteStream(PSDImage_t* Image, const Byte* InStream, Byte** NewPos)
{
	Word i;
	PSDHeader_t Header;
	PSDLayerInfoSection_t LayerSection;
	PSDImageLayer_t* PSDLayer;
	PSDLayerRecord_t* LayerRecord;
	
	FastMemSet(Image,0,sizeof(PSDImage_t));
	FastMemSet(&LayerSection, 0, sizeof(LayerSection));

	InStream = PSDReadHeader(&Header,InStream);		/* Parse out the master header */
	if (InStream) {
		InStream = PSDSkipColorData(InStream);
		if (InStream) {
			InStream = PSDSkipImageResources(InStream);
			if (InStream) {
				InStream = PSDReadLayerInfoSection(&LayerSection, InStream);
				if(InStream) {
					InStream=PSDReadChannelImageData(&Header, &LayerSection, InStream);
					if (InStream) {
						// Combine all the layers channel into the PSDImage structure.
						Image->Width = Header.Width;
						Image->Height = Header.Height;
						Image->NumLayers = LayerSection.NumLayers;
						Image->Layers = (PSDImageLayer_t*)AllocAPointerClear(sizeof(PSDImageLayer_t)*LayerSection.NumLayers);
						if(Image->Layers) {
							// For each layer extract the channels and put them into something more useful.
							for(i = 0; i < Image->NumLayers; i++) {
								PSDLayer = &Image->Layers[i];
								LayerRecord = &LayerSection.LayerRecordsPtr[i];

								PSDLayer->Top = LayerRecord->Top;
								PSDLayer->Bottom = LayerRecord->Bottom;
								PSDLayer->Left = LayerRecord->Left;
								PSDLayer->Right = LayerRecord->Right;
								PSDLayer->Width = PSDLayer->Right-PSDLayer->Left;
								PSDLayer->Height = PSDLayer->Bottom-PSDLayer->Top;
								
								// mask
								PSDLayer->MaskTop = LayerRecord->LayerMaskData.Top;
								PSDLayer->MaskLeft = LayerRecord->LayerMaskData.Left;
								PSDLayer->MaskRight = LayerRecord->LayerMaskData.Right;
								PSDLayer->MaskBottom = LayerRecord->LayerMaskData.Bottom;
								PSDLayer->MaskWidth = PSDLayer->MaskRight-PSDLayer->MaskLeft;
								PSDLayer->MaskHeight = PSDLayer->MaskBottom-PSDLayer->MaskTop;

								PSDLayer->Name = 0;

								// code the channels.
								PSDCodeRGBChannels(&Header, LayerRecord, PSDLayer);
								PSDCodeAlphaChannel(&Header, LayerRecord, PSDLayer);
								PSDCodeMaskChannel(&Header, LayerRecord, PSDLayer);
							}
						}
					}
				}
				// everything is packed up in PSDImage_t, so kill the layersection to free other mem.
				FreePSDLayerInfoSectionBlock(&LayerSection);
			}
		}
	}
	if( NewPos ) {
		*NewPos = (Byte*)InStream;
	}
	if (!InStream) {
		PSDImageDestroy(Image);		/* Oh crap */
		return PSD_FAIL;
	}
	return PSD_OK;				/* Return the end pointer or zero */
}

void FreePSDImage(PSDImage_t* PSD)
{
	int i;
	PSDImageLayer_t* layer;

	for(i = 0; i < PSD->NumLayers; i++)
	{
		layer = &PSD->Layers[i];
		
		if(layer->Alpha)
			free(layer->Alpha);
		if(layer->Mask)
			free(layer->Mask);
		if(layer->RGB)
			free(layer->RGB);
	}

	if(PSD->Layers)
		free(PSD->Layers);
	PSD->Layers = 0;
	PSD->NumLayers = 0;
}

Image_t* ImageNew(int w, int h, int bytes_pp)
{
	Image_t* image = (Image_t*)malloc(sizeof(Image_t));
	if(image == 0)
		return 0;
	memset(image, 0, sizeof(Image_t));
	
	if(w == 0 || h == 0)
		return 0;

	image->x = image->y = 0;
	image->width = w;
	image->height = h;
	image->flags = 0;

	image->data = (unsigned char*)malloc(bytes_pp*w*h);
	if(!image->data)
	{
		free(image);
		return 0;
	}

	return image;
}

void FreeImageData(Image_t* image)
{
	if(image->data == 0)
		return;
	free(image->data);
}

void FreeImageStruct(Image_t* image)
{
	FreeImageData(image);
	free(image);
}

Image_t* PSDMakeImageFromLayer(PSDImageLayer_t* Layer, int flags)
{
	Image_t* image=0;

	switch(flags)
	{
	case PSD_FLAG_RGB:
		if(!Layer->RGB)
			return 0;
		// just get rgb.
		image = ImageNew(Layer->Width, Layer->Height, 3);
		if(!image)
			return 0;
		image->x = Layer->Left; image->y = Layer->Top;
		memcpy(image->data, Layer->RGB, Layer->Width*Layer->Height*3);
		break;
	case PSD_FLAG_ALPHA:
		if(!Layer->Alpha)
			return 0;
		// just get alpha.
		image = ImageNew(Layer->Width, Layer->Height, 1);
		if(!image)
			return 0;
		image->x = Layer->Left; image->y = Layer->Top;
		memcpy(image->data, Layer->Alpha, Layer->Width*Layer->Height);
		break;
	case PSD_FLAG_MASK:
		if(!Layer->Mask)
			return 0;
		image = ImageNew(Layer->MaskWidth, Layer->MaskHeight, 1);
		if(!image)
			return 0;
		image->x = Layer->MaskLeft; image->y = Layer->MaskTop;
		memcpy(image->data, Layer->Mask, Layer->MaskWidth*Layer->MaskHeight);
		break;
	case PSD_FLAG_RGBA:
		{
			int i, numbytes;
			unsigned char* rgb, *alpha, *data;
			
			if(!Layer->RGB || !Layer->Alpha)
				return 0;
				
			image = ImageNew(Layer->Width, Layer->Height, 4);
			if(!image)
				return 0;
			image->x = Layer->Left; image->y = Layer->Top;
			numbytes = Layer->Width*Layer->Height*4;

			rgb = Layer->RGB;
			alpha = Layer->Alpha;
			data = image->data;

			for(i = 0; i < numbytes; i+=4)
			{
				*data++ = *rgb++;
				*data++ = *rgb++;
				*data++ = *rgb++;
				*data++ = *alpha++;
			}
		}
	}

	if(image)
		image->flags = flags;

	return image;
}