[comp.sources.amiga] v91i009: GIFMachine 2.104 - convert GIF images into IFF SHAMs, Part02/02

amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (02/07/91)

Submitted-by: caw@miroc.Chi.IL.US (Christopher A. Wichura)
Posting-number: Volume 91, Issue 009
Archive-name: graphics/gifmachine2104/part02

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 2)."
# Contents:  Sources/main.c
# Wrapped by tadguy@ab20 on Wed Feb  6 20:18:34 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Sources/main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/main.c'\"
else
echo shar: Extracting \"'Sources/main.c'\" \(11560 characters\)
sed "s/^X//" >'Sources/main.c' <<'END_OF_FILE'
X/* Copyright 1990 by Christopher A. Wichura.
X   See file GIFMachine.doc for full description of rights.
X*/
X
X#include "GIFMachine.h"
X#include <dos/rdargs.h>
X#include <dos/dosasl.h>
X#include <dos/stdio.h>
X#include <workbench/startup.h>
X
Xstruct GIFdescriptor gdesc;
X
Xstruct RGB **BitPlane;
Xstruct RGB GlobalColourTable[256];
X
Xextern UWORD *SHAMmem;
X
Xextern BYTE *PlaneBuf;
X
Xextern BOOL Laced;
X
Xextern UBYTE *Planes[8];
X
XULONG ImageNumber;
X
Xextern struct MinList CommentList;
X
X/* our version number stuff */
Xextern UBYTE __far VersionID[];
X
X/* indicates which memory list to allocate from */
Xextern UWORD CurrentMem;
X
X/* the current GIF file handle */
XBPTR GIFfh = NULL;
X
X/* here we have some defines relating to our GADS call */
X#define ESC "\x9B"
X#define GIFMACH ESC "33;42mGIFMachine" ESC "32;40m"
X#define SPACES	ESC "32m]\n                      [" ESC "33m"
X#define BRACES	ESC "32m] [" ESC "33m"
X#define ARG_HELP	"%s v%s\nCopyright \xA9 1990 by " \
X		ESC "4;33;42mChristopher A. Wichura" ESC "0;33;40m (" \
X		ESC "32mcaw" ESC "33m@" ESC "32mmiroc.chi.il.us" ESC "33m)\n\n" \
X		ESC "31mUsage:     %s <" ESC "31mGIFfile(s)" ESC "32m> [" \
X		ESC "33mTO " ESC "31mDirectory | File" BRACES "ALL%s" \
X		"NOBORDER " ESC "32m<" ESC "31mLine Thresh" ESC "32m>] [" ESC \
X		"33mXCOMP" BRACES "DITHER%sXFLIP" BRACES "YFLIP" BRACES \
X		"DEEP" BRACES "BUFSIZE " ESC "32m<" ESC "31mSize in Kbytes" \
X		ESC "32m>]\n" ESC "31m"
X
X#define ARG_TEMPLATE "GIFfiles/M/A,TO/K,ALL/S,NOBORDER/K/N,XCOMP/S,DITHER/S,XFLIP/s,YFLIP/s,DEEP/S,BUFSIZE/K/N"
X#define ARG_FILES  0
X#define ARG_TO     1
X#define ARG_ALL    2
X#define ARG_NOBORD 3
X#define ARG_XCOMP  4
X#define ARG_DITHER 5
X#define ARG_FLIPX  6
X#define ARG_FLIPY  7
X#define ARG_DEEP   8
X#define ARG_BUFSIZ 9
X#define ARG_sizeof 10
X
X/* we will make the argument array global so that other modules can get at
X   the ARG_TO, ARG_ALL and ARG_XCOMP fields easily */
Xstruct RDArgs *ArgsPtr;
Xchar *ArgArray[ARG_sizeof];
XBOOL ArgToIsDir;
X
X/* size of the read buffered i/o space */
Xstatic ULONG BufSize = 2048;	/* default size is 2k */
X
Xint NoBorderLineThresh = 0;
X
X/* some mem pointers used when we do dithering */
XBYTE *CurrentLineErr[3];
XBYTE *LastLineErr[3];
X
X/* this flag says if we scaled the image */
XBOOL DidXComp;
X
X/* we print this when the user hits the break key */
Xchar *AbortMsg = "*** User Interruption!\n";
X
X/* storage for our library bases */
Xstruct Library *MathIeeeDoubBasBase = NULL;
Xstruct Library *IFFParseBase = NULL;
X
X/* storage for our anchor when looking for pattern matches */
Xstruct Anchor {
X		struct AnchorPath APath;
X		char              Path[256];
X	} *anchor = NULL;
X
X/* here we have our main routine */
Xint __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg)
X{
X	register char **FilesPtr;
X	struct RDArgs MyArgs;
X
X	InitMemory();
X
X	if (WBMsg) {
X		WarnMustUseCLI();
X		MyExit(5);
X	}
X
X	if (!(MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library", 0))) {
X		MyPrintf("Unable to access %s!\n", "mathieeedoubbas.library");
X		MyExit(5);
X	}
X
X	if (!(IFFParseBase = OpenLibrary("iffparse.library", 0))) {
X		MyPrintf("Unable to access %s!\n", "iffparse.library");
X		MyExit(5);
X	}
X
X	memset ((char *)&MyArgs, 0, sizeof(struct RDArgs));
X
X	if (!(MyArgs.RDA_ExtHelp = (UBYTE *)MyAlloc(strlen(ARG_HELP) + (2 * strlen(GIFMACH)) + (2 * strlen(SPACES)) + strlen(VersionID) + 1))) {
X		PutStr("Out of memory!\n");
X		MyExit(5);
X	}
X
X	MySPrintf((char *)MyArgs.RDA_ExtHelp, ARG_HELP, GIFMACH, VersionID, GIFMACH, SPACES, SPACES);
X
X	if (!(ArgsPtr = ReadArgs(ARG_TEMPLATE, (LONG *)&ArgArray, &MyArgs))) {
X		PrintFault(IoErr(), NULL);
X		MyExit(5);
X	}
X
X	MyFree((char *)MyArgs.RDA_ExtHelp);
X
X	if (ArgArray[ARG_TO])
X		ArgToIsDir = IsDir(ArgArray[ARG_TO]);
X
X	if (ArgArray[ARG_NOBORD]) {
X		NoBorderLineThresh = *((LONG *)ArgArray[ARG_NOBORD]);
X		if (NoBorderLineThresh < 0 || NoBorderLineThresh > 100) {
X			PutStr("Invalid NOBORDER line threshhold specified.\n");
X			MyExit(3);
X		}
X	}
X
X	if (ArgArray[ARG_BUFSIZ])
X		BufSize = *((LONG *)ArgArray[ARG_BUFSIZ]) * 1024;
X
X	if (!(FilesPtr = (char **)ArgArray[ARG_FILES])) {
X		PutStr("No GIF files selected.\n");
X		MyExit(3);
X	}
X
X	InitDiff();	/* one time init for the RGBdiff function */
X
X	while (*FilesPtr)
X		DoPattern(*FilesPtr++);
X
X	MyExit(0);
X}
X
Xvoid MyExit(ULONG result)
X{
X	if (GIFfh)
X		Close(GIFfh);
X
X	if (IFFParseBase)
X		CloseLibrary(IFFParseBase);
X
X	if (MathIeeeDoubBasBase)
X		CloseLibrary(MathIeeeDoubBasBase);
X
X	if (anchor)
X		MatchEnd(&anchor->APath);
X
X	if (ArgsPtr)
X		FreeArgs(ArgsPtr);
X
X	FreeAll(1);
X	FreeAll(0);
X
X	XCEXIT(result);
X}
X
X
X/* this will walk through a pattern doing conversions */
Xvoid DoPattern(char *pat)
X{
X	register int error;
X
X	if (!(anchor = (struct Anchor *)MyAlloc(sizeof(struct Anchor)))) {
X		PutStr("Out of memory!\n");
X		MyExit(10);
X	}
X
X	anchor->APath.ap_Strlen = sizeof(anchor->Path);
X	anchor->APath.ap_Flags = APF_DOWILD;
X	anchor->APath.ap_BreakBits = SIGBREAKF_CTRL_C;
X
X	error = MatchFirst(pat, &anchor->APath);
X
X	while (!error) {
X		if (anchor->APath.ap_Info.fib_DirEntryType > 0) {
X			if (ArgArray[ARG_ALL]) {
X				if (!(anchor->APath.ap_Flags & APF_DIDDIR))
X					anchor->APath.ap_Flags |= APF_DODIR;
X				anchor->APath.ap_Flags &= ~APF_DIDDIR;
X			}
X		} else
X			Convert(anchor->APath.ap_Buf);
X
X		error = MatchNext(&anchor->APath);
X	}
X
X	MatchEnd(&anchor->APath);
X	MyFree((char *)anchor);
X	anchor = NULL;
X
X	switch(error) {
X		case ERROR_BREAK:
X			PutStr(AbortMsg);
X			MyExit(ABORTEXITVAL);
X			break;
X
X		case ERROR_OBJECT_NOT_FOUND:
X			PutStr("File not found.\n");
X			break;
X
X		case ERROR_BUFFER_OVERFLOW:
X			PutStr("Path too long!\n");
X			break;
X
X		case ERROR_NO_MORE_ENTRIES:	/* normal termination */
X			break;
X
X		default:
X			MyPrintf("I/O Error #%ld!\n", error);
X			break;
X	}
X}
X
X/* here we have the routine that gets ready to do the conversion */
Xvoid Convert(char *name)
X{
X	register int index;
X	char *basename;
X	char *ptr;
X	char sig[7];
X	int size;
X	int error;
X	int colours;
X	LONG cmdcode;
X	
X	struct DateStamp StartTime, EndTime;
X
X	CurrentMem++;
X
X	if (!(GIFfh = Open(name, MODE_OLDFILE))) {
X		MyPrintf("Error #%ld trying to open %s...\n", IoErr(), name);
X		goto LeaveConvert;
X	}
X
X	SetVBuf(GIFfh, BUF_FULL, BufSize);
X
X	sig[6] = NULL;
X
X	if (FRead(GIFfh, sig, 1, 6) != 6 || strncmp("GIF", sig, 3)) {
X		MyPrintf("%s is not a GIF file...\n", name);
X		goto LeaveConvert;
X	}
X
X	MyPrintf("Converting %s ", name);
X
X	basename = FilePart(name);
X	ptr = basename + strlen(basename) - 4;
X
X	if (!strnicmp(".gif", ptr, 4))
X		*ptr = NULL;
X
X	size = strlen(basename) + 6;
X
X	if (ArgArray[ARG_TO]) {
X		if (ArgToIsDir)
X			size += strlen(ArgArray[ARG_TO]) + 1;
X		else
X			size = strlen(ArgArray[ARG_TO]) + 1;
X	}
X
X	if (!(ptr = MyAlloc(size))) {
X		PutStr("... Out of memory!\n");
X		goto LeaveConvert;
X	}
X
X	if (ArgArray[ARG_TO]) {
X		strcpy(ptr, ArgArray[ARG_TO]);
X
X		if (ArgToIsDir) {
X			AddPart(ptr, basename, size);
X			strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
X		}
X	} else {
X		strcpy(ptr, basename);
X		strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
X	}
X
X	MyPrintf("to %s...\n", ptr);
X
X	DateStamp((LONG *)&StartTime);
X
X	if (FRead(GIFfh, (char *)&gdesc, 1, 7) != 7) {
X		PutStr("Error reading screen descriptor.\n");
X		goto LeaveConvert;
X	}
X
X	FlipWord(&gdesc.gd_Width);
X	FlipWord(&gdesc.gd_Height);
X
X	MyPrintf("Signature = \"%s\", Width = %ld, Height = %ld\n",
X		sig, gdesc.gd_Width, gdesc.gd_Height);
X
X	NewList((struct List *)&CommentList);
X
X	DidXComp = 0;
X	colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
X
X	if (!(gdesc.gd_ColInfo & 1L << 7)) {
X		PutStr("No global colour map supplied, using internal.\n");
X
X		for (index = 0; index < colours; index++) {
X			GlobalColourTable[index].rgb_Red   =
X			GlobalColourTable[index].rgb_Green =
X			GlobalColourTable[index].rgb_Blue  = index;
X		}
X	} else {
X		MyPrintf("Global colour map contains %ld entries.\n", colours);
X
X		for (index = 0; index < colours; index++) {
X			if (FRead(GIFfh, &GlobalColourTable[index], 1, 3) != 3) {
X				MyPrintf("Error reading global colour #%ld.\n",
X					index);
X				goto LeaveConvert;
X			}
X		}
X	}
X
X	size = ((gdesc.gd_Width + 7) / 8) + 1;
X	size += (size + 127) >> 7;
X
X	if (!(BitPlane = (struct RGB **)MyAlloc(gdesc.gd_Height * sizeof(struct RGB *))) ||
X	    !(SHAMmem  = (UWORD *)MyAlloc(gdesc.gd_Height * 16 * sizeof(UWORD))) ||
X	    !(PlaneBuf = (BYTE *)MyAlloc(size))) {
X		PutStr("Out of memory trying to allocate picture.\n");
X		goto LeaveConvert;
X	}
X
X	size = (gdesc.gd_Width + 1) * sizeof(struct RGB);
X
X	for (index = 0; index < gdesc.gd_Height; index++)
X		if (!(BitPlane[index] = (struct RGB *)MyAlloc(size))) {
X			PutStr("Out of memory trying to allocate picture.\n");
X			goto LeaveConvert;
X		}
X
X	size = ((gdesc.gd_Width + 7) / 8) + 1;
X	for (index = 0; index < (ArgArray[ARG_DEEP] ? 8 : 6); index++)
X		if (!(Planes[index] = (UBYTE *)MyAlloc(size))) {
X			PutStr("Out of memory trying to allocate picture.\n");
X			goto LeaveConvert;
X		}
X
X	if (ArgArray[ARG_DITHER]) {
X		size = gdesc.gd_Width * sizeof(BYTE);
X
X		for (index = 0; index < 3; index++)
X			if (!(CurrentLineErr[index] = (BYTE *)MyAlloc(size)) ||
X			    !(LastLineErr[index] = (BYTE *)MyAlloc(size))) {
X				PutStr("Out of memory trying to allocate picture.\n");
X				goto LeaveConvert;
X			}
X	}
X
X	ImageNumber = 1;
X
X	/* at this point we start looking for images, extensions or the gif
X	   terminator.  we call the appropriate routine as we find each. */
X
X	for (error = FALSE; error == FALSE;) {
X		if ((cmdcode = FGetC(GIFfh)) == -1) {
X			PutStr("...I/O error reading GIF file.\n");
X			goto LeaveConvert;
X		}
X
X		switch(cmdcode) {
X			case GIF_IMAGE:
X				error = DoImage(GIFfh);
X				break;
X
X			case GIF_EXTENSION:
X				error = DoExtension(GIFfh);
X				break;
X
X			case GIF_TERMINATOR:
X				if (ArgArray[ARG_NOBORD])
X					StripBorder();
X
X				if (ArgArray[ARG_FLIPX])
X					DoXFlip();
X
X				if (ArgArray[ARG_FLIPY])
X					DoYFlip();
X
X				if (ArgArray[ARG_XCOMP]) {
X					DoXComp();
X					DidXComp = 1;
X				}
X
X				if (gdesc.gd_Height > 200 && DidXComp)
X					Laced = TRUE;
X				else
X					Laced = FALSE;
X
X				if (!ArgArray[ARG_DEEP]) {
X					if (ArgArray[ARG_DITHER])
X						DitherTo12();
X					else
X						ReduceTo12();
X
X					GIFtoSHAM();
X				}
X
X				error = WriteIFF(ptr, (BOOL)ArgArray[ARG_DEEP]);
X				break;
X
X			default:
X				MyPrintf("...Unknown directive #%ld encountered.\n",
X					cmdcode);
X				error = TRUE;
X		}
X	}
X
X	DateStamp((ULONG *)&EndTime);
X
X	{
X		register ULONG Hours;
X		register ULONG Minutes;
X		register ULONG Seconds;
X		register ULONG Seconds2;
X	
X		Seconds = (EndTime.ds_Days * 86400) + (EndTime.ds_Minute * 60) + (EndTime.ds_Tick / TICKS_PER_SECOND);
X		Seconds2 = (StartTime.ds_Days * 86400) + (StartTime.ds_Minute * 60) + (StartTime.ds_Tick / TICKS_PER_SECOND);
X
X		Seconds -= Seconds2;
X
X		Hours = Seconds / 3600;
X		Seconds -= Hours * 3600;
X
X		Minutes = Seconds / 60;
X		Seconds -= Minutes * 60;
X
X		MyPrintf("...Conversion time was %ld hour%s, %ld minute%s and %ld second%s.\n",
X			Hours, (Hours != 1 ? "s" : ""),
X			Minutes, (Minutes != 1 ? "s" : ""),
X			Seconds, (Seconds != 1 ? "s" : ""));
X	}
X
XLeaveConvert:
X	FreeAll(CurrentMem--);
X
X	if (GIFfh) {
X		Close(GIFfh);
X		GIFfh = NULL;
X	}
X}
X
X/* this will check to see if we have a directory or not */
XBOOL IsDir(char *name)
X{
X	register BPTR lock;
X	register BOOL result = FALSE;
X
X	struct FileInfoBlock __aligned fib;
X
X	if (lock = Lock(name, ACCESS_READ)) {
X		if (Examine(lock, &fib)) {
X			if (fib.fib_DirEntryType > 0)
X				result = TRUE;
X		}
X		UnLock(lock);
X	}
X
X	return result;
X}
X
X/* this will convert a word from LSB/MSB to MSB/LSB */
Xvoid FlipWord(UWORD *word)
X{
X	register UBYTE swap1;
X	register UBYTE swap2;
X
X	swap1 = *word & 0xFF;
X	swap2 = (*word & 0xFF00) >> 8;
X	*word = swap1 << 8 | swap2;
X}
END_OF_FILE
if test 11560 -ne `wc -c <'Sources/main.c'`; then
    echo shar: \"'Sources/main.c'\" unpacked with wrong size!
fi
# end of 'Sources/main.c'
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.misc.