/*
 * The Python Imaging Library
 * $Id$
 *
 * built-in image file handling
 *
 * history:
 * 1995-11-26 fl  Created, supports PGM/PPM
 * 1996-08-07 fl  Write "1" images as PGM
 * 1999-02-21 fl  Don't write non-standard modes
 *
 * Copyright (c) 1997-99 by Secret Labs AB.
 * Copyright (c) 1995-96 by Fredrik Lundh.
 *
 * See the README file for information on usage and redistribution.
 */


#include "Imaging.h"

#include <ctype.h>

Imaging
ImagingOpenPPM(const char* infile)
{
    FILE* fp;
    int i, c, v;
    char* mode;
    int x, y, max;
    Imaging im;

    if (!infile)
	return ImagingError_ValueError(NULL);

    fp = fopen(infile, "rb");
    if (!fp)
	return ImagingError_IOError();

    /* PPM magic */
    if (fgetc(fp) != 'P')
	goto error;
    switch (fgetc(fp)) {
    case '4': /* FIXME: 1-bit images are not yet supported */
	goto error;
    case '5':
	mode = "L";
	break;
    case '6':
	mode = "RGB";
	break;
    default:
	goto error;
    }

    i = 0;
    c = fgetc(fp);

    x = y = max = 0;

    while (i < 3) {

	/* Ignore optional comment fields */
	while (c == '\n') {
	    c = fgetc(fp);
	    if (c == '#') {
		do {
		    c = fgetc(fp);
		    if (c == EOF)
			goto error;
		} while (c != '\n');
		c = fgetc(fp);
	    }
	}

	/* Skip forward to next value */
	while (isspace(c))
	    c = fgetc(fp);

	/* And parse it */
	v = 0;
	while (isdigit(c)) {
	    v = v * 10 + (c - '0');
	    c = fgetc(fp);
	}

	if (c == EOF)
	    goto error;

	switch (i++) {
	case 0:
	    x = v;
	    break;
	case 1:
	    y = v;
	    break;
	case 2:
	    max = v;
	    break;
	}
    }

    im = ImagingNew(mode, x, y);
    if (!im)
	return NULL;

    /* if (max != 255) ... FIXME: does anyone ever use this feature? */

    if (strcmp(im->mode, "L") == 0) {

	/* PPM "L" */
	for (y = 0; y < im->ysize; y++)
	    if (fread(im->image[y], im->xsize, 1, fp) != 1)
		goto error;

    } else {

	/* PPM "RGB" or PyPPM mode */
	for (y = 0; y < im->ysize; y++)
	    for (x = i = 0; x < im->xsize; x++, i += im->pixelsize)
		if (fread(im->image[y]+i, im->bands, 1, fp) != 1)
		    goto error;
    }

    fclose(fp);

    return im;

error:
    fclose(fp);
    return ImagingError_IOError();
}


int
ImagingSaveRaw(Imaging im, FILE* fp)
{
    int x, y, i;

    if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) {

        /* @PIL227: FIXME: for mode "1", map != 0 to 255 */

	/* PGM "L" */
	for (y = 0; y < im->ysize; y++)
	    fwrite(im->image[y], 1, im->xsize, fp);

    } else {

	/* PPM "RGB" or other internal format */
	for (y = 0; y < im->ysize; y++)
	    for (x = i = 0; x < im->xsize; x++, i += im->pixelsize)
		fwrite(im->image[y]+i, 1, im->bands, fp);

    }

    return 1;
}


int
ImagingSavePPM(Imaging im, const char* outfile)
{
    FILE* fp;

    if (!im) {
	(void) ImagingError_ValueError(NULL);
	return 0;
    }

    fp = fopen(outfile, "wb");
    if (!fp) {
	(void) ImagingError_IOError();
	return 0;
    }

    if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) {
	/* Write "PGM" */
	fprintf(fp, "P5\n%d %d\n255\n", im->xsize, im->ysize);
    } else if (strcmp(im->mode, "RGB") == 0) {
        /* Write "PPM" */
        fprintf(fp, "P6\n%d %d\n255\n", im->xsize, im->ysize);
    } else {
	(void) ImagingError_ModeError();
        return 0;
    }

    ImagingSaveRaw(im, fp);

    fclose(fp);

    return 1;
}