/*************************************************************************/
/*                                                                       */
/*  Copyright (c) 1994 Stanford University                               */
/*                                                                       */
/*  All rights reserved.                                                 */
/*                                                                       */
/*  Permission is given to use, copy, and modify this software for any   */
/*  non-commercial purpose as long as this copyright notice is not       */
/*  removed.  All other uses, including redistribution in whole or in    */
/*  part, are forbidden without prior written permission.                */
/*                                                                       */
/*  This software is provided with absolutely no warranty and no         */
/*  support.                                                             */
/*                                                                       */
/*************************************************************************/

#ifndef USE_PROTOTYPES
#define USE_PROTOTYPES 1
#endif

#ifndef lint
static char sccsid[] = "@(#)savemap.c	1.3 2/6/9q";
#endif

#include <stdio.h>
#include <tiffioP.h>
#include "tiff_rgba_io.h"

#define	streq(a,b)	(strcmp(a,b) == 0)

#define BYTESWAP 

static u_char	rbuf[2048];
static u_char	gbuf[2048];
static u_char	bbuf[2048];
static u_char	abuf[2048];
static u_char	*scanline = NULL;

static int	rowsperstrip = -1;
static int	compression = COMPRESSION_LZW;
static int	config = PLANARCONFIG_CONTIG;
static int	orientation = ORIENTATION_BOTLEFT;

#define	MIN(a,b)	((a)<(b)?(a):(b))
#define	ABS(x)		((x)<0?-(x):(x))


int
tiff_save_rgba(char *name, int *pixels, int width, int height)
{
	TIFF *tif;
	int xsize, ysize;
	int xorg, yorg;
	int y, i;
	int *pos;

	xsize = width;
	ysize = height;

	tif = TIFFOpen(name, "w");
	if (tif == NULL)
	    return 0;

	TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, xsize);
	TIFFSetField(tif, TIFFTAG_IMAGELENGTH, ysize);
	TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
	TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 4);
	TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
	TIFFSetField(tif, TIFFTAG_PLANARCONFIG, config);
	TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);
	TIFFSetField(tif, TIFFTAG_ORIENTATION, orientation);
	if (rowsperstrip <= 0)
		rowsperstrip = (8*1024)/TIFFScanlineSize(tif);
	TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,
	    rowsperstrip == 0 ? 1 : rowsperstrip);
	if (config == PLANARCONFIG_CONTIG)
		scanline = (u_char *)malloc(TIFFScanlineSize(tif));

	for (y = 0, pos = pixels; y < ysize;
			y++, pos += xsize) {

	    if (config == PLANARCONFIG_CONTIG) {
#ifdef BYTESWAP
		register char *sp = (char *) pos;
		register char *tp = (char *) scanline;
		register int x;

		for (x = 0; x < xsize; x++) {
		    tp[3] = sp[0];
		    tp[2] = sp[1];
		    tp[1] = sp[2];
		    tp[0] = sp[3];
			sp += 4;
			tp += 4;
		}
#endif
#ifndef BYTESWAP
                bcopy(pos, scanline, xsize*4);
#endif
		if (TIFFWriteScanline(tif, scanline, y, 0) < 0)
			break;
	    }
	    else if (config == PLANARCONFIG_SEPARATE) {

		register char *pp = (char *) pos;
		register int x;

		for (x = 0; x < xsize; x++) {
		    rbuf[x] = pp[0];
		    gbuf[x] = pp[1];
		    bbuf[x] = pp[2];
		    abuf[x] = pp[3];
			pp += 4;
		}
		if (TIFFWriteScanline(tif, rbuf, y, 0) < 0 ||
		    TIFFWriteScanline(tif, gbuf, y, 1) < 0 ||
		    TIFFWriteScanline(tif, bbuf, y, 2) < 0 ||
		    TIFFWriteScanline(tif, abuf, y, 3) < 0)
			break;
	    } 
	}
    (void) TIFFClose(tif);
    return 1;
}


int
tiff_load_rgba(char *file, int **pixels, int *width, int *height)
{
	TIFF *tif;
	u_short config, bitspersample, samplesperpixel;
	u_long xsize, ysize;
	register int x, y, rowbytes;
	u_char *buf;
        int temp;
	ushort orient;
        register char *tp ;
        register char *sp ;

	if ((tif = TIFFOpen(file, "r")) == NULL) {
	    fprintf(stderr, "%s: error opening file.\n", file);
	    return 0;
	}

	TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
	switch (bitspersample) {
	case 8:
		break;
	default:
		fprintf(stderr, "%s: Can not image a %d-bit/sample image.\n",
		    file, bitspersample);
	        return 0;
	}
	TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
        switch (samplesperpixel) {
	case 3: case 4:
		break;
	default:
		fprintf(stderr, "%s: Can not image a %d samples/pixel image.\n",
		    file, bitspersample);
	        return 0;
	}
	TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &xsize);
	TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &ysize);
	TIFFGetField(tif, TIFFTAG_ORIENTATION, &orient);
	switch (orient) {
	case ORIENTATION_TOPLEFT:  case ORIENTATION_BOTLEFT:
	    break;
	default:
	    fprintf(stderr, "%s: Unsupported orientation.  Will assume ORIENTATION_TOPLEFT.\n" , file);
	    break;
	}

	rowbytes =TIFFScanlineSize(tif);

	*width = xsize;
	*height = ysize;
	*pixels = (int *) malloc(ysize*xsize*sizeof(int));


        switch (samplesperpixel) {
	    case 3:
		tp = (char *) (*pixels);
		if (orient != ORIENTATION_BOTLEFT)
		    tp += 4 * (*height-1) * *width;
		buf = (u_char *) malloc(rowbytes);
		
		for (y = 0; y < ysize; y++) {
		    if (TIFFReadScanline(tif, buf, y, 0) < 0)
			break;

#ifdef BYTESWAP
		    sp = (char *) buf;

		    for (x = 0; x < xsize; x++) {
			tp[3] = sp[0];
			tp[2] = sp[1];
			tp[1] = sp[2];
			tp[0] = 0;
			tp += 4;
			sp += 3;
		    }
#endif

		if (orient != ORIENTATION_BOTLEFT)
		    tp -= 8* *width;
		}
		break;

	    case 4:
		buf = (u_char *) (*pixels);
		if (orient != ORIENTATION_BOTLEFT)
		    buf += (*height-1) * rowbytes;
		for (y = 0; y < ysize; y++) {
		    if (TIFFReadScanline(tif, buf, y, 0) < 0)
			break;


#ifdef BYTESWAP
		    tp = (char *) buf;
		    sp = (char *) &temp;

		    for (x = 0; x < xsize; x++) {
			temp = *((int *)tp);
			tp[3] = sp[0];
			tp[2] = sp[1];
			tp[1] = sp[2];
			tp[0] = sp[3];
			tp += 4;
		    }
#endif
		    if (orient != ORIENTATION_BOTLEFT)
			buf -= rowbytes;
		    else
			buf += rowbytes;
		}
		break;

	    default:
		fprintf(stderr, "%s: Can not image a %d samples/pixel image.\n",
		    file, bitspersample);
	        return 0;
	}

	(void) TIFFClose(tif);
	return 1;
}
