/*
	name:	ppm.c

	PPM 24-bit color picture support
	--------------------------------

	These routines enable image input/output in 24-bit PPM format.
	I know very little about the PPM format (I have only looked at
	one file to figure out the format), thus I guess RayLab is not
	able to read all PPM files. RayLab supports the P6 PPM format
	(binary 24-bit), and the 'max-value' for input files may range
	from 1 to 255, presuming that each color-component (R,G, and B)
	is one byte (three bytes/pixel).

    This source-code is part of the RayLab 1.1 package, and it is provided
    for your compiling pleasure.  You may use it, change it, re-compile it
    etc., as long as nobody else but you receive the changes/compilations
    that you have made!

    You may not use any part(s) of this source-code for your own productions
    without the permission from the author of RayLab. Please read the legal
    information found in the users documentation for RayLab for more details.

*/


#include  <stdlib.h>
#include  <string.h>

#include  "defs.h"
#include  "extern.h"


	unsigned char	ppmdata[parraysize*3];
	long		ppm_maxvalue;


/* ---------------------------------------------------------------------
   WritePpmHeader()
   --------------------------------------------------------------------- */

void WritePpmHeader(FILE *f,long width, long height)
{
        fprintf(f,"P6"); fputc((char)10,f);
        fprintf(f,"%ld %ld",width,height); fputc((char)10,f);
        fprintf(f,"%d",255); fputc((char)10,f);
}


/* ---------------------------------------------------------------------
   CleanupPpm()
   --------------------------------------------------------------------- */

void CleanupPpm(FILE *f)
{
	/* Not supported!! */
	/* To make a proper Cleanup(), you need to be able to */
	/* over-write the height value in the beginning of the */
	/* file, which can be tricky as the PPM format uses ascii */
	/* numbers, which occupies more or less space in the file */
	/* depending on the magnitude of the number. */
}


/* ---------------------------------------------------------------------
   WritePpmLine()
   --------------------------------------------------------------------- */

void WritePpmLine(FILE *f, long width)
{
	long	i;
	unsigned char *pixels;

	pixels=ppmdata;
	for(i=0;i<width;i++) {
	    *pixels++=pixelarray[i].r;	/* Use order: r,g,b */
	    *pixels++=pixelarray[i].g;
	    *pixels++=pixelarray[i].b;
	}
	(void) fwrite((void *)ppmdata,sizeof(unsigned char),(size_t)(width*3),f);
}


/* ---------------------------------------------------------------------
   ReadPpmHeader()
   --------------------------------------------------------------------- */

void ReadPpmHeader(FILE *f, long *width, long *height)
{
	int	i, itmp;
	long	tmpwidth, tmpheight;
	char	buffer[20];

	tmpwidth=tmpheight=*width=*height=-1L;

	fread((void *)buffer,sizeof(char),(size_t)2,f);
	buffer[2]=0;
	if(strcmp(buffer,"P6")==0) {
	    buffer[0]=0;
	    itmp=fgetc(f);
	    while((itmp!=EOF)&&(ischar(itmp)==FALSE)) itmp=fgetc(f);
	    i=0;
	    while((itmp!=EOF)&&(ischar(itmp)==TRUE)) {
		buffer[i]=(char)itmp;
		itmp=fgetc(f);
		i++;
	    }
	    if(itmp==EOF) {
		fprintf(textoutput,"\nError: Premature end of PPM file\n");
	    }
	    else {
		buffer[i]=0;
		tmpwidth=atol(buffer);
		buffer[0]=0;
		itmp=fgetc(f);
		while((itmp!=EOF)&&(ischar(itmp)==FALSE)) itmp=fgetc(f);
		i=0;
		while((itmp!=EOF)&&(ischar(itmp)==TRUE)) {
		    buffer[i]=(char)itmp;
		    itmp=fgetc(f);
		    i++;
		}
		if(itmp==EOF) {
		    fprintf(textoutput,"\nError: Premature end of PPM file\n");
		}
		else {
		    buffer[i]=0;
		    tmpheight=atol(buffer);
		    buffer[0]=0;
		    itmp=fgetc(f);
		    while((itmp!=EOF)&&(ischar(itmp)==FALSE)) itmp=fgetc(f);
		    i=0;
		    while((itmp!=EOF)&&(ischar(itmp)==TRUE)) {
			buffer[i]=(char)itmp;
			itmp=fgetc(f);
			i++;
		    }
		    if(itmp==EOF) {
			fprintf(textoutput,"\nError: Premature end of PPM file\n");
		    }
		    else {
			buffer[i]=0;
			ppm_maxvalue=atol(buffer);
			if(ppm_maxvalue>255) {
			    fprintf(textoutput,"\nError: The PPM max-value must be less than 256\n");
			    tmpwidth=tmpheight=-1;
			}
			else {
			    while((itmp!=EOF)&&(itmp!=10)) itmp=fgetc(f);
			}
		    }
		}
	    }
	    if((itmp!=EOF)&&(tmpwidth>0)&&(tmpheight>0)) {
		if(tmpwidth<=parraymaxpix) {
		    *width=tmpwidth;
		    *height=tmpheight;
		}
		else fprintf(textoutput,"\nError: Maximum width is %d\n",parraymaxpix);
	    }
	}
	else {
	    fprintf(textoutput,"\nError: Not recognized as a 'P6' PPM file\n");
	}
}


/* ---------------------------------------------------------------------
   ReadPpmImage()
   --------------------------------------------------------------------- */

short ReadPpmImage(int *ImageNum, FILE *f, long width, long height)
{
	short	ImageType;
	int	i,j;
	unsigned char *Ppmptr;
	unsigned char *Bodyptr;
	IMAGE24	*Image24;

	ImageType=IMG_NONE;

	if(Num24Images<maximages) {
	    Image24=(void *)malloc(sizeof(IMAGE24));
	    if(Image24!=NULL) {
		Image24->XSize=width; Image24->YSize=height;
		Image24->Interpolate=INTPOL_NONE;
		Image24->Maptype=MAP_PLANAR;
		Image24->Tile=TILE_TRUE;
		Image24->Body=(unsigned char *)malloc((size_t)(width*height*3));
		if(Image24->Body!=NULL) {
		    i=0;
		    Bodyptr=Image24->Body;
		    while(i<height) {
			(void) fread(ppmdata,(size_t)1,(size_t)(3*width),f);
			Ppmptr=ppmdata;
			for(j=0;j<width;j++) {
			    *Bodyptr++=(unsigned char)((((int)*Ppmptr++)*255)/ppm_maxvalue);
			    *Bodyptr++=(unsigned char)((((int)*Ppmptr++)*255)/ppm_maxvalue);
			    *Bodyptr++=(unsigned char)((((int)*Ppmptr++)*255)/ppm_maxvalue);
			}
			i++;
		    }
		    *ImageNum=Num24Images;
		    Img24Array[Num24Images]=Image24;
		    Num24Images++;
		    ImageType=IMG_24BIT;
		}
		else {
		    free(Image24);
		    Image24=NULL;
		}
	    }
	}
	else {
	    fprintf(textoutput,"\nError: Maximum amount of 24-bit images exceeded\n");
	}

	return(ImageType);
}

