// tiff2ppm.m: Translate a TIFF file to PPM format
// Usage: tiff2ppm tifffile  > ppmfile
// Compile with: 
//   cc -O -g tiff2ppm.m -o tiff2ppm -lsys_s -lNeXT_s -arch m68k -arch i386
// Written by cahalan@clouds.gsfc.nasa.gov, October, 1994.
#include <stdio.h>
#import <dpsclient/event.h>
#import <appkit/appkit.h>
#define maxVal 255 
#define HI	240  // upper 4 bits
#define LO	15   // lower 4 bits

	struct Color {unsigned char *R; unsigned char *G; unsigned char *B;
				unsigned char *A;};
	struct Color *pColor;
	BOOL isPlanar = FALSE, hasAlpha = FALSE;
	int width, height, samples = 3, bitsPerSample = 8, numColors = 3;
	unsigned char r, g, b, invert = maxVal;
	int colorSpace = NX_RGBColorSpace;

void die(char *s) {fprintf(stderr,"%s\n",s);exit(1);}

void writePPM(void)
    {
	register int x, y, i;

	fprintf(stdout, "P6\n");
	fprintf(stdout, "%d %d\n", width, height);
	fprintf(stdout, "%d\n", maxVal);

//   ********************* grayscale with "min-is-white"
	if (samples==1 && bitsPerSample == 8) {
		if(colorSpace == NX_OneIsWhiteColorSpace) invert = 0;
		for (y=0; y<height; y++) for (x=0; x<width; x++)  {
			r = *pColor->R++ ^ invert; 
			for (i=0; i<3; i++) putchar(r);
		}
	return;
	}

//   ********************* increment Color ptr for planar or non-planar
		switch(bitsPerSample) {
			case 1: 
			case 2: die("Can't do monochrome!\n");
				break;
			case 4: 
			     if(isPlanar) {samples = samples >> 1;
			      for (y=0; y<height; y++) for (x=0; x<width/2; x++)  {
				r = *pColor->R; g = *pColor->G; b = *pColor->B;
				putchar(r & HI);
				putchar(g & HI);
				putchar(b & HI);
				putchar(r << 4);
				putchar(g << 4);
				putchar(b << 4);
				pColor->R++; pColor->G++; pColor->B++; 
			     } }
			     else if(hasAlpha) { samples = samples >> 1;
			      for (y=0; y<height; y++) for (x=0; x<width; x++)  {
				r = *pColor->R; g = *pColor->G;
				putchar(r & HI);
				putchar(r << 4);
				putchar(g & HI);
				pColor->R += samples; 
				pColor->G += samples; 
			     } }
			     else for (y=0; y<height; y++) for (x=0; x<width/2; x++)  {
				r = *pColor->R; g = *pColor->G; b = *pColor->B;
				putchar(r & HI );
				putchar(r << 4);
				putchar(g & HI);
				putchar(g << 4);
				putchar(b & HI);
				putchar(b << 4);
				pColor->R += samples; 
				pColor->G += samples; 
				pColor->B += samples;
			     }
				break;
			case 8: 
			    for (y=0; y<height; y++) for (x=0; x<width; x++)  {
				fwrite(pColor->R, 1, 1, stdout);
				fwrite(pColor->G, 1, 1, stdout);
				fwrite(pColor->B, 1, 1, stdout);
				if(isPlanar) {pColor->R++; pColor->G++; pColor->B++;}
				else {
					pColor->R += samples; 
					pColor->G += samples; 
					pColor->B += samples;
				}
			     }
				break;
			default: die("Don't recognize this TIFF type!\n");
				break;
		}
    }


void main(int argc, char *argv[])
{
   id tiff;
   unsigned char *planeData[5] = {NULL, NULL, NULL, NULL, NULL};
   unsigned char *meshedData = NULL;
   NXSize size;

/*   ********************* check usage  ****************
   if(argc > 1) {
	fprintf(stderr, "argc = %d\n", argc);
	fprintf(stderr, "Translating %s to PPM\n", argv[1]);
   }
   else die("Usage: tiff2ppm tiffFile > ppmFile");
*/

//   ********************* read TIFF, load into imageRep *****
   tiff = [[NXBitmapImageRep alloc] initFromFile:argv[1]];

//   ********************* get a pointer to the image data *****
   [tiff getDataPlanes:planeData];
/*   fprintf(stderr, "planeData[] = {%ld, %ld, %ld, %ld, %ld}\n",
			planeData[0], planeData[1], planeData[2],
			planeData[3], planeData[4]);
*/
//  ********************* get image dimensions, etc
   [tiff getSize:&size];
   width = size.width;
   height = size.height;
   samples = [tiff samplesPerPixel];
   bitsPerSample = [tiff bitsPerSample];
   numColors = [tiff numColors];
   hasAlpha = [tiff hasAlpha];
   colorSpace = [tiff colorSpace];
fprintf(stderr, "width = %d\t height = %d\n", width, height);
fprintf(stderr, "samples = %d\t bitsPerSample = %d\n", samples, bitsPerSample);
fprintf(stderr, "numColors = %d\t hasAlpha = %d\t colorSpace = %d\n", 
				numColors, hasAlpha, colorSpace);

//   ********************* init Color ptr for planar or non-planar
   pColor = malloc(sizeof(struct Color));
   if(isPlanar = [tiff isPlanar]) {
   	pColor->R = planeData[0];
	pColor->G = planeData[1];
	pColor->B = planeData[2];
   } else {
   	meshedData = planeData[0];
	pColor->R = meshedData;
	pColor->G = meshedData+1; 
	pColor->B = meshedData+2;
   }

//   ********************* write out the PPM file
   writePPM();
  
//  ********************* cleanup  ****************************
   [tiff free];
 }
