/*--------------------------------------------------------------------------
 * File: pcx.c
 * Written by: Fredrik Kling, 1998-01-04
 * Description: ZSOFT image loader (PCX)
 *
 * Updates:
 * -- Date -- | ----- Name ----- |-- Did what....
 * 1998-01-04 | Fredrik Kling    | Implementation
 *
 * Todo:
 *
 -------------------------------------------------------------------------------*/

#include "system/xstdio.h"
#include "formats/vio.h"
#include "formats/pcx.h"


VIO *pcx_load( char *filename)
{
	VIO *vio;
	BYTE *dst;
	XFILE *f;
	int i,k,pos,yc,ofs,colc;
	BYTE version,encode,bpp,cpp,b,num;
	BYTE colmap[48];
	RGB palette[256];
	WORD xmin,ymin,xmax,ymax,bpsl,pdata;


	if ( (f = xfopen( filename, "rb")) == NULL)	return( NULL);

	if ( xfr_byte( f) != 0x0a)
	{
		xfclose( f);
		return( NULL);
	}
	/* version should be: 0,2,3,5 */
	version = xfr_byte (f);

	if (version != 5)
	{
		xfclose (f);
		return NULL;
	}

	printf ("encode: %i\n");
	encode = xfr_byte (f);

	bpp = xfr_byte (f);
	printf ("bpp: %i\n",bpp);

	xmin = xfrbe_word (f);
	ymin = xfrbe_word (f);
	xmax = xfrbe_word (f)+1;
	ymax = xfrbe_word (f)+1;

/*
	printf ("Version: %i\n",version);
	if (encode) printf ("picture RLE coded!\n");
		else printf ("uncompressed picture!\n");
	printf ("xsize: %i\n",xmax-xmin);
	printf ("ysize: %i\n",ymax-ymin);
*/

	// skip dot per inch
	xfseek (f,4,SEEK_CUR);
	for (i=0;i<48;i++) colmap[i] = xfr_byte (f);
	xfseek (f,1,SEEK_CUR);

	cpp = xfr_byte (f);
	bpsl =  xfrbe_word (f);
	pdata = xfrbe_word (f);

	printf ("cpp: %i, bpsl: %i, pdata: %i\n",cpp,bpsl,pdata);

	switch (cpp)
	{
		case 1 :
				dst = xmalloc (sizeof (BYTE) * (xmax-xmin) * (ymax - ymin));
				break;
		case 2 :
		case 3 :
		case 4 :
				dst = xmalloc (sizeof (RGB) * (xmax-xmin) * (ymax - ymin));
				break;
		default : printf ("unsupported mode!\n"); exit (1);
	}

	if (dst == NULL)
	{
		printf ("Out of memory\n");
		xfclose (f);
		return NULL;
	}


	// jump....
	xfseek (f,58,SEEK_CUR);

	pos = 0;

	if (encode)
	{
			ofs=0;
			for (yc=0;yc<(ymax-ymin);yc++)
			{
				for (colc=0;colc<cpp;colc++)
				{
					for (pos=0;pos<(xmax-xmin);)
					{
						b = xfr_byte (f);
						if ((b & 0xc0) == 0xc0)
						{
							num = (b & 63);
							b = xfr_byte (f);
							// we got a coded byte!!
							for (k=0;k<num;k++)
							{
								dst[pos*cpp+colc+ofs]=b;
								pos++;
							}
						} else
							{
								dst[pos*cpp+colc+ofs] = b;
								pos++;
				  		} // else
					} // pos..
				} // colc
				ofs += cpp*(ymax-ymin);
			}

	} // encode...

	xfseek (f,-769,SEEK_END);

	b = xfr_byte (f);
	if (b != 0x0c)
	{
		printf ("hmmm...  no colorcode byte found: %i,%i\n",xftell (f),b);
		printf ("assuming 24 bits picture.\n");
		xfclose (f);
		vio = vio_create24bit (NULL,(RGB *)dst,xmax-xmin,ymax-ymin);
	} else
		{
			for (i=0;i<256;i++)
			{
				palette[i].r = xfr_byte (f) >> 2;
				palette[i].g = xfr_byte (f) >> 2;
				palette[i].b = xfr_byte (f) >> 2;
			}
			xfclose(f);
			vio = vio_create8bit (NULL,palette,dst,xmax-xmin,ymax-ymin);
		}

	printf ("Done!\n");
	return vio;
}

