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.