[comp.sources.amiga] v90i245: GIFMachine 1.0 - convert GIF pictures into IFF SHAM, Part01/02

amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (09/04/90)

Submitted-by: caw@miroc.Chi.IL.US (Christopher A. Wichura)
Posting-number: Volume 90, Issue 245
Archive-name: util/gifmachine-1.0/part01

[ uuencoded executable enclosed  ...tad ]

GIFMachine will convert GIF pictures into IFF SHAM format (and __ONLY__
SHAM).  I wrote it as a replacement for ShamSharp, which I feel has a
number of problems:  GURU's in SHAM more on GIFs with greater than 400
lines, does not fully conform to the GIF spec, always drops the odd pixels
out on images wider than 320 pixels, writes bad IFFs on a regular basis,
etc.  GIFMachine has none of these problems, and tends to get less for the
colour error as well.

GIFMachine requires the arp library, v39 or greater, to be present.  It
runs just dandy on my 3000, too! :-)  On a stock 500/1000/2000 it takes
around a half hour to convert an image around 640x480 (as opposed to 2 and
a half minutes on the 3000).  GIFMachine has been tested with images as
large as 1152x890.

Please note that unless you have the viewer `Mostra', by S. Vigna, images with
>400 lines can not be properly viewed after conversion.  This is because
the other SHAM viewers either 1) Assume nothing greater than 400 exists and
will not allow scrolling around, or 2) allow scrolling, but don't rebuild
the copper list when scrolling vertically so as soon as you scroll down the
image gets scragged.

Lattice C 5.05 source code has been provided in this archive, as well as an
lmkfile to build it.  Manx users will probably have to play around with the
custom startup code I use, but the rest ought to work more or less
straight.  Note that I have my ARP glue routines in the file LIB:ARP
instead of in the arpglue.o file that is distributed with the ARP 1.3
programmers' kit.

-=> CAW

#!/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 1 (of 2)."
# Contents:  GIFMachine.docs GIFMachine.h colourlist.c doimage.c
#   extensions.c giftosham.c lmkfile main.c rgbdiff.c startup.a
#   stripborder.c warncli.c writeiff.c xcomp.c
# Wrapped by tadguy@abcfd20 on Mon Sep  3 18:37:04 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'GIFMachine.docs' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'GIFMachine.docs'\"
else
echo shar: Extracting \"'GIFMachine.docs'\" \(6277 characters\)
sed "s/^X//" >'GIFMachine.docs' <<'END_OF_FILE'
X
X                                GIFMachine
X
X                 Copyright 1990 by Christopher A. Wichura
X                           (caw@miroc.chi.il.us)
X
X
XLegal mumbo jumbo:
X
XGIFMachine is not in the public domain.  All source files, along with the
Xresulting executable, are copyright by C. Wichura.  You may not sell
XGIFMachine.  The only allowed charge that may be placed on GIFMachine is
Xfor media and/or mailing costs.
X
XGIFMachine may be freely redistributed via BBSs, InterNet/Usenet, and disk
Xlibraries such as Fred Fish's, as long as the archive is not modified.
XDisk magazines and services that charge for file transfers may not
Xdistribute GIFMachine.
X
XIn using GIFMachine, you accept the responsibility for any damage or loss of
Xproductivity/money that may occur through or during its use.  C. Wichura is
Xnot and can not be held accountable.
X
X                            What is GIFMachine?
X                            ~~~~~~~~~~~~~~~~~~~
XGIFMachine is a program that converts pictures stored in the CompuServe GIF
X(Graphics Interchange Format) format into IFF SHAM format.  There are very
Xfew programs that do this, and most have many problems (not that GIFMachine
Xdoesn't either -- see below).
X
XFor a long time, I used a program called ShamSharp to convert GIFs to IFF
Xformat.  ShamSharp was the only thing I would even consider using (execpt
Xfor ASDG's The Art Department, a very fine commercial product!).  However,
Xthere were a number of things about it that irked me.
X
X   1)  If a picture had >16 colours and a width >320, ShamSharp would
X       __ALWAYS__ halve the width of the image.  Not only that, but it
X       did so by simply skipping every other pixel of the original GIF.
X       This resulted in a tremendous loss in resolution.
X       
X       I, myself, would rather have the entire picture converted and be
X       able to use my favorite viewer (Mostra, by S. Vigna) to scroll
X       around the image.  Thus, by default, GIFMachine will not halve
X       the picture's width.  There is a command line switch to make it
X       do so, however, in which case it actually thinks about it a bit
X       rather than just dropping the odd pixels.
X
X   2)  If an image had more than 400 lines in it, ShamSharp would
X       GURU the system if the SHAM mode flag was used.  GIFMachine handles
X       large pictures well (that was one of the primary concerns I had
X       while writing it) and has been tested with images as large as
X       1152x890!
X
X   3)  ShamSharp would write bad IFF files for me on a regular basis.  I
X       suspect this is because of some subtle bug in the cmpByteRun1
X       compression routine ShamSharp uses.  Anyway, GIFMachine has yet to
X       write a bad IFF on me.  (Cross Fingers, Cross Fingers :-)
X
XGIFMachine also offers the user the ability to automatically remove a
Xborder area in a picture.  (I just hate it when you have an image floating
Xin the middle of the screen with inches of nothing around it.)
X
XYou can also use full ARP wildcards and multiple file specs, much as with
Xthe ARP C:MOVE command.  This eases conversion of a large number of images.
X
X                          Drawbacks of GIFMachine
X                          ~~~~~~~~~~~~~~~~~~~~~~~
XIf you are looking for speed, go someplace else.  GIFMachine was written
Xwith the idea of getting the best possible image from a GIF file, not as
Xsomething to view GIFs in a quick and dirty manner.  Usually what I do is
Xuse something like HAMGIF to see if the GIF is actually worth the effort
Xand then convert a series of GIFs in one shot by specifying multiple
Xfilepspecs.  On a stock 500, the average picture takes around 25 minutes to
Xconvert (half that if the image is interlaced, which is often the case when
Xthe width is halved).
X
XGIFMachine knows how to write only one thing: SHAMs.  If a picture only
Xuses <= 16 colours, SHAM is not needed.  It would be much faster to write a
Xnormal IFF and skip the SHAM conversion calculations.  In such a case, it
Xwould be better to go back and use something like ShamSharp.
X
XThe only viewer I know of that properly handles SHAMs with >400 lines is
XMostra.  SuperSham 3.2 (?) will display the image, but does not allow
Xscrolling around.  The latest version of Christian Weber's ShowIFF
X(included in the v18.? distribution of his iff.library) will also display
XSHAMs and let one scroll around.  However, he does not rebuild the copper
Xlist during vertical scrolling and thus the image turns to muck if one
Xscrolls down.
X
X                             Using GIFMachine
X                             ~~~~~~~~~~~~~~~~
XGIFMachine requires that you have the arp.library, version 39 or greater,
Xin your LIBS: directory.  It also requires a fair amount of RAM (though it
Xdoes not have to be CHIP RAM or contiguous).  The 1152x890 image required
X1.9 megs of memory to convert.
X
XGIFMachine uses the arp GADS() argument parser.  Thus, one can always enter
X`GIFMachine ?' on the command line for help.  GIFMachine can not be run
Xfrom the WorkBench.
X
XGIFMachine accepts the following arguments:
X
X<filespec1> ... <filespecN> [TO <directory or filespec>] [ALL]
X                            [NOBORDER <line thresh>] [XCOMP]
X
XEach filespec may contain any valid ARP wildcards (really regular
Xexpressions).
X
XThe TO option allows one to specify where to put the IFFs.  If not given,
Xthey will be placed in the current directory.  It is generally advised that
XTO point at a directory.  However, if you are converting only a single GIF
Xfile then there is not reason one can not specify a full filespec.
X
XThe ALL option will cause GIFMachine to recursively descend into any
Xdirectories while matching filespecs.
X
XThe NOBORDER option instructs GIFMachine to remove the border area from an
Ximage.  It takes, as its <line thresh> parameter, an integer between 0 and
X100 that indicates what percentage of a line can differ from the border
Xcolour and still have the line removed.
X
XThe final option, XCOMP, tells GIFMachine to halve the width of images with
Xa width >320.
X
XNote that if GIFMachine determines that the image can be written interlaced
X(depends on aspect ratios) then it will work on two lines at a time instead
Xof one.  This is because the SHAM format only changes the base colours
Xevery other line when displaying interlaced images.
X
X-=> CAW
END_OF_FILE
if test 6277 -ne `wc -c <'GIFMachine.docs'`; then
    echo shar: \"'GIFMachine.docs'\" unpacked with wrong size!
