/* +-------------------------------------------------------------------+ */
/* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)	       | */
/* |								       | */
/* | Permission to use, copy, modify, and to distribute this software  | */
/* | and its documentation for any purpose is hereby granted without   | */
/* | fee, provided that the above copyright notice appear in all       | */
/* | copies and that both that copyright notice and this permission    | */
/* | notice appear in supporting documentation.	 There is no	       | */
/* | representations about the suitability of this software for	       | */
/* | any purpose.  this software is provided "as is" without express   | */
/* | or implied warranty.					       | */
/* |								       | */
/* +-------------------------------------------------------------------+ */

/* $Id: readWritePNM.c,v 1.21 2005/03/20 20:15:34 demailly Exp $ */

#include <stdio.h>
#include <string.h>
#include "image.h"
#include "libpnmrw.h"

#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include "xpaint.h"

#define TRUE 1
#define FALSE 0

char * PNM_alpha_separator = "\n";

Image *
ReadPNM(char *file)
{
    int x, y;
    xel **els = NULL;
    xel *curel;
    xelval maxval;
    int pnm_type;
    FILE *fd;
    Image *image, *rgb = NULL;
    int format;
    int wth, hth;
    unsigned char *dp;
    unsigned int c;

    pnm_init2(file);
    if ((fd = fopen(file, "r")) == NULL)
	return NULL;

 restart:
    if ((els = pnm_readpnm(fd, &wth, &hth, &maxval, &format)) == NULL)
	return NULL;
    pnm_type = PNM_FORMAT_TYPE(format);

    if (feof(fd)) {
        fclose(fd);
        fd = NULL;
    } else {
        /* eliminate any extra characters in between */
        do {
            c = fgetc(fd);
        } while (c != 'P' && !feof(fd));
        if (feof(fd)) {
	    fclose(fd);
            fd = NULL;
	} else
	    fseek(fd, -1, SEEK_CUR);
    }

    if (pnm_type == PBM_TYPE)
	image = ImageNewBW(wth, hth);
    else if (pnm_type == PGM_TYPE)
	image = ImageNewGrey(wth, hth);
    else
	image = ImageNew(wth, hth);
    dp = image->data;

    for (y = 0; y < hth; y++) {
	for (curel = els[y], x = 0; x < wth; x++, curel++) {
	    if (pnm_type == PPM_TYPE) {
		*dp++ = 255 * PPM_GETR(*curel) / maxval;
		*dp++ = 255 * PPM_GETG(*curel) / maxval;
		*dp++ = 255 * PPM_GETB(*curel) / maxval;
	    } else if (pnm_type == PGM_TYPE) {
		*dp++ = 255 * PNM_GET1(*curel) / maxval;
	    } else {
		*dp++ = (PNM_GET1(*curel) != PBM_WHITE) ? 1 : 0;
	    }
	}
    }

    pnm_freearray(els, hth);

    if (rgb) {
        if (image->isGrey && 
            image->width == rgb->width && image->height == rgb->height) {
	    rgb->alpha = image->data;
            image->data = NULL;
	}
        ImageDelete(image);
        image = rgb;
        if (fd) fclose(fd);
    } else
    if (fd) {
        rgb = image;
        if (rgb)
            goto restart;
        fclose(fd);
    }

    return image;
}

static int writePNM(char *file, FILE * fd, Image * image, int flag)
{
    xel **xels;
    int x, y;
    unsigned char *ip;
    int format;

    if (image->isBW)
	format = PBM_FORMAT;
    else if (image->isGrey)
	format = PGM_FORMAT;
    else
	format = PPM_FORMAT;

    pnm_init2(file);

    xels = pnm_allocarray(image->width, image->height);

    for (y = 0; y < image->height; y++)
	for (x = 0; x < image->width; x++) {
	    ip = ImagePixel(image, x, y);
	    PPM_ASSIGN(xels[y][x], ip[0], ip[1], ip[2]);
	}

    pnm_writepnm(fd, xels, image->width, image->height, 255, format, flag);

    pnm_freearray(xels, image->height);

    return FALSE;
}

int WritePNMType(char *file, Image * image, int mode)
{
    FILE *fd;
    Image * alphachannel;
    int i;

    if ((fd = fopen(file, "w")) == NULL)
	return TRUE;

    i = writePNM(file, fd, image, mode);

    if (!i && image->alpha) {
         alphachannel = ImageNewGrey(image->width, image->height);
         memcpy(alphachannel->data, image->alpha, image->width * image->height);
         for (i = 0; i<strlen(PNM_alpha_separator); i++)
	     fputc(PNM_alpha_separator[i], fd);
         i = writePNM(file, fd, alphachannel, mode);
         ImageDelete(alphachannel);
    }

    fclose(fd);

    return i;
}

int WritePNM(char *file, Image * image)
{
    return WritePNMType(file, image, Global.image_param.pnm_ascii);
}

int WriteBinaryPNM(char *file, Image * image)
{
    return WritePNMType(file, image, FALSE);
}

int WriteAsciiPNM(char *file, Image * image)
{
    return WritePNMType(file, image, TRUE);
}

int WriteAsciiPNMfd(FILE * fd, Image * image)
{
    return writePNM("filename", fd, image, TRUE);
}

int TestPNM(char *file)
{
    FILE *fd;
    int ret = FALSE;
    char buf[4];

    if ((fd = fopen(file, "r")) == NULL)
	return FALSE;

    if (fread(buf, sizeof(char), 3, fd) == 3) {
	if (buf[0] == 'P') {
	    switch (buf[1]) {
	    case '1':
	    case '2':
	    case '3':
	    case '4':
	    case '5':
	    case '6':
		ret = TRUE;
	    default:
		break;
	    }
	}
    }
    fclose(fd);

    return ret;
}
