/*****************************************************************************
* Abstraction of the PPM image format for input and output.		     *
******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                *
******************************************************************************
* Written by:  Gennady Agranov and Gershon Elber        Ver 0.2, Apr. 1995   *
*****************************************************************************/

#include "program.h"

static FILE
    *PPMFile = NULL;
static int PPMWidth, PPMHeight, PPMLine;
static PixelStruct **PixelData;

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Opens output image file in PPM format.                                   M
*   Creates file header. Note we allocate full image size since ppm expects  M
* lines top to bottom and we scan convert bottom to top.                     M
*                                                                            *
* PARAMETERS:                                                                M
*   argv:     Pointer to the name of this program.                           M
*   XSize:    X dimension of the image.                                      M
*   YSize:    Y dimension of the image.                                      M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   PPMOpenFile, PPM, output image                                           M
*****************************************************************************/
void PPMOpenFile(char **argv, int XSize, int YSize)
{
    int i;

    if (PPMFile != stdout && PPMFile != NULL)
        fclose(PPMFile);

    PPMFile = stdout;
    PPMWidth = XSize;
    PPMHeight = YSize;
    PPMLine = 0;

    PixelData = (PixelStruct **) IritMalloc(PPMHeight * sizeof(PixelStruct *));

    for (i = 0; i < PPMHeight; i++) {
	PixelData[i] =
	    (PixelStruct *) IritMalloc(PPMWidth * sizeof(PixelStruct));
    }

    if (PPMFile != NULL)
        fprintf(PPMFile,
		"P6\n# IRIT Irender image file 24 bit rgb\n%d %d\n%d\n",
		XSize, YSize, 255);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Outputs given line of color pixels and alpha correction values to the    M
*   ouput image file.                                                        M
*                                                                            *
* PARAMETERS:                                                                M
*   Alpha:  Array of alpha values.                                           M
*   Pixels: Array of color pixels.                                           M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   PPMPutLine, PPM, output image                                            M
*****************************************************************************/
void PPMPutLine(ByteType *Alpha, PixelStruct *Pixels)
{
    if (PPMLine < PPMHeight)
	GEN_COPY(PixelData[PPMLine++], Pixels, PPMWidth * sizeof(PixelStruct));
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Closes output image file.                                                M
*                                                                            *
* PARAMETERS:                                                                M
*   None                                                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   PPMCloseFile, PPM, output image                                          M
*****************************************************************************/
void PPMCloseFile(void)
{
    int i;

    for (i = 0; i < PPMHeight; i++) {
	fwrite(PixelData[PPMHeight - i - 1], PPMWidth * sizeof(PixelStruct),
	       1, PPMFile);
	IritFree(PixelData[PPMHeight - i - 1]);
    }
    IritFree(PixelData);

    if (PPMFile!=NULL)
	fclose(PPMFile);

    PPMFile = NULL;
}


/*****************************************************************************
* DESCRIPTION:                                                               M
*   Loads image file in PPM format.                                          M
*                                                                            *
* PARAMETERS:                                                                M
*   File:  Name of the image file.                                           M
*                                                                            *
* RETURN VALUE:                                                              M
*   ImageStruct *:  Pointer to dynamicaly created image.                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   PPMLoadImage, PPM, image file, texture                                   M
*****************************************************************************/
ImageStruct *PPMLoadImage(char *File)
{
    char Line[LINE_LEN_LONG];
    FILE *PPMLoad;
    ImageStruct *PImage;

    if ((PPMLoad = fopen(File, "r")) == NULL)
        return NULL;

    PImage = MALLOC(ImageStruct, 1);

    fgets(Line, LINE_LEN_LONG - 1, PPMLoad);
    if (strncmp(Line, "P6", 2) != 0)
        return NULL;

    fgets(Line, LINE_LEN_LONG - 1, PPMLoad);
    if (Line[0] == '#')
	fgets(Line, LINE_LEN_LONG - 1, PPMLoad);
    sscanf(Line, "%d %d", &PImage -> xSize, &PImage -> ySize);
    if (PImage -> xSize < 0 ||
	PImage -> xSize > 10000 ||
	PImage -> ySize < 0 ||
	PImage -> ySize > 10000)
	return NULL;

    /* Get the 255 line. */
    fgets(Line, LINE_LEN_LONG - 1, PPMLoad);

    PImage -> data = MALLOC(PixelStruct,
			    (PImage -> ySize + 1) * (PImage -> xSize + 1));
    fread(PImage -> data,
	  PImage -> xSize * PImage -> ySize * sizeof(PixelStruct),
	  1, PPMLoad);

    fclose(PPMLoad);

    PImage -> xSize--;      /* No good reason, but does not work otherwise. */

    return PImage;
}