fi
# end of 'GIFMachine.docs'
fi
if test -f 'GIFMachine.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'GIFMachine.h'\"
else
echo shar: Extracting \"'GIFMachine.h'\" \(2628 characters\)
sed "s/^X//" >'GIFMachine.h' <<'END_OF_FILE'
X/* Copyright 1990 by Christopher A. Wichura.
X   See file GIFMachine.doc for full description of rights.
X*/
X
X#include <exec/types.h>
X#define DO_ARP_COPIES
X#include <libraries/ArpBase.h>
X#include <proto/exec.h>
X#include <string.h>
X
X/* reference ArpBase so that the #pragma's won't choke */
Xextern struct ArpBase *ArpBase;
X
X/* some structures to make parsing the gif files a bit easier */
Xstruct GIFdescriptor {
X	UWORD gd_Width;
X	UWORD gd_Height;
X	UBYTE gd_ColInfo;
X	UBYTE gd_BackGround;
X	UBYTE gd_Reserved;
X};
X
Xstruct ImageDesc {
X	UWORD id_Left;
X	UWORD id_Top;
X	UWORD id_Width;
X	UWORD id_Height;
X	UBYTE id_Info;
X};
X
X#define GIF_IMAGE      0x2C
X#define GIF_EXTENSION  0x21
X#define GIF_TERMINATOR 0x3B
X
X/* this magic cookie defines the maximum size of the master colour list */
X#define MAXCOLOURS 4096
X
X/* convert a GIF colour intensity into an Amiga intensity */
X#define CVRTGIF(a) buf[a] >> 4
X
X/* these next macros are used to get the r, g, and b values of a given
X   index */
X#define GetRed(a)	(UBYTE)(MasterColourTable[a] >> 8)
X#define GetGreen(a)	(UBYTE)((MasterColourTable[a] >> 4) & 0xF)
X#define GetBlue(a)	(UBYTE)(MasterColourTable[a] & 0xF)
X
X/* determine if pic is too wide to be entirely on a HAM screen */
X#define ISTOOBIG (gdesc.gd_Width > 320)
X
X/* whenever we want to abort we will return this as our error code */
X#define ABORTEXITVAL 1
X
X/* function prototypes we use */
Xextern int __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg);
Xextern void	XCEXIT(int);
Xextern void	WarnMustUseCLI(void);
Xextern void	DoPattern(char *);
Xextern void	Convert(char *);
Xextern BOOL	IsDir(char *);
Xextern void	FlipWord(UWORD *);
Xextern BOOL	DoImage(BPTR);
Xextern BOOL	DoExtension(BPTR);
Xextern UWORD	AddColour(UBYTE *);
Xextern BOOL	WriteIFF(char *);
Xextern void	PutValue(UWORD, UWORD, UWORD);
Xextern UWORD	GetValue(UWORD, UWORD);
Xextern int	ReadCode(BPTR);
Xextern void	AddPixel(UBYTE);
Xextern void	StripBorder(void);
Xextern BOOL	BorderCheck(UWORD, UWORD);
Xextern void	DoXComp(void);
Xextern void	GIFtoSHAM(void);
Xextern void	GetPalette(ULONG, ULONG);
Xextern void	InitDiff(void);
Xextern ULONG	RGBdiff(UBYTE, UBYTE, UBYTE, UBYTE, UBYTE, UBYTE);
Xextern void	OutDump(int);
Xextern void	OutRun(int, int);
Xextern BOOL	PutLong(ULONG);
Xextern BOOL	PutWord(UWORD);
Xextern BOOL	PutChar(UBYTE);
X
X/* modules that want to use the Get/PutValue macros should include this
X   next macro to externally reference the picture storage array */
X#define EXTERNBITPLANE extern UWORD **BitPlane
X
X/* these two macros get and store values in the picture plane */
X#define GetValue(a, b)    BitPlane[b][a]
X#define PutValue(a, b, c) BitPlane[b][a] = c
END_OF_FILE
if test 2628 -ne `wc -c <'GIFMachine.h'`; then
    echo shar: \"'GIFMachine.h'\" unpacked with wrong size!
fi
# end of 'GIFMachine.h'
fi
if test -f 'colourlist.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'colourlist.c'\"
else
echo shar: Extracting \"'colourlist.c'\" \(788 characters\)
sed "s/^X//" >'colourlist.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
XUWORD TotalColours;
XUWORD MasterColourTable[MAXCOLOURS];
X
XUWORD AddColour(UBYTE *buf)
X{
X	register UWORD colour;
X	register UWORD index;
X
X	colour = (UWORD)(CVRTGIF(0) << 8 | CVRTGIF(1) << 4 | CVRTGIF(2));
X
X	for (index = 0; index < TotalColours; index++) {
X		if (colour == MasterColourTable[index])
X			return index;
X	}
X
X	/* note that we don't check to see if the list is full.  this is
X	   because we can't possibly have more than max colours because
X	   16 * 16 * 16 is MAXCOLOURS and thus we will match somewhere in
X	   the table when it is full.  Not to hot of en explanation, eh? */
X
X	MasterColourTable[TotalColours] = colour;
X	return TotalColours++;	
X}
END_OF_FILE
if test 788 -ne `wc -c <'colourlist.c'`; then
    echo shar: \"'colourlist.c'\" unpacked with wrong size!
fi
# end of 'colourlist.c'
fi
if test -f 'doimage.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'doimage.c'\"
else
echo shar: Extracting \"'doimage.c'\" \(5222 characters\)
sed "s/^X//" >'doimage.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
Xextern struct GIFdescriptor gdesc;
XEXTERNBITPLANE;
X
Xstatic struct ImageDesc idesc;
Xextern UWORD GlobalColourTable[256];
Xstatic UWORD LocalColourTable[256];
Xextern ULONG ImageNumber;
X
Xextern char *AbortMsg;
X
Xstatic UWORD Xpos, Ypos;
Xstatic BOOL interleave;
X
Xstatic UBYTE LeaveStep[5]  = {1, 8, 8, 4, 2};
Xstatic UBYTE LeaveFirst[5] = {0, 0, 4, 2, 1};
X
X/* some variables used by the decompressor */
Xstatic int ReadError;
Xstatic UBYTE CodeSize;
Xstatic int EOFCode;
Xstatic UBYTE ReadMask;
Xstatic int CompDataPointer;
Xstatic int CompDataCount;
Xstatic UBYTE CompData[256];
X
X/* tables used by the decompressor */
Xstatic UWORD Prefix[4096];
Xstatic UBYTE Suffix[4096];
Xstatic UBYTE OutCode[1025];
X
XBOOL DoImage(BPTR fh)
X{
X	UBYTE buf[3];
X	register int index;
X	register int colours;
X
X	Printf("...Image #%ld encountered.\n", ImageNumber++);
X
X	if (Read(fh, (char *)&idesc, 9) != 9) {
X		Puts("......Error reading image descriptor.");
X		return TRUE;
X	}
X
X	FlipWord(&idesc.id_Left);
X	FlipWord(&idesc.id_Top);
X	FlipWord(&idesc.id_Width);
X	FlipWord(&idesc.id_Height);
X
X	interleave = idesc.id_Info & 1L << 6;
X	if (interleave)
X		interleave = 1;
X
X	Printf("......Xpos from %ld to %ld, Ypos from %ld to %ld, %sinterlaced.\n",
X		idesc.id_Left, idesc.id_Left + idesc.id_Width - 1,
X		idesc.id_Top, idesc.id_Top + idesc.id_Height - 1,
X		interleave ? "" : "not ");
X
X	if (idesc.id_Info & 1L << 7) {
X		colours = 1L << ((idesc.id_Info & 7) + 1);
X		Printf("......Local colour map contains %ld entries.\n", colours);
X
X		for (index = 0; index < colours; index++) {
X			if (Read(fh, buf, 3) != 3) {
X				Printf("......Error reading local colour #%ld.\n",
X					index);
X				return TRUE;
X			}
X
X			LocalColourTable[index] = AddColour(buf);
X		}
X	} else {
X		colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
X		CopyMem((char *)GlobalColourTable, (char *)LocalColourTable,
X			sizeof(LocalColourTable));
X	}
X
X	Xpos = Ypos = 0;
X
X	/* now we are ready to read the image in so do it! */
X
X	{
X		int Code, MaxCode, ClearCode, CurCode,
X		    OldCode, InCode, FreeCode;
X		int OutCount;
X		int FirstFree;
X		UBYTE InitCodeSize, FinChar, BitMask;
X
X		Printf("......Decompressing line number %5ld", Ypos);
X
X		/* get the codesize and do general setup for decompression */
X		if (Read(fh, buf, 1) != 1) {
X			Puts("\n......I/O Error during decompression.");
X			return TRUE;
X		}
X
X		CodeSize = buf[0];
X		ClearCode = 1L << CodeSize;
X		EOFCode = ClearCode + 1;
X		FreeCode = FirstFree = ClearCode + 2;
X
X		CodeSize++;	/* per GIF spec */
X		InitCodeSize = CodeSize;
X		MaxCode = 1L << CodeSize;
X		ReadError = ReadMask = OutCount = 0;
X		CompDataPointer = CompDataCount = 0;
X
X		BitMask = colours - 1;
X
X		Code = ReadCode(fh);
X		while (Code != EOFCode) {
X			if (ReadError)
X				return TRUE;
X
X			if (CheckAbort(NULL)) {
X				Printf("\n%s\n", AbortMsg);
X				XCEXIT(ABORTEXITVAL);
X			}
X
X			if (Code == ClearCode) {
X				CodeSize = InitCodeSize;
X				MaxCode = 1L << CodeSize;
X				FreeCode = FirstFree;
X				FinChar = CurCode = OldCode = Code = ReadCode(fh);
X				AddPixel(FinChar);
X			} else {
X				CurCode = InCode = Code;
X
X				if (CurCode >= FreeCode) {
X					CurCode = OldCode;
X					OutCode[OutCount++] = FinChar;
X				}
X
X				while (CurCode > BitMask) {
X					if (OutCount > 1024) {
X						Puts("\n......Corrupt GIF file (OutCount)");
X						return TRUE;
X					}
X
X					OutCode[OutCount++] = Suffix[CurCode];
X					CurCode = Prefix[CurCode];
X				}
X
X				FinChar = CurCode;
X				AddPixel(FinChar);
X
X				for (index = OutCount - 1; index >= 0; index--)
X					AddPixel(OutCode[index]);
X				OutCount = 0;
X
X				Prefix[FreeCode] = OldCode;
X				Suffix[FreeCode] = FinChar;
X				OldCode = InCode;
X
X				if (++FreeCode >= MaxCode) {
X					if (CodeSize < 12) {
X						CodeSize++;
X						MaxCode <<= 1;
X					}
X				}
X			}
X
X			Code = ReadCode(fh);
X		}
X	}
X
X	if (Read(fh, buf, 1) != 1) {
X		return TRUE;
X	}
X
X	/* done decompressing.  Erase decompressing message and exit */
X	Puts("\x9B" "22D\x9BKed.");
X
X	if (buf[0] != 0)
X		Puts("......Warning:  Unaligned packet.");
X
X	return FALSE;
X}
X
Xstatic UBYTE ByteBuf;
X
Xint ReadCode(BPTR fh)
X{
X	register int temp;
X	register int DstMasked;
X	register int DstMask;
X	UBYTE buf[1];
X
X	temp = 0;
X	DstMasked = 1L << CodeSize;
X	for (DstMask = 1; DstMask != DstMasked; DstMask <<= 1) {
X		if (!ReadMask) {
X			if (CompDataPointer == CompDataCount) {
X				if (Read(fh, (char *)buf, 1) != 1) {
X					Puts("\n......I/O Error during decompression.");
X					ReadError = 1;
X					return EOFCode;
X				}
X
X				if (Read(fh, (char *)CompData, buf[0]) != buf[0]) {
X					Puts("\n......I/O Error during decompression.");
X					ReadError = 1;
X					return EOFCode;
X				}
X
X				CompDataCount = buf[0];
X				CompDataPointer = 0;
X			}
X
X			ReadMask = 1;
X			ByteBuf = CompData[CompDataPointer++];
X		}
X
X		if (ByteBuf & ReadMask)
X			temp |= DstMask;
X
X		ReadMask <<= 1;
X	}
X
X	return temp;
X}
X
Xvoid AddPixel(UBYTE index)
X{
X	PutValue((UWORD)(Xpos + idesc.id_Left), (UWORD)(Ypos + idesc.id_Top),
X		LocalColourTable[index]);
X
X	if (++Xpos == idesc.id_Width) {
X		Xpos = 0;
X		Ypos += LeaveStep[interleave];
X		if (Ypos >= idesc.id_Height)
X			Ypos = LeaveFirst[++interleave];
X
X		Printf("\x9B" "5D%5ld", Ypos + idesc.id_Top);
X	}
X}
END_OF_FILE
if test 5222 -ne `wc -c <'doimage.c'`; then
    echo shar: \"'doimage.c'\" unpacked with wrong size!
