/*------------------------------------------------------------------------------
	squeezeImage.m	Copyright (c) 1991, Karl Kraft;

	SYNOPSIS
	cc -o squeezeImage -lNeXT_s squeezeImage.m

		squeezeimage takes a tiff file and compresses it
		using either LZW, Packbits, or JPEG compression.
		
You are free to study this program,
and use any indistinguishable part
of it in any program, without permission
of any kind.

	REVISIONS
K^2	Karl Kraft, Ensuing Technologies, karl@bodi.portal.com
--
	Date			Who		Modification
	6/24/91;		K^2		Prepared for release.
	6/17/91;		K^2		Began Revision tracking.
------------------------------------------------------------------------------*/

#import <stdio.h>			// For printing error messages
#import <stdlib.h>			// Assorted functions
#import <objc/Object.h>			// For our superclass
#import <appkit/NXBitmapImageRep.h>  	// to read,compress, and write tiffs
#import <streams/streams.h>		// To read and write tiffs
#import <appkit/tiff.h>			// Useful header goodies

//This function will tell us the size of the stream.  For some reason this isn't builtin.
int	streamSize(NXStream *theStream)
{
	char *addr;
	int len;
	int maxlen;
	NXGetMemoryBuffer(theStream, &addr, &len,&maxlen);
	return len;
}


// Here we create a small object that knows how to read and compress a tiff file.
@interface Mumble:Object
{
	id theBitmap;
}

+readFile:(char *)filename;
-writeBest:(char *)filename level:(int)level;
@end


@implementation Mumble
// This object is so simple that we do not bother with writing a init method.
// Instead we create a class method that makes a Mumble from a tiff file.
+readFile:(char *)filename;
{
	self = [[Mumble alloc] init];
	theBitmap = [[NXBitmapImageRep alloc] initFromFile:filename];
	return self;
}


// This is the heart of the program.  We write each type of compression, keeping track of who is best.
// For small images, No compression may be best, so we have to set that up as a default.
//filename is the file to write too

-writeBest:(char *)filename level:(int)level;
{
	NXStream *beststream;
	NXStream *tempstream;
	NXStream *swapStream;
	char *bestmethod;
	
	bestmethod = "No";
	beststream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
	[theBitmap writeTIFF:beststream 				usingCompression:NX_TIFF_COMPRESSION_NONE];

if (level >=1) {
	tempstream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
	[theBitmap writeTIFF:tempstream 				usingCompression:NX_TIFF_COMPRESSION_PACKBITS];
	if (streamSize(tempstream)<streamSize(beststream)) {
		bestmethod = "PackBits";
		swapStream = tempstream;
		tempstream=beststream;
		beststream=swapStream;
	}	
	NXCloseMemory(tempstream, NX_FREEBUFFER);
}


if (level >=2) {
	tempstream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
	[theBitmap writeTIFF:tempstream 				usingCompression:NX_TIFF_COMPRESSION_LZW];
	if (streamSize(tempstream)<streamSize(beststream)) {
		bestmethod = "LZW";
		swapStream = tempstream;
		tempstream=beststream;
		beststream=swapStream;
	}	
	NXCloseMemory(tempstream, NX_FREEBUFFER);
}


if (level >=3) {
	tempstream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
	[theBitmap writeTIFF:tempstream 				usingCompression:NX_TIFF_COMPRESSION_JPEG
		andFactor:level];
	if (streamSize(tempstream)<streamSize(beststream)) {
		bestmethod = "JPEG";
		swapStream = tempstream;
		tempstream=beststream;
		beststream=swapStream;
	}	
	NXCloseMemory(tempstream, NX_FREEBUFFER);
}
	printf("Saving to %s with %s compression.\n",filename,bestmethod);
	NXSaveToFile(beststream, filename);
	return self;
}

@end

main (int argc, char *argv[])
{
	id anImage;
	int level;
	
	if ((argc<3) || (argc>4)) {
		fprintf(stderr,"Usage:%s infile outfile [level]\n",argv[0]);
		fprintf(stderr,"level = {0..255}\n0= No Compression\n1= or Packbits \n");
		fprintf(stderr,"2=  or LZW\n 3+  Allow JPEG (lose quality)\n");
		exit -1;
	}
	if (argc==3) level = 2; else level=atoi(argv[3]);
	[[[Mumble readFile:argv[1]] writeBest:argv[2] level:level] free];
	exit(0);
}

