--- a
+++ b/ppm.c
@@ -0,0 +1,308 @@
+/* Panorama_Tools	-	Generate, Edit and Convert Panoramic Images
+   Copyright (C) 1998,1999 - Helmut Dersch  der@fh-furtwangen.de
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*------------------------------------------------------------*/
+
+// Functions to read and write ppm format
+
+
+#include "filter.h"
+
+
+static int readPPMFileHeader(file_spec src, Image *im);
+
+
+// image is allocated, but not image data
+
+int readPPM(Image *im, fullPath *sfile)
+{
+	file_spec	src;
+	long count;
+	
+	if( myopen( sfile, read_bin, src ) )
+	{	
+		PrintError("Error Opening Image File");
+		return -1;
+	}
+	
+
+	if( readPPMFileHeader(src, im) != 0 )
+	{
+		PrintError("Error Reading File Header");
+		myclose( src );
+		return -1;
+	}
+
+	im->bitsPerPixel	= 24;	
+	im->bytesPerLine 	= im->width * 3;
+	im->dataSize		= im->bytesPerLine * im->height;
+	
+	im->data			= (unsigned char**) mymalloc( im->width * im->height * 4 );
+	if ( im->data == NULL )
+	{
+		PrintError("Not enough memory");
+		myclose( src );
+		return -1;
+	}
+	
+	count = 	im->width * im->height * 3;
+	
+	myread(src,count,*(im->data));
+	
+	if( count != im->width * im->height * 3 )
+	{
+		PrintError("Error Reading Image Data");
+		myclose( src );
+		return -1;
+	}
+
+	myclose( src );
+	ThreeToFourBPP( im );
+	return 0;
+}
+	
+
+static int readPPMFileHeader(file_spec src, Image *im)
+{
+	int 			i;
+	char 			smallBuf[32], c;
+	long 			count = 1;
+	
+	/* read the file header (including height and width) */
+
+	im->height = -1;
+	while(im->height == -1)
+	{
+		myread(src,count,&c); 
+		if( count != 1 ) return 1;
+		switch(c)
+		{
+			case '#':
+				/* comment line -- skip it */
+				while(c != 0x0A	&& c != 0x0D && count == 1)
+					myread(src,count,&c); 
+				break;
+			case ' ': case '\012': case '\t': case '\015':
+				/* random whitespace... just ignore it. */
+				break;
+			case 'P':
+				/* magic number */
+				myread(src,count,&c); 
+				if(c != '6' )
+				{
+					PrintError("Bad magic number in input file");
+					return(-1);
+				}
+				/* there should be one whitespace character */
+				break;
+			case '0': case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+				/* read width */
+				for(i=0;isdigit(c) && (i+1 < sizeof(smallBuf));i++)
+				{
+					smallBuf[i] = c;
+					myread(src,count,&c); 
+					if( count != 1 ) return  -1;
+				}
+				if(!isspace(c))
+				{
+					PrintError("Bad input file format");
+					return -1;
+				}
+				smallBuf[i] = 0;
+				im->width = atoi(smallBuf);
+				/* read height */
+				myread(src,count,&c); 
+				if( count != 1 ) return  -1;
+				for(i=0;isdigit(c) && (i+1 < sizeof(smallBuf));i++)
+				{
+					smallBuf[i] = c;
+					myread(src,count,&c); 
+					if( count != 1 ) return  -1;
+				}
+				if(!isspace(c))
+				{
+					PrintError("Bad input file format");
+					return -1;
+				}
+				smallBuf[i] = 0;
+				im->height = atoi(smallBuf);
+				/* read numColors */
+				myread(src,count,&c); 
+				if( count != 1 ) return  -1;
+				for(i=0;isdigit(c) && (i+1 < sizeof(smallBuf));i++)
+				{
+					smallBuf[i] = c;
+					myread(src,count,&c); 
+					if( count != 1 ) return  -1;
+				}
+				if(!isspace(c))
+				{
+					PrintError("Bad input file format");
+					return -1;
+				}
+				smallBuf[i] = 0;
+				if(atoi(smallBuf) != 255)
+					PrintError("Warning: Wrong Colordepth!");
+				break;
+			default:
+					PrintError("Bad input file format");
+					return(-1);
+				break;
+		}
+	}
+			
+	/* the header has been taken care of.  The rest of the file is just image data. */	
+	return(0);
+}
+
+
+
+int writePPM( Image *im, fullPath *sfile )
+{
+	char header[30];
+	long count;
+	file_spec	fnum;
+	int y, cy, cpy;
+	unsigned char* data;
+
+
+
+	if(  myopen( sfile, write_bin, fnum )   )
+	{	
+		PrintError("Error Writing Image File");
+		return -1;
+	}
+
+	if( im->bitsPerPixel == 32 )
+		FourToThreeBPP	( im );
+		
+	if( im->bytesPerLine != im->width * 3 ) 	// Eliminate Pad bytes
+	{
+		data = *(im->data);
+		for(y=0; y<im->height; y++)
+		{
+			cy = im->height * im->bytesPerLine;
+			cpy = im->height * im->width * 3;
+
+			memcpy( data+cpy, data+cy, im->width * 3);
+		}
+		im->bytesPerLine = im->width * 3;
+		im->dataSize = im->height * im->bytesPerLine;
+	}
+					
+
+	sprintf( header, "P6\n%ld %ld\n%ld\n", im->width, im->height, 255L);
+
+	count = strlen( header );
+	mywrite( fnum, count, header );
+	
+	if( count != strlen( header ))
+	{
+		PrintError("Error writing file header");
+		return -1;
+	}
+	
+	count = im->dataSize;
+	mywrite( fnum, count, *(im->data) );
+	
+	if( count != im->dataSize )
+	{
+		PrintError("Error writing image data");
+		return -1;
+	}
+	
+	myclose( fnum );
+	return 0;
+}
+
+int makeTempPath( fullPath *path ){
+	file_spec fnum;
+	char *dir;
+	static int try = 0;
+	int i;
+	char fname[24];
+
+
+	dir = strrchr( path->name, '/' );
+	if( dir == NULL ){
+		dir = path->name;
+	}else{
+		dir++;
+	}
+
+	
+#define MAX_TEMP_TRY	1000
+	
+	try++;
+	
+	for(i=0; i < MAX_TEMP_TRY; try++,i++){
+		sprintf( fname, "_PTStitcher_tmp_%d", try );
+		if( strlen( fname ) + 2 < sizeof(path->name) - (strlen(path->name)-strlen(dir)) ){
+			sprintf( dir, "%s", fname );
+			if( myopen( path, read_bin, fnum ))
+				break;
+			myclose( fnum );
+		}else{
+			PrintError("Path too long");
+			return -1;
+		}
+	}
+	if( try < MAX_TEMP_TRY )
+		return 0;
+	else
+		return -1;
+	
+}
+
+
+int readImage( Image *im, fullPath *sfile )
+{
+	char *ext,extension[4];
+	int i;
+	
+	
+	ext = strrchr( sfile->name, '.' );
+	if( ext == NULL || strlen(ext) != 4 )
+	{
+		PrintError("Unsupported File Format: Must be JPEG, TIF or PPM");
+		return -1;
+	}
+	ext++;
+	strcpy( extension, ext );
+	for(i=0; i<3; i++)
+		extension[i] = tolower(extension[i]);
+
+	
+	if( strcmp( extension, "ppm" ) == 0 )
+		return readPPM(  im, sfile );
+	else if( strcmp( extension, "jpg" ) == 0 )
+		return readJPEG(im, sfile );
+	else if( strcmp( extension, "tif" ) == 0 )
+		return readTIFF(im, sfile );
+	else{
+		PrintError("Unsupported File Format: Must be JPEG, TIF or PPM");
+		return -1;
+	}
+}
+		
+
+int writeImage( Image *im, fullPath *sfile ){
+	return writePPM( im, sfile );
+}
+
+