fi
# end of 'doimage.c'
fi
if test -f 'extensions.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'extensions.c'\"
else
echo shar: Extracting \"'extensions.c'\" \(755 characters\)
sed "s/^X//" >'extensions.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
Xstatic UBYTE buf[256];
X
XBOOL DoExtension(BPTR fh)
X{
X	register int size;
X
X	if (Read(fh, buf, 1) != 1) {
X		Puts("...Error reading extension block function code.");
X		return TRUE;
X	}
X
X	Printf("...Extension block function code #%ld not know, skipping.\n",
X		 buf[0]);
X
X	/* we must skip over any data for the extension block */
X	for (;;) {
X		if (Read(fh, buf, 1) != 1) {
X			Puts("...Error reading extension block function code.");
X			return TRUE;
X		}
X
X		size = buf[0];
X
X		if (size == 0)
X			return FALSE;
X
X		if (Read(fh, buf, size) != size) {
X			Puts("...Error reading extension block function code.");
X			return TRUE;
X		}
X	}
X}
END_OF_FILE
if test 755 -ne `wc -c <'extensions.c'`; then
    echo shar: \"'extensions.c'\" unpacked with wrong size!
fi
# end of 'extensions.c'
fi
if test -f 'giftosham.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'giftosham.c'\"
else
echo shar: Extracting \"'giftosham.c'\" \(5232 characters\)
sed "s/^X//" >'giftosham.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
Xextern struct GIFdescriptor gdesc;
XEXTERNBITPLANE;
X
Xextern UWORD MasterColourTable[MAXCOLOURS];
X
Xextern char *AbortMsg;
X
Xextern BOOL Laced;
X
XUWORD *SHAMmem;
X
Xstruct rgb {
X	UBYTE rgb_Red;
X	UBYTE rgb_Green;
X	UBYTE rgb_Blue;
X} Palette[16];
X
Xstatic UWORD ColourBuf[MAXCOLOURS];
Xstatic UBYTE PaletteBuf[MAXCOLOURS];
Xstatic ULONG ErrBuf[MAXCOLOURS];
X
X#define ISLACED (Laced && (y != gdesc.gd_Height - 1))
X
Xvoid GIFtoSHAM(void)
X{
X	register UWORD x;
X	register UWORD current;
X	register int index;
X	register int index2;
X	ULONG error;
X	UWORD y;
X	int Pal;
X	int ShamIndex;
X	int colours;
X
X	ULONG TotalErr, LineErr;
X
X	ULONG bestpal;
X	ULONG besterr;
X
X	UBYTE CurrentRed,  CurrentGreen,  CurrentBlue;
X	UBYTE PreviousRed, PreviousGreen, PreviousBlue;
X
X	Printf("...Converting to SHAM format.\n......Line");
X
X	ShamIndex = TotalErr = 0;
X
X	/* palette zero is always the background colour.  regardless of
X	   what the GIF specified for the background, we always use black.
X	   this is a kludge to get around a hardware `feature' that causes
X	   all overscanned screens to have a black background regardless
X	   of what the background was specified to be.
X	*/
X
X	Palette[0].rgb_Red = Palette[0].rgb_Green = Palette[0].rgb_Blue = 0;
X
X	for (y = 0; y < gdesc.gd_Height; y += (ISLACED ? 2 : 1)) {
X		if (ISLACED)
X			Printf("s %5ld-%5ld", y, y + 1);
X		else
X			Printf(" %5ld", y);
X
X		if (CheckAbort(NULL)) {
X			Printf("\n%s\n", AbortMsg);
X			XCEXIT(ABORTEXITVAL);
X		}
X
X		memset((char *)ColourBuf, 0, sizeof(ColourBuf));
X
X		for (colours = index2 = 0; index2 < (ISLACED ? 2 : 1); index2++)
X			for (x = 0; x < gdesc.gd_Width; x++) {
X				current = GetValue(x, y + index2);
X
X				if (ColourBuf[current]++ == 0)
X					colours++;
X			}
X
X		Printf(", %4ld unique colours", colours);
X
X		memset((char *)PaletteBuf, 0, sizeof(PaletteBuf));
X
X		for (index = 0; index < MAXCOLOURS; index++) {
X			if (ColourBuf[index] == 0)
X				continue;
X
X			ErrBuf[index] = RGBdiff(GetRed(index),
X						GetGreen(index),
X						GetBlue(index),
X						Palette[0].rgb_Red,
X						Palette[0].rgb_Green,
X						Palette[0].rgb_Blue);
X		}
X
X		for (Pal = 1; Pal < 16; Pal++) {
X			for (besterr = index = 0; index < MAXCOLOURS; index++) {
X				if (ColourBuf[index] == 0)
X					continue;
X
X				if (ErrBuf[index] * ColourBuf[index] >= besterr) {
X					bestpal = index;
X					besterr = ErrBuf[index] * ColourBuf[index];
X				}
X			}
X
X			Palette[Pal].rgb_Red   = GetRed(bestpal);
X			Palette[Pal].rgb_Green = GetGreen(bestpal);
X			Palette[Pal].rgb_Blue  = GetBlue(bestpal);
X
X			for (index = 0; index < MAXCOLOURS; index++) {
X				if (ColourBuf[index] == 0)
X					continue;
X
X				error = RGBdiff(GetRed(index),
X						GetGreen(index),
X						GetBlue(index),
X						Palette[Pal].rgb_Red,
X						Palette[Pal].rgb_Green,
X						Palette[Pal].rgb_Blue);
X
X				if (error < ErrBuf[index]) {
X					ErrBuf[index] = error;
X					PaletteBuf[index] = Pal;
X				}
X			}
X		}
X
X		for (index = 0; index < 16; index++)
X			SHAMmem[ShamIndex++] = (UWORD)(
X				Palette[index].rgb_Red   << 8 |
X				Palette[index].rgb_Green << 4 |
X				Palette[index].rgb_Blue);
X
X		for (index2 = 0; index2 < (ISLACED ? 2 : 1); index2++) {
X			PreviousRed   = Palette[0].rgb_Red;
X			PreviousGreen = Palette[0].rgb_Green;
X			PreviousBlue  = Palette[0].rgb_Blue;
X
X			for (LineErr = x = 0; x < gdesc.gd_Width; x++) {
X				current = GetValue(x, y + index2);
X
X				CurrentRed   = GetRed(current);
X				CurrentGreen = GetGreen(current);
X				CurrentBlue  = GetBlue(current);
X
X				besterr = ErrBuf[current];
X				bestpal = PaletteBuf[current];
X
X				error = RGBdiff(
X					CurrentRed,
X					CurrentGreen,
X					CurrentBlue,
X					CurrentRed,
X					PreviousGreen,
X					PreviousBlue);
X
X				if (error < besterr) {
X					besterr = error;
X					bestpal = 16;
X				}
X
X				error = RGBdiff(
X					CurrentRed,
X					CurrentGreen,
X					CurrentBlue,
X					PreviousRed,
X					CurrentGreen,
X					PreviousBlue);
X
X				if (error < besterr) {
X					besterr = error;
X					bestpal = 17;
X				}
X
X				error = RGBdiff(
X					CurrentRed,
X					CurrentGreen,
X					CurrentBlue,
X					PreviousRed,
X					PreviousGreen,
X					CurrentBlue);
X
X				if (error < besterr) {
X					besterr = error;
X					bestpal = 18;
X				}
X
X				if (bestpal < 16) {
X					PutValue(x, y + index2, bestpal);
X
X					PreviousRed   = Palette[bestpal].rgb_Red;
X					PreviousGreen = Palette[bestpal].rgb_Green;
X					PreviousBlue  = Palette[bestpal].rgb_Blue;
X				} else if (bestpal == 16) {
X					PutValue(x, y + index2, CurrentRed | 0x20);
X
X					PreviousRed = CurrentRed;
X				} else if (bestpal == 17) {
X					PutValue(x, y + index2, CurrentGreen | 0x30);
X
X					PreviousGreen = CurrentGreen;
X				} else {
X					PutValue(x, y + index2, CurrentBlue | 0x10);
X
X					PreviousBlue = CurrentBlue;
X				}
X
X				LineErr += besterr;
X			}
X
X			TotalErr += LineErr;
X		}
X
X		Printf("\x9B" "%sD\x9BK", (ISLACED ? "34" : "27"));
X	}
X
X	{
X		ULONG	ErrPerPixel;
X		char	TextBuf[10];
X
X		ErrPerPixel = ((TotalErr / gdesc.gd_Height) * 1000) / gdesc.gd_Width;
X		SPrintf(TextBuf, "%ld.%03ld", ErrPerPixel / 1000, ErrPerPixel % 1000);
X
X		Printf("\x9B" "5DTotal colour error = %ld, Mean per line = %ld, Per pixel = %s.\n",
X			TotalErr, TotalErr / gdesc.gd_Height, TextBuf);
X	}
X}
END_OF_FILE
if test 5232 -ne `wc -c <'giftosham.c'`; then
    echo shar: \"'giftosham.c'\" unpacked with wrong size!
