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.