fi
# end of 'giftosham.c'
fi
if test -f 'lmkfile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'lmkfile'\"
else
echo shar: Extracting \"'lmkfile'\" \(1035 characters\)
sed "s/^X//" >'lmkfile' <<'END_OF_FILE'
X# lmkfile for GIFMachine
X# (c) 1990 by Christopher A. Wichura (caw@miroc.chi.il.us)
X
XCPU = -m0
XDEBUG = -d2
XCFLAGS = $(DEBUG) $(CPU) -v -cs -rr -fid -O
X
XND = NODEBUG
XLFLAGS = $(ND) SMALLCODE SMALLDATA
X
XHDR = GIFMachine.h
X
XOBJS = startup.o main.o warncli.o doimage.o extensions.o writeiff.o colourlist.o stripborder.o xcomp.o rgbdiff.o giftosham.o
XLIBS = LIB:ARP.lib LIB:LCR.lib LIB:amiga.lib
X
X.c.o:
X	LC $(CFLAGS) $*
X
X.a.o:
X	ASM -iINCLUDE: $*
X
XGIFMachine: $(OBJS)
X	BLink <WITH < (GIFMachine.lnk)
XFROM $(OBJS)
XTO GIFMachine
XLIB $(LIBS)
X$(LFLAGS)
X<
X
Xmain.o: main.c $(HDR)
X	LC $(CFLAGS) main
X
Xdoimage.o: doimage.c $(HDR)
X	LC $(CFLAGS) doimage
X
Xextensions.o: extensions.c $(HDR)
X	LC $(CFLAGS) extensions
X
Xwriteiff.o: writeiff.c $(HDR)
X	LC $(CFLAGS) writeiff
X
Xcolourlist.o: colourlist.c $(HDR)
X	LC $(CFLAGS) colourlist
X
Xstripborder.o: stripborder.c $(HDR)
X	LC $(CFLAGS) stripborder
X
Xxcomp.o: xcomp.c $(HDR)
X        LC $(CFLAGS) xcomp
X
Xgiftosham.o: giftosham.c $(HDR)
X	LC $(CFLAGS) giftosham
X
Xrgbdiff.o: rgbdiff.c $(HDR)
X	LC $(CFLAGS) rgbdiff
END_OF_FILE
if test 1035 -ne `wc -c <'lmkfile'`; then
    echo shar: \"'lmkfile'\" unpacked with wrong size!
fi
# end of 'lmkfile'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(9441 characters\)
sed "s/^X//" >'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 <workbench/startup.h>
X
Xstruct GIFdescriptor gdesc;
X
XUWORD **BitPlane;
XUWORD GlobalColourTable[256];
X
Xextern UWORD *SHAMmem;
X
Xextern BYTE *PlaneBuf;
X
Xextern BOOL Laced;
X
Xextern UBYTE *Planes[6];
X
XULONG ImageNumber;
Xextern UWORD TotalColours;
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 ARP_HELP	GIFMACH " v1.0 \xA9 1990 by " \
X			ESC "4;33;42mChristopher A. Wichura" \
X			ESC "0;33;40m (" ESC "32mcaw" ESC "33m@" \
X			ESC "32mmiroc.chi.il.us" ESC "33m)\n" \
X			ESC "31mUsage:     " GIFMACH " <" ESC \
X			"31mGIFfile(s)" ESC "32m> [" ESC "33mTO " \
X			ESC "31mDirectory | File" ESC "32m] [" \
X			ESC "33mALL" ESC "32m]\n                      [" \
X			ESC "33mNOBORDER " ESC "32m<" ESC "31mLine " \
X			"Thresh" ESC "32m>] [" ESC "33mXCOMP" \
X			ESC "32m]\n" ESC "31m"
X
X#define ARP_TEMPLATE "GIFfiles/...,TO/k,ALL/s,NOBORDER/k,XCOMP/s"
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_sizeof 5
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 */
Xchar *ArgArray[ARG_sizeof];
XBOOL ArgToIsDir;
X
Xint NoBorderLineThresh = 0;
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!";
X
X/* storage for the math library base */
Xstruct Library *MathIeeeDoubBasBase;
X
X/* here we have our main routine */
Xint __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg)
X{
X	register char **FilesPtr;
X
X	if (WBMsg) {
X		WarnMustUseCLI();
X		XCEXIT(5);
X	}
X
X	if (!(MathIeeeDoubBasBase = ArpOpenLibrary("mathieeedoubbas.library", 0))) {
X		Puts("Unable to access mathieeedoubbas.library!");
X		XCEXIT(5);
X	}
X
X	memset((char *)ArgArray, 0, sizeof(ArgArray));
X
X	if (GADS(cmdptr, cmdlen, ARP_HELP, ArgArray, ARP_TEMPLATE) < 0) {
X		Puts(ArgArray[0]);
X		XCEXIT(5);
X	}
X
X	if (ArgArray[ARG_TO])
X		ArgToIsDir = IsDir(ArgArray[ARG_TO]);
X
X	if (ArgArray[ARG_NOBORD]) {
X		NoBorderLineThresh = Atol(ArgArray[ARG_NOBORD]);
X		if (NoBorderLineThresh < 0 || NoBorderLineThresh > 100) {
X			Puts("Invalid NOBORDER line threshhold specified.");
X			XCEXIT(3);
X		}
X	}
X
X	if (!(FilesPtr = (char **)ArgArray[ARG_FILES])) {
X		Puts("No GIF files selected.");
X		XCEXIT(3);
X	}
X
X	InitDiff();	/* one time init for the RGBdiff function */
X
X	while (*FilesPtr)
X		DoPattern(*FilesPtr++);	
X}
X
X/* this will walk through a pattern doing conversions */
Xvoid DoPattern(char *pat)
X{
X	register struct Anchor {
X		struct AnchorPath APath;
X		char              Path[256];
X	} *anchor;
X	register int error;
X
X	if (!(anchor = (struct Anchor *)ArpAlloc(sizeof(struct Anchor)))) {
X		Puts("Out of memory!");
X		XCEXIT(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 = FindFirst(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 = FindNext(&anchor->APath);
X	}
X
X	FreeAnchorChain(&anchor->APath);
X
X	switch(error) {
X		case ERROR_BREAK:
X			Puts(AbortMsg);
X			XCEXIT(ABORTEXITVAL);
X			break;
X
X		case ERROR_OBJECT_NOT_FOUND:
X			Puts("File not found.");
X			break;
X
X		case ERROR_BUFFER_OVERFLOW:
X			Puts("Path too long!");
X			break;
X
X		case ERROR_NO_MORE_ENTRIES:	/* normal termination */
X			break;
X
X		default:
X			Printf("I/O Error #%ld!\n", error);
X			break;
X	}
X
X	FreeTrackedItem((struct DefaultTracker *)anchor);
X}
X
X/* here we have the routine that gets ready to do the conversion */
Xvoid Convert(char *name)
X{
X	register BPTR fh;
X	register int index;
X	char *basename;
X	char *ptr;
X	char sig[7];
X	UBYTE buf[3];
X	int size;
X	int error;
X	int colours;
X	UWORD NewBackground;
X
X	struct DateStamp StartTime, EndTime;
X
X	if (!CreateTaskResList()) {
X		Puts("Fatal tracker error!");
X		XCEXIT(10);
X	}
X
X	if (!(fh = ArpOpen(name, MODE_OLDFILE))) {
X		Printf("Error #%ld trying to open %s...\n", IoErr(), name);
X		goto LeaveConvert;
X	}
X
X	sig[6] = NULL;
X
X	if (Read(fh, sig, 6) != 6 || strncmp("GIF", sig, 3)) {
X		Printf("%s is not a GIF file...\n", name);
X		goto LeaveConvert;
X	}
X
X	Printf("Converting %s ", name);
X
X	basename = BaseName(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 = ArpAlloc(size))) {
X		Puts("... Out of memory!");
X		goto LeaveConvert;
X	}
X
X	if (ArgArray[ARG_TO]) {
X		strcpy(ptr, ArgArray[ARG_TO]);
X
X		if (ArgToIsDir) {
X			TackOn(ptr, basename);
X			strcat(ptr, ".sham");
X		}
X	} else {
X		strcpy(ptr, basename);
X		strcat(ptr, ".sham");
X	}
X
X	Printf("to %s...\n", ptr);
X
X	DateStamp((LONG *)&StartTime);
X
X	if (Read(fh, (char *)&gdesc, 7) != 7) {
X		Puts("Error reading screen descriptor.");
X		goto LeaveConvert;
X	}
X
X	FlipWord(&gdesc.gd_Width);
X	FlipWord(&gdesc.gd_Height);
X
X	Printf("Signature = \"%s\", Width = %ld, Height = %ld\n",
X		sig, gdesc.gd_Width, gdesc.gd_Height);
X
X	DidXComp = TotalColours = 0;
X	colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
X
X	if (!(gdesc.gd_ColInfo & 1L << 7)) {
X		Puts("No global colour map supplied, using internal.");
X
X		for (index = 0; index < colours; index++) {
X			buf[0] = buf[1] = buf[2] = CVRTGIF(index);
X			GlobalColourTable[index] = AddColour(buf);
X		}
X	} else {
X		Printf("Global colour map contains %ld entries.\n", colours);
X
X		for (index = 0; index < colours; index++) {
X			if (Read(fh, buf, 3) != 3) {
X				Printf("Error reading global colour #%ld.\n",
X					index);
X				goto LeaveConvert;
X			}
X
X			GlobalColourTable[index] = AddColour(buf);
X			if (index == gdesc.gd_BackGround)
X				NewBackground = GlobalColourTable[index];
X		}
X
X		gdesc.gd_BackGround = NewBackground;
X	}
X
X	size = ((gdesc.gd_Width + 7) / 8) + 1;
X	size += (size + 127) >> 7;
X
X	if (!(BitPlane = (UWORD **)ArpAlloc(gdesc.gd_Height * sizeof(UWORD *))) ||
X	    !(SHAMmem  = (UWORD *)ArpAlloc(gdesc.gd_Height * 16 * sizeof(UWORD))) ||
X	    !(PlaneBuf  = (BYTE *)ArpAlloc(size))) {
X		Puts("Out of memory trying to allocate picture.");
X		goto LeaveConvert;
X	}
X
X	size = (gdesc.gd_Width + 1) * sizeof(UWORD);
X
X	for (index = 0; index < gdesc.gd_Height; index++)
X		if (!(BitPlane[index] = (UWORD *)ArpAlloc(size))) {
X			Puts("Out of memory trying to allocate picture.");
X			goto LeaveConvert;
X		}
X
X	size = ((gdesc.gd_Width + 7) / 8) + 1;
X	for (index = 0; index < 6; index++)
X		if (!(Planes[index] = (UBYTE *)ArpAlloc(size))) {
X			Puts("Out of memory trying to allocate picture.");
X			goto LeaveConvert;
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 (Read(fh, buf, 1) != 1) {
X			Puts("...Error reading GIF file.");
X			break;
X		}
X
X		switch(buf[0]) {
X			case GIF_IMAGE:
X				error = DoImage(fh);
X				break;
X
X			case GIF_EXTENSION:
X				error = DoExtension(fh);
X				break;
X
X			case GIF_TERMINATOR:
X				Printf("...%ld unique colours used by GIF file.\n",
X					TotalColours);
X
X				if (ArgArray[ARG_NOBORD])
X					StripBorder();
X
X				if (ArgArray[ARG_XCOMP] && ISTOOBIG) {
X					DoXComp();
X					DidXComp = 1;
X				}
X
X				if (gdesc.gd_Height > 200 && (!ISTOOBIG || DidXComp))
X					Laced = TRUE;
X				else
X					Laced = FALSE;
X
X				GIFtoSHAM();
X				error = WriteIFF(ptr);
X				break;
X
X			default:
X				Printf("...Unknown directive #%ld encountered.\n",
X					buf[0]);
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		Printf("...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	FreeTaskResList();
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	/* kludge to word allign our FileInfoBlock to avoid having to */
X	/* call AllocMem() for it.  Gotten from a UseNet message.     */
X
X	char c_fib[sizeof(struct FileInfoBlock) + 3];
X	struct FileInfoBlock *fib = (struct FileInfoBlock *)
X		((unsigned long)(((unsigned long)c_fib+3)>>2)<<2);
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 9441 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'rgbdiff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rgbdiff.c'\"
else
echo shar: Extracting \"'rgbdiff.c'\" \(876 characters\)
sed "s/^X//" >'rgbdiff.c' <<'END_OF_FILE'
X/* Note:  this colour comparison routine was snitched from HamSharp.
X
X   This has the side effect of allowing one to compare colour errors gotten
X   with GIFMachine to those gotten with (S)HamSharp.
X*/
X
X#include "GIFMachine.h"
X
Xstatic UBYTE Diff[16][16];
Xstatic UBYTE Intensity[16][16][16];
X
Xextern struct Library *MathIeeeDoubBasBase;
X
Xvoid InitDiff(void)
X{
X	register int i;
X	register int j;
X	register int r;
X	register int g;
X	register int b;
X
X	for (i = 0; i < 16; i++)
X		for (j = 0; j < 16; j++)
X			Diff[i][j] = (i - j) * (i - j);
X
X	for (r = 0; r < 16; r++)
X		for (g = 0; g < 16; g++)
X			for (b = 0; b < 16; b++)
X				Intensity[r][g][b] = (int)(.299 * r + .587 * g + .114 * b);
X}
X
XULONG RGBdiff(UBYTE r1, UBYTE g1, UBYTE b1, UBYTE r2, UBYTE g2, UBYTE b2)
X{
X	return (ULONG)(Diff[Intensity[r1][g1][b1]][Intensity[r2][g2][b2]] +
X		Diff[r1][r2] + Diff[g1][g2] + Diff[b1][b2]);
X}
END_OF_FILE
if test 876 -ne `wc -c <'rgbdiff.c'`; then
    echo shar: \"'rgbdiff.c'\" unpacked with wrong size!
fi
# end of 'rgbdiff.c'
fi
if test -f 'startup.a' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'startup.a'\"
else
echo shar: Extracting \"'startup.a'\" \(4258 characters\)
sed "s/^X//" >'startup.a' <<'END_OF_FILE'
X INCLUDE "libraries/ArpBase.i"
X INCLUDE "exec/execbase.i"
X INCLUDE "libraries/dosextens.i"
X
X XREF @main
X
X XREF _LVOOpenLibrary
X XREF _LVOCloseLibrary
X XREF _LVOSetSignal
X XREF _LVOForbid
X XREF _LVOWaitPort
X XREF _LVOGetMsg
X XREF _LVOReplyMsg
X
X XREF _LinkerDB
X XREF __BSSBAS
X XREF __BSSLEN
X XREF _RESLEN
X XREF _RESBASE
X XREF _NEWDATAL
X
X XREF _AbsExecBase
X
XCALL	MACRO
X	jsr _LVO\1(a6)
X	ENDM
X
X  SECTION StartCode,CODE
X
X; arp resident tag goes here
X	RESIDENT 10*1024
X
Xinit:
X	movem.l	d0/a0,-(sp)
X
X; first off we will check for our workbench message, if any.  we will store
X; the pointer to it in d7 temporarily until we actually copy the data
X; segment over.  otherwise we wouldn't be residentiable.
X
X	moveq	#0,d7		; clear out longword
X
X; get address of our task
X	move.l	_AbsExecBase.W,a6
X	move.l	ThisTask(a6),a3
X
X; clear any pending signals
X	moveq	#0,d0
X	move.l	#$00003000,d1
X	CALL	SetSignal
X
X; check for workbench message
X	tst.l	pr_CLI(a3)
X	bne.s	FromCLI
X
X	lea	pr_MsgPort(a3),a0
X	CALL	WaitPort
X	lea	pr_MsgPort(a3),a0
X	CALL	GetMsg
X	move.l	d0,d7
X
XFromCLI:
X	lea	ARPlib(pc),a1
X	moveq	#ArpVersion,d0
X	CALL	OpenLibrary
X	tst.l	d0
X	bne.s	ARPmain
X
X	lea	DOSlib(pc),a1
X	CALL	OpenLibrary
X	tst.l	d0
X	beq.s	bomb
X
X	move.l	d0,a6
X	CALL	Output
X	move.l	d0,d1
X	beq.s	bomb
X
X	lea	Msg1(pc),a0
X	move.l	a0,d2
X	moveq	#Msg1Len,d3
X	CALL	Write
X
X	move.l	a6,a1
X	move.l	_AbsExecBase.W,a6
X	CALL	CloseLibrary
X
Xbomb:	addq.l	#8,sp		; pop d0/a0 off stack
X
X	move.l	d7,d0		; check if we have a workbench startup
X	bsr	ReplyWB		; message and reply it if so
X
X	moveq	#0,d0		; set an exit code
X	rts
X
XARPmain:
X	move.l	d0,a6
X
X	lea	_LinkerDB,a4
X	sub.l	#_RESBASE,a4
X
X; get mem to hold data and bss stuff
X	move.l	#_RESLEN,d0
X	CALL	ArpAlloc
X	tst.l	d0
X	bne.s	gotmem
X
X; no mem available so bomb out
X	move.l	d7,d0		; check for wb startup message and reply
X	bsr	ReplyWB		; it if present
X
X	addq.l	#8,sp		; pop d0/a0 off of stack
X
X	moveq	#20,d0
X	moveq	#ERROR_NO_FREE_STORE,d2
X	CALL	ArpExit
X
X; get ready to copy data over into freshly alloced data area
Xgotmem:	move.l	d0,a0
X	move.l	d0,a2
X
X	move.l	d0,a1
X	move.l	#_NEWDATAL,d0
Xcpy:	move.l	(a4)+,(a0)+
X	subq.l	#1,d0
X	bne.s	cpy
X
X; now do the relocs for resident data
X	move.l	(a4)+,d0
Xreloc:	beq.s	nreloc
X	move.l	a1,a0
X	add.l	(a4)+,a0
X	add.l	(a0),a2
X	move.l	a2,(a0)
X	move.l	a1,a2
X	subq.l	#1,d0
X	bra.s	reloc
X
Xnreloc:	move.l	a1,a4
X	add.l	#_RESBASE,a4
X
X; stash some important junk away
X	move.l	a6,_ArpBase(a4)
X	move.l	GfxBase(a6),_GfxBase(a4)
X	move.l	IntuiBase(a6),_IntuitionBase(a4)
X	move.l	d7,_WBenchMsg(a4)
X
X	move.l	_AbsExecBase.W,a6
X	move.l	a6,_SysBase(a4)
X	movem.l	sp,__StackPtr(a4)
X
X; call our main program.  we call the main routine with the following
X; arguments:
X;
X;   d0 = length of command line
X;   a0 = pointer to command line
X;   a1 = pointer to workbench startup message (or NULL)
X
X	movem.l	(sp)+,d0/a0
X	movea.l	d7,a1
X	jsr	@main
X	moveq	#0,d0
X	bra.s	Exit
X
X XDEF _XCEXIT
X_XCEXIT:
X	move.l	4(sp),d0
X XDEF @XCEXIT
X@XCEXIT:
X
XExit:	move.l	d0,d2			; save return code in safe place
X
X	move.l	_WBenchMsg(a4),d0	; check if we need to reply the
X	bsr	ReplyWB			; workbench startup message
X
X1$	move.l	d2,d0			; restore return code
X
X	move.l	_ArpBase(a4),a6
X	movea.l	__StackPtr(a4),sp
X	moveq	#0,d2
X	CALL	ArpExit
X
X; this subroutine is called when we try to check if we need to reply
X; the workbench message.  This is done because we do this in more than
X; one place.
X
XReplyWB:
X	move.l	d0,d2
X	beq.s	1$
X
X	move.l	_AbsExecBase.W,a6
X	CALL	Forbid
X	movea.l	d2,a1
X	CALL	ReplyMsg
X
X1$	rts
X
X; ---- This is the data we need for the startup module.  we don't put it in
X;      a data segment, though, or it would end up being copied over when we
X;      clone the data hunk and this stuff isn't needed anywhere else...
X
X    IFGE ArpVersion-100
X	 FAIL "You lose: Time to bump version report to 3 digits!"
X    ENDC
X
XDOSlib	dc.b "dos.library",0
X
XTEM	SET ArpVersion/10
XMsg1	dc.b "You need "
XARPlib	ArpName
X	dc.b " V",TEM+'0',(ArpVersion-(TEM*10))+'0','+',10,0
XMsg1Len	EQU *-Msg1
X	ds.w 0
X
X; ---- This is the BBS segment that holds various startup junk for us.
X
X   SECTION __MERGED,BSS
X
X XDEF _ArpBase
X XDEF _GfxBase
X XDEF _SysBase
X XDEF _IntuitionBase
X XDEF _WBenchMsg
X XDEF __StackPtr
X
X_ArpBase	ds.b 4
X_GfxBase	ds.b 4
X_SysBase	ds.b 4
X_IntuitionBase	ds.b 4
X_WBenchMsg	ds.b 4
X__StackPtr	ds.b 4
X
X   END
END_OF_FILE
if test 4258 -ne `wc -c <'startup.a'`; then
    echo shar: \"'startup.a'\" unpacked with wrong size!
fi
# end of 'startup.a'
fi
if test -f 'stripborder.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stripborder.c'\"
else
echo shar: Extracting \"'stripborder.c'\" \(2650 characters\)
sed "s/^X//" >'stripborder.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
Xextern struct GIFdescriptor gdesc;
XEXTERNBITPLANE;
X
Xextern char *AbortMsg;
X
Xextern int NoBorderLineThresh;
X
Xextern UWORD MasterColourTable[MAXCOLOURS];
X
Xstatic UWORD BorderCol;
X
X#define BorderCheck(a, b) (GetValue(a, b) != BorderCol)
X
Xvoid StripBorder(void)
X{
X	register UWORD x;
X	register UWORD y;
X	register int thresh;
X	register BOOL breakout;
X	UWORD LeftEdge, TopEdge;
X	UWORD Width, Height;
X	int WidthThresh, HeightThresh;
X
X	Puts("...Removing border.");
X
X	BorderCol = GetValue(0, 0);
X
X	WidthThresh  = NoBorderLineThresh * gdesc.gd_Width  / 100;
X	HeightThresh = NoBorderLineThresh * gdesc.gd_Height / 100;
X
X	for (breakout = y = 0; (y < gdesc.gd_Height) && !breakout; y++) {
X		for (thresh = x = 0; x < gdesc.gd_Width; x++)
X			if (BorderCheck(x, y))
X				if (++thresh > WidthThresh) {
X					breakout = TRUE;
X					break;
X				}
X
X		if (CheckAbort(NULL)) {
X			Puts(AbortMsg);
X			XCEXIT(ABORTEXITVAL);
X		}
X	}
X
X	TopEdge = y - 1;
X
X	for (breakout = 0, y = gdesc.gd_Height - 1; y >= 0 && !breakout; y--) {
X		for (thresh = x = 0; x < gdesc.gd_Width; x++)
X			if (BorderCheck(x, y))
X				if (++thresh > WidthThresh) {
X					breakout = TRUE;
X					break;
X				}
X
X		if (CheckAbort(NULL)) {
X			Puts(AbortMsg);
X			XCEXIT(ABORTEXITVAL);
X		}
X	}
X
X	Height = y - TopEdge + 2;
X
X	for (breakout = x = 0; (x < gdesc.gd_Width) && !breakout; x++) {
X		for (thresh = y = 0; y < gdesc.gd_Height; y++)
X			if (BorderCheck(x, y))
X				if (++thresh > HeightThresh) {
X					breakout = TRUE;
X					break;
X				}
X
X		if (CheckAbort(NULL)) {
X			Puts(AbortMsg);
X			XCEXIT(ABORTEXITVAL);
X		}
X	}
X
X	LeftEdge = x - 1;
X
X	for (breakout = 0, x = gdesc.gd_Width - 1; x >= 0 && !breakout; x--) {
X		for (thresh = y = 0; y < gdesc.gd_Height; y++)
X			if (BorderCheck(x, y))
X				if (++thresh > HeightThresh) {
X					breakout = TRUE;
X					break;
X				}
X
X		if (CheckAbort(NULL)) {
X			Puts(AbortMsg);
X			XCEXIT(ABORTEXITVAL);
X		}
X	}
X
X	Width = x - LeftEdge + 2;
X
X	if ((Width != gdesc.gd_Width) || (Height != gdesc.gd_Height)) {
X		if (Width < 5 || Height < 5) {
X			Puts("......Too much of picture would be removed.  Not modified.");
X			return;
X		}
X
X		for (y = 0; y < Height; y++) {
X			for (x = 0; x < Width; x++)
X				PutValue(x, y,
X				   GetValue((UWORD)(LeftEdge + x),
X					    (UWORD)(TopEdge + y)));
X
X			PutValue(x, y, gdesc.gd_BackGround);
X
X			if (CheckAbort(NULL)) {
X				Puts(AbortMsg);
X				XCEXIT(ABORTEXITVAL);
X			}
X		}
X
X		if (Width & 1)
X			Width++;
X
X		Printf("......New width = %ld, New height = %ld\n", Width, Height);
X		gdesc.gd_Width = Width;
X		gdesc.gd_Height = Height;
X	}
X}
END_OF_FILE
if test 2650 -ne `wc -c <'stripborder.c'`; then
    echo shar: \"'stripborder.c'\" unpacked with wrong size!
fi
# end of 'stripborder.c'
fi
if test -f 'warncli.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'warncli.c'\"
else
echo shar: Extracting \"'warncli.c'\" \(1457 characters\)
sed "s/^X//" >'warncli.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 <exec/types.h>
X#include <intuition/intuition.h>
X#include <graphics/text.h>
X#include <proto/intuition.h>
X
Xstatic struct TextAttr TOPAZ60 = {"topaz.font", TOPAZ_SIXTY,
X	FS_NORMAL, FPF_ROMFONT};
X
Xstatic struct IntuiText BodyText2 = {-1, -1,    /* pen numbers */
X                             0,             /* draw mode */
X                             9,14,          /* starting offsets */
X                             &TOPAZ60,      /* text attribute pointer */
X                             "for CLI use only!",
X                             NULL };
X
Xstatic struct IntuiText BodyText1 = {-1,-1,      /* pen numbers */
X                             0,             /* draw mode */
X                             29,4,          /* starting offsets */
X                             &TOPAZ60,      /* text attribute pointer */
X                             "GIFMachine is",
X                             &BodyText2 };
X
Xstatic struct IntuiText ContinueText = {-1,-1,  /* pen numbers */
X                             0,             /* draw mode */
X                             4,4,           /* starting offsets */
X                             &TOPAZ60,      /* text attribute pointer */
X                             "CONTINUE",
X                             NULL };
X
Xvoid WarnMustUseCLI(void)
X{
X	AutoRequest(NULL,&BodyText1,NULL,&ContinueText,0,0,220,64);
X}
END_OF_FILE
if test 1457 -ne `wc -c <'warncli.c'`; then
    echo shar: \"'warncli.c'\" unpacked with wrong size!
fi
# end of 'warncli.c'
fi
if test -f 'writeiff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'writeiff.c'\"
else
echo shar: Extracting \"'writeiff.c'\" \(6554 characters\)
sed "s/^X//" >'writeiff.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 <iff/ILBM.h>
X
Xextern struct GIFdescriptor gdesc;
XEXTERNBITPLANE;
X
Xextern char *AbortMsg;
X
Xextern UWORD *SHAMmem;
XBYTE *PlaneBuf;
X
XBOOL Laced;
X
Xstatic BPTR ofh;
X
XUBYTE *Planes[6];
X
Xstatic UBYTE CompBuf[256];
Xstatic ULONG PlanePos;
X
XBOOL WriteIFF(char *tofile)
X{
X	register int index;
X	register ULONG ChunkSize;
X	register UWORD current;
X
X	ColorRegister ColourBuf;
X
X	ULONG FormSize, BodySize, BodySizePos;
X
X	Printf("...Writing IFF file.");
X
X	if (!(ofh = ArpOpen(tofile, MODE_NEWFILE))) {
X		Printf("\n......Error %ld trying to create %s.", IoErr(), tofile);
X		return TRUE;
X	}
X
X	gdesc.gd_Width &= ~1L;	/* make sure width is even */
X
X	if (PutLong(FORM) || PutLong(0L) || PutLong(ID_ILBM))
X		return TRUE;
X
X#define WRITTENBY "Written by GIFMachine on "
X
X	ChunkSize = strlen(WRITTENBY) + LEN_DATSTRING;
X	if (IS_ODD(ChunkSize))
X		ChunkSize++;
X
X	if (PutLong(MakeID('A','N','N','O')) || PutLong(ChunkSize))
X		return TRUE;
X
X	if (Write(ofh, WRITTENBY, strlen(WRITTENBY)) != strlen(WRITTENBY)) {
X		Printf("\n......Error %ld during write.\n", IoErr());
X		return TRUE;
X	}
X
X	{
X		struct DateTime dat;
X		char Date[LEN_DATSTRING];
X
X		DateStamp((LONG *)&dat.dat_Stamp);
X		dat.dat_Format = FORMAT_DOS;
X		dat.dat_Flags = 0;
X		dat.dat_StrDay = NULL;
X		dat.dat_StrDate = Date;
X		dat.dat_StrTime = NULL;
X
X		memset(Date, 0, LEN_DATSTRING);
X		StamptoStr(&dat);
X
X		if (Write(ofh, Date, LEN_DATSTRING) != LEN_DATSTRING) {
X			Printf("\n......Error %ld during write.\n", IoErr());
X			return TRUE;
X		}
X	}
X
X	if (IS_ODD(Seek(ofh, 0, OFFSET_CURRENT)))
X		PutChar(0);
X
X	if (PutLong(ID_BMHD) || PutLong(sizeof(BitMapHeader)))
X		return TRUE;
X
X	if (PutWord(gdesc.gd_Width) || PutWord(gdesc.gd_Height) ||
X	    PutLong(0L) /* x,y pos both zero */ || PutChar(6) ||
X	    PutChar(mskNone) || PutChar(cmpByteRun1) || PutChar(0) ||
X	    PutWord(0) /* background is transparent colour */ ||
X	    PutChar((UBYTE)(Laced ? x320x400Aspect : x320x200Aspect)) ||
X	    PutChar((UBYTE)(Laced ? y320x400Aspect : y320x200Aspect)) ||
X	    PutWord(320) || PutWord((UWORD)(Laced ? 400 : 200)))
X		return TRUE;
X
X	if (PutLong(ID_CAMG) || PutLong(4) ||
X	    PutLong(Laced ? 0x804 : 0x800))
X		return TRUE;
X
X	if (PutLong(ID_CMAP) || PutLong(16 * 3))
X		return TRUE;
X
X	for (index = 0; index < 16; index++) {
X		current = SHAMmem[index];
X
X		ColourBuf.red   = (current >> 4) & 0xF0;
X		ColourBuf.green = current & 0xF0;
X		ColourBuf.blue  = (current & 15) << 4;
X
X		if (Write(ofh, (char *)&ColourBuf, sizeofColorRegister) !=
X			sizeofColorRegister) {
X			Printf("\n......Error %ld during write.\n", IoErr());
X				return TRUE;
X		}
X	}
X
X	ChunkSize = (Laced ? gdesc.gd_Height / 2 : gdesc.gd_Height) * 16 * sizeof(UWORD);
X
X	if (PutLong(MakeID('S','H','A','M')) || PutLong(ChunkSize + 2) || PutWord(0))
X		return TRUE;
X
X	if (Write(ofh, (char *)SHAMmem, ChunkSize) != ChunkSize) {
X		Printf("\n......Error %ld during write.\n", IoErr());
X		return TRUE;
X	}
X
X	if (PutLong(ID_BODY))
X		return TRUE;
X
X	BodySizePos = Seek(ofh, 0, OFFSET_CURRENT);
X	if (PutLong(0L))
X		return TRUE;
X
X	/* now we actually write the body chunk out */
X	{
X		register int plane;
X		register int col;
X		register UWORD x;
X		register UWORD y;
X		UBYTE PlaneMask, ColMask;
X		UWORD Cols;
X
X		Printf("\n......Line ");
X
X		Cols = (gdesc.gd_Width + 7) / 8;
X		if (IS_ODD(Cols))
X			Cols++;
X
X		for (y = 0; y < gdesc.gd_Height; y++) {
X			Printf("%5ld", y);
X
X			if (CheckAbort(NULL)) {
X				Printf("\n%s\n", AbortMsg);
X				XCEXIT(ABORTEXITVAL);
X			}
X
X			col = 0;
X			ColMask = 1L << 7;
X
X			for (x = 0; x < gdesc.gd_Width; x++) {
X				current = GetValue(x, y);
X
X				PlaneMask = 1;
X				for (plane = 0; plane < 6; plane++) {
X					if (current & PlaneMask)
X						Planes[plane][col] |= ColMask;
X
X					PlaneMask <<= 1;
X				}
X
X				if (ColMask == 1) {
X					ColMask = 1L << 7;
X					col++;
X				} else
X					ColMask >>= 1;
X			}
X
X			/* now we need to compress the scan line */
X
X			{
X				register BOOL state;
X				register char c;
X				register char lastc;
X				register UWORD nbuf;
X				register UWORD rstart;
X
X				for (plane = 0; plane < 6; plane++) {
X
X					CompBuf[0] = lastc = c = Planes[plane][0];
X
X					state = FALSE;
X					PlanePos = rstart = 0;
X					nbuf = col = 1;
X
X					while (col < Cols) {
X						CompBuf[nbuf++] = c = Planes[plane][col++];
X
X						switch (state) {
X							case FALSE:
X							if (nbuf > 128) {
X								OutDump(nbuf - 1);
X								CompBuf[0] = c;
X								nbuf = 1;
X								rstart = 0;
X								break;
X							}
X
X							if (c == lastc) {
X								if (nbuf - rstart >= 3) {
X									if (rstart > 0)
X										OutDump(rstart);
X									state = TRUE;
X								} else if (rstart == 0)
X									state = TRUE;
X							} else
X								rstart = nbuf - 1;
X
X							break;
X
X							case TRUE:
X							if ((c != lastc) || (nbuf - rstart > 128)) {
X								OutRun(nbuf - 1 - rstart, lastc);
X								CompBuf[0] = c;
X								nbuf = 1;
X								rstart = 0;
X								state = FALSE;
X							}
X
X							break;
X						}
X
X						lastc = c;
X					}
X
X					switch (state) {
X						case FALSE:
X						OutDump(nbuf);
X						break;
X
X						case TRUE:
X						OutRun(nbuf - rstart, lastc);
X						break;
X					}
X
X					/* now write the compressed plane out */
X					if (Write(ofh, (char *)PlaneBuf, PlanePos) != PlanePos) {
X						Printf("\n......Error %ld during write.\n", IoErr());
X						return TRUE;
X					}
X
X					memset((char *)Planes[plane], 0, Cols);
X				}		
X			}
X
X			Printf("\x9B" "5D");
X		}
X
X	}
X
X	/* finished writing the body so pad it if needed and then fix a
X	   a couple chunk sizes and we are done! */
X
X	if (IS_ODD(Seek(ofh, 0, OFFSET_CURRENT)))
X		if (PutChar(0))
X			return TRUE;
X
X	BodySize = Seek(ofh, 0, OFFSET_CURRENT) - BodySizePos - 4;
X	FormSize = Seek(ofh, 0, OFFSET_CURRENT) - 8;
X
X	Seek(ofh, 4, OFFSET_BEGINNING);
X	if (PutLong(FormSize))
X		return TRUE;
X
X	Seek(ofh, BodySizePos, OFFSET_BEGINNING);
X	PutLong(BodySize);
X
X	Puts("\x9B" "5D\x9BKWritten.");
X
X	return TRUE;
X}
X
Xvoid OutDump(int nn)
X{
X	register int index;
X
X	PlaneBuf[PlanePos++] = nn - 1;
X
X	for (index = 0; index < nn; index++)
X		PlaneBuf[PlanePos++] = CompBuf[index];
X}
X
Xvoid OutRun(int nn, int cc)
X{
X	PlaneBuf[PlanePos++] = -(nn - 1);
X	PlaneBuf[PlanePos++] = cc;
X}
X
XBOOL PutLong(ULONG l)
X{
X	if (PutWord((UWORD)(l >> 16)))
X		return TRUE;
X	return PutWord((UWORD)l);
X}
X
XBOOL PutWord(UWORD w)
X{
X	if (PutChar((UBYTE)(w >> 8)))
X		return TRUE;
X	return PutChar((UBYTE)w);
X}
X
XBOOL PutChar(UBYTE b)
X{
X	char buf[1];
X
X	buf[0] = b;
X	if (Write(ofh, buf, 1) != 1) {
X		Printf("\n......Error %ld during write.\n", IoErr());
X		return TRUE;
X	}
X}
END_OF_FILE
if test 6554 -ne `wc -c <'writeiff.c'`; then
    echo shar: \"'writeiff.c'\" unpacked with wrong size!
fi
# end of 'writeiff.c'
fi
if test -f 'xcomp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xcomp.c'\"
else
echo shar: Extracting \"'xcomp.c'\" \(2470 characters\)
sed "s/^X//" >'xcomp.c' <<'END_OF_FILE'
X/* Copyright 1990 by Christopher A. Wichura.
X   See file GIFMachine.doc for full description of rights.
X*/
X
X/* This function will take the gif screen we have read in and scale it to
X   one half of its previous X size.
X
X   What we do here is just a step above skipping every other pixel (like
X   most routines I have seen do).  While we still put emphasis on the
X   even pixels, we at least take account of the odds next to them by
X   using a weighted average.
X
X   This method is by no means the best way to do this.  If anyone wants
X   to build a smarter one I would be very interested in seeing it.
X*/
X
X#include "GIFMachine.h"
X
Xextern struct GIFdescriptor gdesc;
XEXTERNBITPLANE;
X
Xextern char *AbortMsg;
X
Xextern UWORD MasterColourTable[MAXCOLOURS];
Xextern UWORD TotalColours;
X
Xvoid DoXComp(void)
X{
X	register UWORD x1;
X	register UWORD x2;
X	register UWORD y;
X	register UWORD ColourIndex;
X	register UWORD num;
X	UBYTE ColBuf[3];
X	UWORD OldNumColours;
X	UWORD NewWidth;
X
X	NewWidth = gdesc.gd_Width >> 1;
X	if (NewWidth & 1)
X		NewWidth++;
X
X	Printf("...Compressing width to %ld.\n......Line ", NewWidth);
X	OldNumColours = TotalColours;
X
X        for (y = 0; y < gdesc.gd_Height; y++) {
X		Printf("%5ld", y);
X
X		for (x1 = x2 = 0; x2 < gdesc.gd_Width; x1++, x2 += 2) {
X			num = 4;
X			ColourIndex = GetValue(x2, y);
X
X			ColBuf[0] = GetRed(ColourIndex) * 4;
X			ColBuf[1] = GetGreen(ColourIndex) * 4;
X			ColBuf[2] = GetBlue(ColourIndex) * 4;
X
X			if (x2 > 1) {
X				num += 2;
X				ColourIndex = GetValue((UWORD)(x2 - 1), y);
X
X				ColBuf[0] += GetRed(ColourIndex) * 2;
X				ColBuf[1] += GetGreen(ColourIndex) * 2;
X				ColBuf[2] += GetBlue(ColourIndex) * 2;
X			}
X
X			if (x2 + 1 < gdesc.gd_Width) {
X				num += 2;
X				ColourIndex = GetValue((UWORD)(x2 + 1), y);
X
X				ColBuf[0] += GetRed(ColourIndex) * 2;
X				ColBuf[1] += GetGreen(ColourIndex) * 2;
X				ColBuf[2] += GetBlue(ColourIndex) * 2;
X			}
X
X			ColBuf[0] = ((ColBuf[0] + num / 2) / num) << 4;
X			ColBuf[1] = ((ColBuf[1] + num / 2) / num) << 4;
X			ColBuf[2] = ((ColBuf[2] + num / 2) / num) << 4;
X
X			ColourIndex = AddColour(ColBuf);
X
X			PutValue(x1, y, ColourIndex);
X		}
X
X		PutValue(x1, y, gdesc.gd_BackGround);
X
X		if (CheckAbort(NULL)) {
X			Printf("\n%s\n", AbortMsg);
X			XCEXIT(ABORTEXITVAL);
X		}
X
X		Printf("\x9B" "5D");
X	}
X
X	Puts("\x9B" "5DCompressed.");
X
X	if (TotalColours > OldNumColours)
X		Printf("......Total unique colours increased by %ld to %ld.\n",
X			TotalColours - OldNumColours, TotalColours);
X
X	gdesc.gd_Width = NewWidth;
X}
END_OF_FILE
if test 2470 -ne `wc -c <'xcomp.c'`; then
    echo shar: \"'xcomp.c'\" unpacked with wrong size!
fi
# end of 'xcomp.c'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
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.