[comp.sources.amiga] v91i008: GIFMachine 2.104 - convert GIF images into IFF SHAMs, Part01/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 008
Archive-name: graphics/gifmachine2104/part01

[ One `source' file was uuencoded.  This requires KickStart 2.0  ...tad ]

This is an update to GIFMachine, a program that converts CompuServe GIF
file graphics into Amiga IFFs in either SHAM or 24bit DEEP format.  Version
2 has been moved to a strictly KickStart 2.0 platform, with all ARPisms
removed from the code.  It will compile with SAS 5.10 with the included
lmkfile (ignore far warning in module giftosham.c).  New options in v2
include DITHER, XFILP, YFLIP, DEEP, and BUFSIZE (note that SetVBuf()
doesn't actually do anything in 2.01 yet so this option is of dubious
effect right now).

#!/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 ReadMeFirst Sources Sources/24to12.c
#   Sources/GIFMachine.h Sources/doflip.c Sources/doimage.c
#   Sources/extensions.c Sources/giftosham.c Sources/largearrays.c
#   Sources/lmkfile Sources/mymem.c Sources/myprintf.c
#   Sources/rgbdiff.c Sources/startup.a Sources/stripborder.c
#   Sources/version.o.uu Sources/warncli.c Sources/writeiff.c
#   Sources/xcomp.c
# Wrapped by tadguy@ab20 on Wed Feb  6 20:18:33 1991
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'\" \(8774 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 extra 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, among its other toys.  (I just hate it when you
Xhave an image floating in the middle of the screen with inches of nothing
Xaround it.)
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.  (Note that
Xthis has changed with GIFMachine v2:  You can now write 24bit deep ILBMs as
Xwell.)
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 KickStart 2.0 or greater (hey, I have a
X3000 and SAS C with 2.0 includes so I dumped ARP in favor of 2.0).  It also
Xrequires a fair amount of RAM (though it does not have to be CHIP RAM or
Xcontiguous).  Alas, memory requirements have gone up with v2; the primary
Ximage now requires three bytes to store a pixel instead of two.   A 640x480
XGIF now requires about a meg of free memory to convert.
X
XGIFMachine uses the 2.0 ReadArgs() argument parser.  Thus, one can always
Xenter `GIFMachine ?' on the command line for help.  GIFMachine can not be
Xrun from the WorkBench.
X
XGIFMachine accepts the following arguments:
X
X<filespec1> ... <filespecN> [TO <directory or filespec>] [ALL]
X                            [NOBORDER <line thresh>] [XCOMP] [DITHER]
X                            [XFLIP] [YFLIP] [DEEP] [BUFSIZE <Size in KBytes>]
X
XEach filespec may contain any valid 2.0 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 no 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.  This option has been slightly
Xmodified in the v2 release:  Before, GIFMachine assumed that the value at
Xcoordinate 0,0 was the colour of the entire border area.  This is not
Xalways the case, however.  Take, for example, a GIF with the image right up
Xin the upper left corner with a large empty region to the right and below
Xof it.  Such an image would have almost none of the offending border
Xremoved.  GIFMachine will now attempt to run the stripper four times, using
Xeach of the four corners' colour for the border check.  For the most part,
Xthis does not slow this function down because a border check is aborted as
Xsoon as the <line thresh> is exceeded and GIFMachine moves to the next
Xcorner.
X
XThe next option, XCOMP, tells GIFMachine to halve the width of images.
X
XWhen the DITHER option is specified, a boustrophedonic Floyd-Steinberg
Xerror diffusion algorythm will be used when reducing the colour palette to
X12 bits.  This can help eliminate colour banding that occurs in places
Xwhere subtle shadows occur.
X
XThe XFLIP and YFLIP options will flip the image horizontally and
Xvertically, respectively.
X
XThe DEEP option will cause GIFMachine to write a 24bit deep ILBM instead of
Xa SHAM file.  The DITHER option will be ignored in this mode, however.
XWriting deep ILBMs if much faster than writing SHAMs because no
Xcomputations need to be made.  Please note that files written with this
Xoption in effect can be quite large.  Expect a 640x480 XCOMPed image to be
Xover 400k in length, for example.
X
XThe final option, BUFSIZE, allows one to change the read buffer size used
Xwhen decompressing GIFs.  It defaults to two Kbytes.  The argument is
Xspecified in number of Kbytes, not bytes.  Thus, if you have memory to burn
Xand want a large buffer you could specify a BUFSIZE 100 and you would get a
Xbuffer 100k in size.  This command does not effect the writing of the IFF
Xfile, however.
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
XGIFMachine and GIF89a compatibility:  GIFMachine should be able to read any
XGIF file written under the GIF89a specs.  GIFMachine does not, however,
Xperform aspect corrections or process Plain Text Extensions (for obvious
Xreasons), Graphic Control Extensions, or Application Extensions.
XGIFMachine will, however, detect the new Comment Extension blocks.  The
Xmessages contained in such blocks will be stored and output as ANNO chunks
Xwhen the IFF file is being written.
X
X-=> CAW
END_OF_FILE
if test 8774 -ne `wc -c <'GIFMachine.docs'`; then
    echo shar: \"'GIFMachine.docs'\" unpacked with wrong size!
fi
# end of 'GIFMachine.docs'
fi
if test -f 'ReadMeFirst' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ReadMeFirst'\"
else
echo shar: Extracting \"'ReadMeFirst'\" \(387 characters\)
sed "s/^X//" >'ReadMeFirst' <<'END_OF_FILE'
XThis is version 2.104, an update to version 2.96.  It fixes a bug in the
XStripBorder() routine which could cause the system to crash (it actually
Xappears to be more a bug in SAS 5.10's conditional code creation).
X
XI also reduced the amount of static memory declared by 1k.  Also moved some
Xof the declarations in giftosham.c to largearrays.c to avoid the `too much
Xglobal data' warning.
END_OF_FILE
if test 387 -ne `wc -c <'ReadMeFirst'`; then
    echo shar: \"'ReadMeFirst'\" unpacked with wrong size!
fi
# end of 'ReadMeFirst'
fi
if test ! -d 'Sources' ; then
    echo shar: Creating directory \"'Sources'\"
    mkdir 'Sources'
fi
if test -f 'Sources/24to12.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/24to12.c'\"
else
echo shar: Extracting \"'Sources/24to12.c'\" \(4024 characters\)
sed "s/^X//" >'Sources/24to12.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
X/* since both MasterColourTable and the PaletteBuf are the same size and
X   type we will define MCT to be the PaletteBuf to cut down on static
X   memory declarations */
X#define MasterColourTable PaletteBuf
X
Xextern UBYTE MasterColourTable[MAXCOLOURS];
Xstatic UWORD TotalColours;
X
Xextern BYTE *CurrentLineErr[3];
Xextern BYTE *LastLineErr[3];
X
Xextern char *AbortMsg;
X
X#define MAXERR 2
X
Xvoid ReduceTo12(void)
X{
X	register UWORD x;
X	register UWORD y;
X
X	PutStr("...Reducing palette to 12 bits.\n......Line ");
X
X	TotalColours = 0;
X	memset((char *)MasterColourTable, 0, sizeof(MasterColourTable));
X
X	for (y = 0; y < gdesc.gd_Height; y++) {
X		MyPrintf("%5ld", y);
X
X		if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X			MyPrintf("\n%s", AbortMsg);
X			MyExit(ABORTEXITVAL);
X		}
X
X		for (x = 0; x < gdesc.gd_Width; x++)
X			PutValue(x, y, AddColour(&BitPlane[y][x]));
X
X		PutStr("\x9B" "5D");
X	}
X
X	MyPrintf("\x9B" "5D%ld total unique colours used.\n", TotalColours);
X}
X
Xvoid DitherTo12(void)
X{
X	register UWORD x;
X	register UWORD y;
X	register int RedErr;
X	register int GreenErr;
X	register int BlueErr;
X	BYTE **cerr, **lerr, **terr;
X	struct RGB rgb;
X
X	PutStr("...Dithering palette to 12 bits.\n......Setup");
X
X	TotalColours = 0;
X	memset((char *)MasterColourTable, 0, sizeof(MasterColourTable));
X
X	cerr = (BYTE **)&CurrentLineErr[0];
X	lerr = (BYTE **)&LastLineErr[0];
X
X	/* the top, left and right borders will be used unmodified */
X
X	for (x = 0; x < gdesc.gd_Width; x++)
X		PutValue(x, 0, AddColour(&BitPlane[0][x]));
X
X	for (y = 1; y < gdesc.gd_Height; y++) {
X		PutValue(0, y, AddColour(&BitPlane[y][0]));
X		PutValue(gdesc.gd_Width - 1, y, AddColour(&BitPlane[y][gdesc.gd_Width - 1]));
X	}
X
X	/* since the error tables are alloced with MEMF_CLEAR we won't bother
X	   to clear them here.  instead, we just hit the main loop */
X
X	PutStr("\x9B" "5DLine ");
X
X	for (y = 1; y < gdesc.gd_Height; y++) {
X		MyPrintf("%5ld", y);
X
X		if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X			MyPrintf("\n%s", AbortMsg);
X			MyExit(ABORTEXITVAL);
X		}
X
X		for (x = 1; x < (gdesc.gd_Width - 1); x++) {
X			rgb = BitPlane[y][x];
X
X			RedErr   = cerr[0][x - 1] + 7*lerr[0][x - 1] + 5*lerr[0][x] + 3*lerr[0][x + 1];
X			GreenErr = cerr[1][x - 1] + 7*lerr[1][x - 1] + 5*lerr[1][x] + 3*lerr[1][x + 1];
X			BlueErr  = cerr[2][x - 1] + 7*lerr[2][x - 1] + 5*lerr[2][x] + 3*lerr[2][x + 1];
X
X			RedErr   >>= 4;
X			GreenErr >>= 4;
X			BlueErr  >>= 4;
X
X	/* now we add the errors into the colour we want.  if this would push
X	   us over 255 (and thus out of range) we subtract the error out so
X	   that we still see some dithering instead of washing out the area. */
X
X			if (rgb.rgb_Red + RedErr > 255)
X				rgb.rgb_Red -= RedErr;
X			else
X				rgb.rgb_Red += RedErr;
X
X			if (rgb.rgb_Green + GreenErr > 255)
X				rgb.rgb_Green -= GreenErr;
X			else
X				rgb.rgb_Green += GreenErr;
X
X			if (rgb.rgb_Blue + BlueErr > 255)
X				rgb.rgb_Blue -= BlueErr;
X			else
X				rgb.rgb_Blue += BlueErr;
X
X			PutValue(x, y, AddColour(&rgb));
X
X			RedErr   = (int)rgb.rgb_Red   - (int)(rgb.rgb_Red   & 0xF0);
X			GreenErr = (int)rgb.rgb_Green - (int)(rgb.rgb_Green & 0xF0);
X			BlueErr  = (int)rgb.rgb_Blue  - (int)(rgb.rgb_Blue  & 0xF0);
X
X			if (RedErr > MAXERR)
X				RedErr = (RedErr * 3) >> 2;
X
X			if (GreenErr > MAXERR)
X				GreenErr = (GreenErr * 3) >> 2;
X
X			if (BlueErr > MAXERR)
X				BlueErr = (BlueErr * 3) >> 2;
X
X			cerr[0][x] = RedErr;
X			cerr[1][x] = GreenErr;
X			cerr[2][x] = BlueErr;
X		}
X
X			terr = lerr;
X			lerr = cerr;
X			cerr = terr;
X
X		PutStr("\x9B" "5D");
X	}
X
X	MyPrintf("\x9B" "5D%ld total unique colours used.\n", TotalColours);
X}
X
XUWORD AddColour(struct RGB *rgb)
X{
X	register UWORD colour;
X
X	colour = ((rgb->rgb_Red << 4) & 0xF00) |
X		 (rgb->rgb_Green & 0xF0) |
X		 (rgb->rgb_Blue >> 4);
X
X	if (!MasterColourTable[colour]) {
X		MasterColourTable[colour] = 1;
X		TotalColours++;
X	}
X
X	return colour;
X}
END_OF_FILE
if test 4024 -ne `wc -c <'Sources/24to12.c'`; then
    echo shar: \"'Sources/24to12.c'\" unpacked with wrong size!
fi
# end of 'Sources/24to12.c'
fi
if test -f 'Sources/GIFMachine.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/GIFMachine.h'\"
else
echo shar: Extracting \"'Sources/GIFMachine.h'\" \(2870 characters\)
sed "s/^X//" >'Sources/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#include <exec/lists.h>
X#include <exec/nodes.h>
X#include <proto/dos.h>
X#include <proto/exec.h>
X#include <string.h>
X#include <stdlib.h>
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_PixelAspect;	/* Aspect Ratio = (Pixel Aspect + 15) / 64 */
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
Xstruct RGB {
X	UBYTE rgb_Red;
X	UBYTE rgb_Green;
X	UBYTE rgb_Blue;
X};
X
X#define GIF_IMAGE      0x2C
X#define GIF_EXTENSION  0x21
X#define GIF_TERMINATOR 0x3B
X
X#define GIF_COMMENT_EXT 0xFE
X
X#define MAXCOLOURS 4096
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)(a >> 8)
X#define GetGreen(a)	(UBYTE)((a >> 4) & 0xF)
X#define GetBlue(a)	(UBYTE)(a & 0xF)
X
X/* whenever we want to abort we will return this as our error code */
X#define ABORTEXITVAL 1
X
X/* this struct is used to hold the linked list of comments found in the GIF
X   file so that each can be written as a seperate ANNO chunk. */
Xstruct CommentNode {
X	struct MinNode cn_Node;
X	char *cn_Comment;
X	ULONG cn_CommentLength;
X};
X
X/* function prototypes we use */
Xextern int __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg);
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 BOOL	WriteIFF(char *, BOOL);
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	InitDiff(void);
Xextern ULONG	RGBdiff(UBYTE, UBYTE, UBYTE, UBYTE, UBYTE, UBYTE);
Xextern void	OutDump(int);
Xextern void	OutRun(int, int);
Xextern void	InitMemory(void);
Xextern char *	MyAlloc(ULONG);
Xextern void	MyFree(char *);
Xextern void	FreeAll(UWORD);
Xextern void	MyExit(ULONG);
Xextern void	DoXFlip(void);
Xextern void	DoYFlip(void);
Xextern void	ReduceTo12(void);
Xextern void	DitherTo12(void);
Xextern UWORD	AddColour(struct RGB *);
Xextern void __stdargs MyPrintf(char *, ...);
Xextern void __stdargs MySPrintf(char *, char *, ...);
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 struct RGB **BitPlane
X
X/* for use once colour palette has been reduced to 12 bits */
X#define GetValue(a, b) *((UWORD *)&BitPlane[b][a])
X#define PutValue(a, b, c) *((UWORD *)&BitPlane[b][a]) = c
END_OF_FILE
if test 2870 -ne `wc -c <'Sources/GIFMachine.h'`; then
    echo shar: \"'Sources/GIFMachine.h'\" unpacked with wrong size!
fi
# end of 'Sources/GIFMachine.h'
fi
if test -f 'Sources/doflip.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/doflip.c'\"
else
echo shar: Extracting \"'Sources/doflip.c'\" \(1470 characters\)
sed "s/^X//" >'Sources/doflip.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
Xvoid DoXFlip(void)
X{
X	register UWORD x1;
X	register UWORD x2;
X	register UWORD y;
X	struct RGB TempColourStore;
X
X	MyPrintf("...Flipping image %s.\n......%s ", "horizontally", "Line");
X
X        for (y = 0; y < gdesc.gd_Height; y++) {
X		MyPrintf("%5ld", y);
X
X		for (x1 = 0, x2 = gdesc.gd_Width - 1; x1 < x2; x1++, x2--) {
X			TempColourStore = BitPlane[y][x1];
X			BitPlane[y][x1] = BitPlane[y][x2];
X			BitPlane[y][x2] = TempColourStore;
X		}
X
X		if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X			MyPrintf("\n%s", AbortMsg);
X			MyExit(ABORTEXITVAL);
X		}
X
X		PutStr("\x9B" "5D");
X	}
X
X	MyPrintf("\x9B" "%sDFlipped.    \n", "5");
X}
X
Xvoid DoYFlip(void)
X{
X	register UWORD y1;
X	register UWORD y2;
X	register UWORD x;
X	struct RGB TempColourStore;
X
X	MyPrintf("...Flipping image %s.\n......%s ", "vertically", "Column");
X
X        for (x = 0; x < gdesc.gd_Width; x++) {
X		MyPrintf("%5ld", x);
X
X		for (y1 = 0, y2 = gdesc.gd_Height - 1; y1 < y2; y1++, y2--) {
X			TempColourStore = BitPlane[y1][x];
X			BitPlane[y1][x] = BitPlane[y2][x];
X			BitPlane[y2][x] = TempColourStore;
X		}
X
X		if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X			MyPrintf("\n%s", AbortMsg);
X			MyExit(ABORTEXITVAL);
X		}
X
X		PutStr("\x9B" "5D");
X	}
X
X	MyPrintf("\x9B" "%sDFlipped.    \n", "7");
X}
END_OF_FILE
if test 1470 -ne `wc -c <'Sources/doflip.c'`; then
    echo shar: \"'Sources/doflip.c'\" unpacked with wrong size!
fi
# end of 'Sources/doflip.c'
fi
if test -f 'Sources/doimage.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/doimage.c'\"
else
echo shar: Extracting \"'Sources/doimage.c'\" \(5352 characters\)
sed "s/^X//" >'Sources/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 struct RGB GlobalColourTable[256];
Xstatic struct RGB 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	register int index;
X	register int colours;
X	int Code;
X
X	MyPrintf("...Image #%ld encountered.\n", ImageNumber++);
X
X	if (FRead(fh, (char *)&idesc, 1, 9) != 9) {
X		PutStr("......Error reading image descriptor.\n");
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	MyPrintf("......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		MyPrintf("......Local colour map contains %ld entries.\n", colours);
X
X		for (index = 0; index < colours; index++) {
X			if (FRead(fh, &LocalColourTable[index], 1, 3) != 3) {
X				MyPrintf("......Error reading local colour #%ld.\n",
X					index);
X				return TRUE;
X			}
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 MaxCode, ClearCode, CurCode,
X		    OldCode, InCode, FreeCode;
X		int OutCount;
X		int FirstFree;
X		UBYTE InitCodeSize, FinChar, BitMask;
X
X		MyPrintf("......Decompressing line number %5ld", Ypos);
X
X		/* get the codesize and do general setup for decompression */
X		if ((CodeSize = FGetC(fh)) == -1) {
X			PutStr("\n......I/O Error during decompression.\n");
X			return TRUE;
X		}
X
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 (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X				MyPrintf("\n%s", AbortMsg);
X				MyExit(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						PutStr("\n......Corrupt GIF file (OutCount)\n");
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 ((Code = FGetC(fh)) == -1)
X		return TRUE;
X
X	/* done decompressing.  Erase decompressing message and exit */
X	PutStr("\x9B" "22D\x9BKed.\n");
X
X	if (Code != 0) {
X		PutStr("......Warning:  Unaligned packet.\n");
X		UnGetC(fh, Code);
X	}
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	register LONG size;
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 ((size = FGetC(fh)) == -1) {
X					PutStr("\n......I/O Error during decompression.\n");
X					ReadError = 1;
X					return EOFCode;
X				}
X
X				if (FRead(fh, (char *)CompData, 1, size) != size) {
X					PutStr("\n......I/O Error during decompression.\n");
X					ReadError = 1;
X					return EOFCode;
X				}
X
X				CompDataCount = size;
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	register UWORD XStore;
X	register UWORD YStore;
X
X	XStore = Xpos + idesc.id_Left;
X	YStore = Ypos + idesc.id_Top;
X
X	BitPlane[YStore][XStore] = 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		MyPrintf("\x9B" "5D%5ld", Ypos + idesc.id_Top);
X	}
X}
END_OF_FILE
if test 5352 -ne `wc -c <'Sources/doimage.c'`; then
    echo shar: \"'Sources/doimage.c'\" unpacked with wrong size!
fi
# end of 'Sources/doimage.c'
fi
if test -f 'Sources/extensions.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/extensions.c'\"
else
echo shar: Extracting \"'Sources/extensions.c'\" \(2266 characters\)
sed "s/^X//" >'Sources/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
Xstruct MinList CommentList;
Xstatic UBYTE buf[256];
X
XBOOL DoExtension(BPTR fh)
X{
X	register LONG size;
X	register LONG cmdcode;
X	register char *Comment;
X	register char *OldComment;
X	register int CommentLength;
X	register int OldCommentLength;
X	register struct CommentNode *cn;
X
X	if ((cmdcode = FGetC(fh)) == -1) {
X		PutStr("...I/O error reading extension block function code\n");
X		return TRUE;
X	}
X
X	switch(cmdcode) {
X		case GIF_COMMENT_EXT:
X			PutStr("...Comment extension encountered.  Contents will be stored in an ANNO chunk.\n");
X
X			if (!(cn = (struct CommentNode *)MyAlloc(sizeof(struct CommentNode)))) {
X				PutStr("......Out of memory allocating comment block.\n");
X				return TRUE;
X			}
X
X			Comment = NULL;
X			CommentLength = 0;
X
X			for (;;) {
X				if ((size = FGetC(fh)) == -1) {
X					PutStr("......I/O Error reading comment block.\n");
X					return TRUE;
X				}
X
X				if (size) {
X					if (FRead(fh, buf, 1, size) != size) {
X						PutStr("......I/O Error reading comment block.\n");
X						return TRUE;
X					}
X
X					OldComment = Comment;
X					OldCommentLength = CommentLength;
X					CommentLength += size;
X
X					if (!(Comment = MyAlloc(CommentLength))) {
X						PutStr("......Out of memory allocating comment block.\n");
X						return TRUE;
X					}
X
X					if (OldCommentLength) {
X						CopyMem(OldComment, Comment, OldCommentLength);
X						MyFree(OldComment);
X					}
X
X					CopyMem(buf, &Comment[OldCommentLength], size);
X				} else {	/* end of comment so store it */
X					cn->cn_Comment = Comment;
X					cn->cn_CommentLength = CommentLength;
X					AddTail((struct List *)&CommentList, (struct Node *)cn);
X					return FALSE;
X				}
X			}
X			break;
X
X		default:
X			MyPrintf("...Extension block function code #%ld not know, skipping.\n",
X			 cmdcode);
X
X			/* we must skip over any data for the extension block */
X			for (;;) {
X				if ((size = FGetC(fh)) == -1) {
X					PutStr("...I/O Error skipping unknown extension block.\n");
X					return TRUE;
X				}
X
X				if (size == 0)
X					return FALSE;
X
X				if (FRead(fh, buf, 1, size) != size) {
X					PutStr("...I/O Error skipping unknown extension block.\n");
X					return TRUE;
X				}
X			}
X			break;
X	}
X}
END_OF_FILE
if test 2266 -ne `wc -c <'Sources/extensions.c'`; then
    echo shar: \"'Sources/extensions.c'\" unpacked with wrong size!
fi
# end of 'Sources/extensions.c'
fi
if test -f 'Sources/giftosham.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/giftosham.c'\"
else
echo shar: Extracting \"'Sources/giftosham.c'\" \(5180 characters\)
sed "s/^X//" >'Sources/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 char *AbortMsg;
X
Xextern BOOL Laced;
X
XUWORD *SHAMmem;
X
Xstruct RGB Palette[16];
X
Xextern UBYTE PaletteBuf[MAXCOLOURS];
Xextern ULONG ColourBuf[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	MyPrintf("...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			MyPrintf("s %5ld-%5ld", y, y + 1);
X		else
X			MyPrintf(" %5ld", y);
X
X		if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X			MyPrintf("\n%s", AbortMsg);
X			MyExit(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		MyPrintf(", %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		MyPrintf("\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		MySPrintf(TextBuf, "%ld.%03ld", ErrPerPixel / 1000, ErrPerPixel % 1000);
X
X		MyPrintf("\x9B" "4DTotal 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 5180 -ne `wc -c <'Sources/giftosham.c'`; then
    echo shar: \"'Sources/giftosham.c'\" unpacked with wrong size!
fi
# end of 'Sources/giftosham.c'
fi
if test -f 'Sources/largearrays.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/largearrays.c'\"
else
echo shar: Extracting \"'Sources/largearrays.c'\" \(192 characters\)
sed "s/^X//" >'Sources/largearrays.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
XUBYTE PaletteBuf[MAXCOLOURS];
XULONG ColourBuf[MAXCOLOURS];
END_OF_FILE
if test 192 -ne `wc -c <'Sources/largearrays.c'`; then
    echo shar: \"'Sources/largearrays.c'\" unpacked with wrong size!
fi
# end of 'Sources/largearrays.c'
fi
if test -f 'Sources/lmkfile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/lmkfile'\"
else
echo shar: Extracting \"'Sources/lmkfile'\" \(939 characters\)
sed "s/^X//" >'Sources/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 mymem.o warncli.o doimage.o extensions.o writeiff.o 24to12.o stripborder.o xcomp.o doflip.o rgbdiff.o giftosham.o myprintf.o largearrays.o
XLIBS = LIB:LCR.lib LIB:amiga2.0.lib
X
X.c.o:
X	LC $(CFLAGS) $*
X
X.a.o:
X	ASM -iINCLUDE: $*
X
XGIFMachine: $(OBJS)
X	UpCVersion version.o
X	BLink <WITH < (GIFMachine.lnk)
XFROM $(OBJS) version.o
XTO GIFMachine
XLIB $(LIBS)
X$(LFLAGS)
X<
X
Xmain.o: main.c $(HDR)
X
Xdoimage.o: doimage.c $(HDR)
X
Xextensions.o: extensions.c $(HDR)
X
Xwriteiff.o: writeiff.c $(HDR)
X
Xstripborder.o: stripborder.c $(HDR)
X
Xxcomp.o: xcomp.c $(HDR)
X
Xdoflip.o: doflip.c $(HDR)
X
Xgiftosham.o: giftosham.c $(HDR)
X
Xrgbdiff.o: rgbdiff.c $(HDR)
X
X24to12.o: 24to12.c $(HDR)
X
Xlargearrays.o: largearrays.c $(HDR)
END_OF_FILE
if test 939 -ne `wc -c <'Sources/lmkfile'`; then
    echo shar: \"'Sources/lmkfile'\" unpacked with wrong size!
fi
# end of 'Sources/lmkfile'
fi
if test -f 'Sources/mymem.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/mymem.c'\"
else
echo shar: Extracting \"'Sources/mymem.c'\" \(1250 characters\)
sed "s/^X//" >'Sources/mymem.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 <exec/lists.h>
X#include <exec/nodes.h>
X#include <exec/memory.h>
X#include <proto/exec.h>
X
Xstruct MyMem {
X	struct MinNode mm_Node;
X	ULONG mm_Size;
X};
X
Xstruct MinList Mem[2];
XUWORD CurrentMem;
X
Xvoid InitMemory(void)
X{
X	NewList((struct List *)&Mem[0]);
X	NewList((struct List *)&Mem[1]);
X	CurrentMem = 0;
X}
X
Xchar *MyAlloc(ULONG size)
X{
X	register struct MyMem *theMemory;
X	register ULONG newsize;
X
X	newsize = size + sizeof(struct MyMem);
X
X	if (!(theMemory = (struct MyMem *)AllocMem(newsize, MEMF_PUBLIC|MEMF_CLEAR)))
X		return NULL;
X
X	AddTail((struct List *)&Mem[CurrentMem], (struct Node *)&theMemory->mm_Node);
X	theMemory->mm_Size = newsize;
X
X	return (char *)theMemory + sizeof(struct MyMem);
X}
X
Xvoid MyFree(char *MemPtr)
X{
X	register struct MyMem *theMemory;
X
X	theMemory = (struct MyMem *)(MemPtr - sizeof(struct MyMem));
X
X	Remove((struct Node *)&theMemory->mm_Node);
X	FreeMem((char *)theMemory, theMemory->mm_Size);
X}
X
Xvoid FreeAll(UWORD memlist)
X{
X	register struct MyMem *theMemory;
X
X	while (theMemory = (struct MyMem *)RemTail((struct List *)&Mem[memlist]))
X		FreeMem((char *)theMemory, theMemory->mm_Size);
X}
END_OF_FILE
if test 1250 -ne `wc -c <'Sources/mymem.c'`; then
    echo shar: \"'Sources/mymem.c'\" unpacked with wrong size!
fi
# end of 'Sources/mymem.c'
fi
if test -f 'Sources/myprintf.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/myprintf.c'\"
else
echo shar: Extracting \"'Sources/myprintf.c'\" \(712 characters\)
sed "s/^X//" >'Sources/myprintf.c' <<'END_OF_FILE'
X#include <proto/dos.h>
X#include <stdarg.h>
X
Xvoid RawDoFmt(char *, APTR, void(*)(), APTR);
X#pragma syscall RawDoFmt 20a ba9804
X
Xvoid __stdargs MyPrintf(char *fmt, ...)
X{
X	va_list args;
X
X	va_start(args, fmt);
X	VPrintf((UBYTE *)fmt, (LONG *)args);
X	Flush(Output());
X	va_end(args);
X}
X
Xstatic void __regargs MySPrintfSupp(char);
X
Xvoid __stdargs MySPrintf(char *buf, char *fmt, ...)
X{
X	va_list args;
X
X	va_start(args, fmt);
X	RawDoFmt(fmt, (APTR)args, MySPrintfSupp, (APTR)buf)
X	va_end(args);
X}
X
Xextern long __builtin_getreg(int);
Xextern void __builtin_putreg(int, char *);
X
Xstatic void __regargs MySPrintfSupp(char Char)
X{
X	char *ptr;
X
X	ptr = (char *)__builtin_getreg(11);
X	*ptr++ = Char;
X	__builtin_putreg(11, ptr);
X}
END_OF_FILE
if test 712 -ne `wc -c <'Sources/myprintf.c'`; then
    echo shar: \"'Sources/myprintf.c'\" unpacked with wrong size!
fi
# end of 'Sources/myprintf.c'
fi
if test -f 'Sources/rgbdiff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/rgbdiff.c'\"
else
echo shar: Extracting \"'Sources/rgbdiff.c'\" \(876 characters\)
sed "s/^X//" >'Sources/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 <'Sources/rgbdiff.c'`; then
    echo shar: \"'Sources/rgbdiff.c'\" unpacked with wrong size!
fi
# end of 'Sources/rgbdiff.c'
fi
if test -f 'Sources/startup.a' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/startup.a'\"
else
echo shar: Extracting \"'Sources/startup.a'\" \(4359 characters\)
sed "s/^X//" >'Sources/startup.a' <<'END_OF_FILE'
X INCLUDE "exec/types.i"
X INCLUDE "exec/execbase.i"
X INCLUDE "exec/memory.i"
X INCLUDE "libraries/dosextens.i"
X
X XREF @main
X
X XREF _LVOOpenLibrary
X XREF _LVOOldOpenLibrary
X XREF _LVOCloseLibrary
X XREF _LVOSetSignal
X XREF _LVOForbid
X XREF _LVOWaitPort
X XREF _LVOGetMsg
X XREF _LVOReplyMsg
X XREF _LVOSetIoErr
X XREF _LVOAllocVec
X XREF _LVOFreeVec
X XREF _LVOOutput
X XREF _LVOWrite
X
X XREF _LinkerDB
X XREF __BSSBAS
X XREF __BSSLEN
X XREF _RESLEN
X XREF _RESBASE
X XREF _NEWDATAL
X
X XREF _AbsExecBase
X
XLIBCALL	MACRO
X	jsr _LVO\1(a6)
X	ENDM
X
X  SECTION StartCode,CODE
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	LIBCALL	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	LIBCALL	WaitPort
X	lea	pr_MsgPort(a3),a0
X	LIBCALL	GetMsg
X	move.l	d0,d7
X
XFromCLI:
X	lea	DOSlib(pc),a1
X	moveq	#36,d0
X	LIBCALL	OpenLibrary
X	tst.l	d0
X	bne.s	DoMain
X
X	lea	DOSlib(pc),a1
X	LIBCALL	OldOpenLibrary
X	tst.l	d0
X	beq.s	bomb
X
X	move.l	d0,a6
X	LIBCALL	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	LIBCALL	Write
X
X	move.l	a6,a1
X	move.l	_AbsExecBase.W,a6
X	LIBCALL	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
X	rts
X
XDoMain:
X	move.l	d0,-(sp)
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	move.l	#MEMF_PUBLIC+MEMF_CLEAR,d1
X	LIBCALL	AllocVec
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	move.l	(sp)+,a6	; get dos base
X	addq.l	#8,sp		; pop d0/a0 off of stack
X
X	moveq	#ERROR_NO_FREE_STORE,d1
X	LIBCALL	SetIoErr
X
X	move.l	a6,a1
X	move.l	_AbsExecBase.W,a6
X	LIBCALL	CloseLibrary
X
X	moveq	#20,d0
X	rts
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	(sp)+,_DOSBase(a4)
X	move.l	d7,_WBenchMsg(a4)
X
X	move.l	_AbsExecBase.W,a6
X	move.l	a6,_SysBase(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	movem.l	sp,__StackPtr(a4)
X
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,d3			; 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
X	move.l	_DOSBase(a4),a6
X	moveq	#0,d1
X	LIBCALL	SetIoErr
X
X	move.l	a6,a1
X	move.l	_AbsExecBase.W,a6
X	LIBCALL	CloseLibrary
X
X	movea.l	__StackPtr(a4),sp
X
X	move.l	a4,a1
X	sub.l	#_RESBASE,a1
X	LIBCALL	FreeVec
X
X	move.l	d3,d0			; restore return code
X	rts
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	LIBCALL	Forbid
X	movea.l	d2,a1
X	LIBCALL	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
XDOSlib	dc.b "dos.library",0
X
XMsg1	dc.b "You need KickStart 2.0 or greater.",13
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 _DOSBase
X XDEF _SysBase
X XDEF _IntuitionBase
X XDEF _WBenchMsg
X XDEF __StackPtr
X
X_DOSBase	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 4359 -ne `wc -c <'Sources/startup.a'`; then
    echo shar: \"'Sources/startup.a'\" unpacked with wrong size!
fi
# end of 'Sources/startup.a'
fi
if test -f 'Sources/stripborder.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/stripborder.c'\"
else
echo shar: Extracting \"'Sources/stripborder.c'\" \(3390 characters\)
sed "s/^X//" >'Sources/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
X#define BorderCheck(a, b) ((BitPlane[b][a].rgb_Red   != BorderCol.rgb_Red) || \
X			   (BitPlane[b][a].rgb_Green != BorderCol.rgb_Green) || \
X			   (BitPlane[b][a].rgb_Blue  != BorderCol.rgb_Blue))
X
Xvoid StripBorder(void)
X{
X	register UWORD x;
X	register UWORD y;
X	register int thresh;
X	register BOOL breakout;
X	LONG LeftEdge, TopEdge;
X	LONG Width, Height;
X	UWORD OrigWidth, OrigHeight;
X	int WidthThresh, HeightThresh;
X	int Corner;
X
X	struct RGB BorderCol;
X
X	PutStr("...Removing border.\n");
X
X	OrigWidth = gdesc.gd_Width;
X	OrigHeight = gdesc.gd_Height;
X
X	for (Corner = 0; Corner < 4; Corner++) {
X		x = (Corner & 1) ? (gdesc.gd_Width - 1) : 0;
X		y = (Corner & 2) ? (gdesc.gd_Height - 1) : 0;
X
X		BorderCol = BitPlane[y][x];
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 (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X				PutStr(AbortMsg);
X				MyExit(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 (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X				PutStr(AbortMsg);
X				MyExit(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 (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X				PutStr(AbortMsg);
X				MyExit(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 (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X				PutStr(AbortMsg);
X				MyExit(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				PutStr("......Too much of picture would be removed.  Not modified.\n");
X				return;
X			}
X
X			for (y = 0; y < Height; y++) {
X				for (x = 0; x < Width; x++)
X					BitPlane[y][x] = BitPlane[TopEdge + y][LeftEdge + x];
X
X				BitPlane[y][x].rgb_Red   =
X				BitPlane[y][x].rgb_Green =
X				BitPlane[y][x].rgb_Blue  = 0;
X
X				if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X					PutStr(AbortMsg);
X					MyExit(ABORTEXITVAL);
X				}
X			}
X
X			gdesc.gd_Width = Width;
X			gdesc.gd_Height = Height;
X		}
X	}
X
X	if ((gdesc.gd_Width != OrigWidth) || (gdesc.gd_Height != OrigHeight)) {
X		if (gdesc.gd_Width & 1)
X			gdesc.gd_Width++;
X
X		MyPrintf("......New width = %ld, New height = %ld\n",
X			gdesc.gd_Width, gdesc.gd_Height);
X	}
X}
END_OF_FILE
if test 3390 -ne `wc -c <'Sources/stripborder.c'`; then
    echo shar: \"'Sources/stripborder.c'\" unpacked with wrong size!
fi
# end of 'Sources/stripborder.c'
fi
if test -f 'Sources/version.o.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/version.o.uu'\"
else
echo shar: Extracting \"'Sources/version.o.uu'\" \(197 characters\)
sed "s/^X//" >'Sources/version.o.uu' <<'END_OF_FILE'
Xbegin 666 version.o
XM```#YP````````/I````!P````(```!@,BXY-B`H,3<@3V-T(#DP*0``````V
XM``/O`0```E]697)S:6]N``````$```-?5F5R<VEO;DE$```````(`0```U]2-
X6979I<VEO;@````````0````````#\@-?8
X``
Xend
Xsize 112
END_OF_FILE
if test 197 -ne `wc -c <'Sources/version.o.uu'`; then
    echo shar: \"'Sources/version.o.uu'\" unpacked with wrong size!
fi
# end of 'Sources/version.o.uu'
fi
if test -f 'Sources/warncli.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/warncli.c'\"
else
echo shar: Extracting \"'Sources/warncli.c'\" \(1701 characters\)
sed "s/^X//" >'Sources/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/exec.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	BOOL	OpenedIntui;
X
X	if (IntuitionBase)
X		OpenedIntui = FALSE;
X	else {
X		if (!(IntuitionBase = OpenLibrary("intuition.library", 0)))
X			return;
X		OpenedIntui = TRUE;
X	}
X
X	AutoRequest(NULL,&BodyText1,NULL,&ContinueText,0,0,220,64);
X
X	if (OpenedIntui)
X		CloseLibrary(IntuitionBase);
X}
END_OF_FILE
if test 1701 -ne `wc -c <'Sources/warncli.c'`; then
    echo shar: \"'Sources/warncli.c'\" unpacked with wrong size!
fi
# end of 'Sources/warncli.c'
fi
if test -f 'Sources/writeiff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/writeiff.c'\"
else
echo shar: Extracting \"'Sources/writeiff.c'\" \(9234 characters\)
sed "s/^X//" >'Sources/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#include <libraries/iffparse.h>
X#include <graphics/view.h>
X#include <proto/iffparse.h>
X#include <dos/datetime.h>
X
Xextern struct GIFdescriptor gdesc;
XEXTERNBITPLANE;
X
Xextern struct MinList CommentList;
X
Xextern char *AbortMsg;
X
Xextern UWORD *SHAMmem;
XBYTE *PlaneBuf;
X
XBOOL Laced;
X
XUBYTE *Planes[8];
X
Xstatic UBYTE CompBuf[256];
Xstatic ULONG PlanePos;
X
X/* our version number stuff */
Xextern ULONG __far Version;
Xextern ULONG __far Revision;
X
XBOOL WriteIFF(char *tofile, BOOL DeepFlag)
X{
X	register struct IFFHandle *iff;
X	register int index;
X	register ULONG ChunkSize;
X	register UWORD current;
X	char WrittenBy[40];
X
X	ColorRegister ColourBuf;
X
X	PutStr("...Writing IFF file.");
X
X	if (!(iff = AllocIFF())) {
X		PutStr("\n......Error allocating IFF handle.\n");
X		return TRUE;
X	}
X
X	if (!(iff->iff_Stream = Open(tofile, MODE_NEWFILE))) {
X		MyPrintf("\n......Error %ld trying to create %s.", IoErr(), tofile);
X		goto EndWriteIFF;
X	}
X
X	InitIFFasDOS(iff);
X
X	if (OpenIFF(iff, IFFF_WRITE)) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
X
X	if (PushChunk(iff, ID_ILBM, FORM, IFFSIZE_UNKNOWN)) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
X
X	if (PushChunk(iff, 0L, MakeID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
X
X	MySPrintf(WrittenBy, "Written by GIFMachine v%ld.%ld on ", Version, Revision);
X
X	if (WriteChunkBytes(iff, (APTR)&WrittenBy, strlen(WrittenBy)) != strlen(WrittenBy)) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
X
X	{
X		struct DateTime dat;
X		char Date[LEN_DATSTRING + 1];
X		int DateLength;
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 + 1);
X		DateToStr(&dat);
X
X		DateLength = strlen(Date) + 1;
X		if (WriteChunkBytes(iff, (APTR)&Date, DateLength) != DateLength) {
X			PutStr("\n......Error writing to IFF.\n");
X			goto EndWriteIFF;
X		}
X	}
X
X	if (PopChunk(iff)) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
X
X	{
X		struct CommentNode *cn;
X		char ANNObuf[1];
X
X#define C_BLOCK_ID "GIF Comment Block: "
X
X		ANNObuf[0] = 0;
X
X		while (cn = (struct CommentNode *)RemHead((struct List *)&CommentList)) {
X			if (PushChunk(iff, 0L, MakeID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
X				PutStr("\n......Error writing to IFF.\n");
X				goto EndWriteIFF;
X			}
X
X			if (WriteChunkBytes(iff, (APTR)C_BLOCK_ID, strlen(C_BLOCK_ID)) != strlen(C_BLOCK_ID)) {
X				PutStr("\n......Error writing to IFF.\n");
X				goto EndWriteIFF;
X			}
X
X			if (WriteChunkBytes(iff, (APTR)cn->cn_Comment, cn->cn_CommentLength) != cn->cn_CommentLength) {
X				PutStr("\n......Error writing to IFF.\n");
X				goto EndWriteIFF;
X			}
X
X			if (WriteChunkBytes(iff, (APTR)ANNObuf, 1) != 1) {
X				PutStr("\n......Error writing to IFF.\n");
X				goto EndWriteIFF;
X			}
X
X			if (PopChunk(iff)) {
X				PutStr("\n......Error writing to IFF.\n");
X				goto EndWriteIFF;
X			}
X		}
X	}
X
X	if (PushChunk(iff, 0L, ID_BMHD, sizeof(BitMapHeader))) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
X
X	{
X		BitMapHeader	bmh;
X
X		bmh.w	             = gdesc.gd_Width & ~1L; /* make sure width is even */
X		bmh.h	             = gdesc.gd_Height;
X		bmh.x       = bmh.y  = 0;
X		bmh.nPlanes          = (DeepFlag ? 24 : 6);
X		bmh.masking          = mskNone;
X		bmh.compression      = cmpByteRun1;
X		bmh.pad1             = 0;
X		bmh.transparentColor = 0;
X		bmh.xAspect          = (Laced ? x320x400Aspect : x320x200Aspect);
X		bmh.yAspect          = (Laced ? y320x400Aspect : y320x200Aspect);
X		bmh.pageWidth        = 320;
X		bmh.pageHeight       = (Laced ? 400 : 200);
X
X		if (WriteChunkBytes(iff, (APTR)&bmh, sizeof(BitMapHeader)) != sizeof(BitMapHeader)) {
X			PutStr("\n......Error writing to IFF.\n");
X			goto EndWriteIFF;
X		}
X	}
X
X	if (PopChunk(iff)) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
X
X	if (PushChunk(iff, 0L, ID_CAMG, 4)) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
X
X	{
X		LONG CAMGbuf[1];
X
X		CAMGbuf[0] = (DeepFlag ? 0 : HAM) | (Laced ? LACE : 0);
X
X		if (WriteChunkBytes(iff, (APTR)&CAMGbuf, 4) != 4) {
X			PutStr("\n......Error writing to IFF.\n");
X			goto EndWriteIFF;
X		}
X	}
X
X	if (PopChunk(iff)) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
X
X	if (!DeepFlag) {
X		if (PushChunk(iff, 0L, ID_CMAP, 16 * 3)) {
X			PutStr("\n......Error writing to IFF.\n");
X			goto EndWriteIFF;
X		}
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 (WriteChunkBytes(iff, (APTR)&ColourBuf, sizeofColorRegister) != sizeofColorRegister) {
X				PutStr("\n......Error writing to IFF.\n");
X				goto EndWriteIFF;
X			}
X		}
X
X		if (PopChunk(iff)) {
X			PutStr("\n......Error writing to IFF.\n");
X			goto EndWriteIFF;
X		}
X
X		ChunkSize = (Laced ? gdesc.gd_Height / 2 : gdesc.gd_Height) * 16 * sizeof(UWORD);
X
X		if (PushChunk(iff, 0L, MakeID('S','H','A','M'), ChunkSize + 2)) {
X			PutStr("\n......Error writing to IFF.\n");
X			goto EndWriteIFF;
X		}
X
X		{
X			UWORD SHAMversion[1];
X
X			SHAMversion[0] = 0;
X
X			if (WriteChunkBytes(iff, (APTR)&SHAMversion, sizeof(UWORD)) != sizeof(UWORD)) {
X				PutStr("\n......Error writing to IFF.\n");
X				goto EndWriteIFF;
X			}
X		}
X
X		if (WriteChunkBytes(iff, (APTR)SHAMmem, ChunkSize) != ChunkSize) {
X			PutStr("\n......Error writing to IFF.\n");
X			goto EndWriteIFF;
X		}
X
X		if (PopChunk(iff)) {
X			PutStr("\n......Error writing to IFF.\n");
X			goto EndWriteIFF;
X		}
X	} /* end if (!DeepFlag) */
X
X	if (PushChunk(iff, 0L, ID_BODY, IFFSIZE_UNKNOWN)) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
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		register int index;
X		UBYTE PlaneMask, ColMask;
X		UWORD Cols;
X
X		PutStr("\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			MyPrintf("%5ld", y);
X
X			if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X				MyPrintf("\n%s", AbortMsg);
X				CloseIFF(iff);
X				Close(iff->iff_Stream);
X				FreeIFF(iff);
X				MyExit(ABORTEXITVAL);
X			}
X
X			for (index = 0; index < (DeepFlag ? 3 : 1); index++) {
X				col = 0;
X				ColMask = 1L << 7;
X
X				for (x = 0; x < gdesc.gd_Width; x++) {
X					if (DeepFlag)
X						current = *((UBYTE *)&BitPlane[y][x]+index);
X					else
X						current = GetValue(x, y);
X
X					PlaneMask = 1;
X					for (plane = 0; plane < (DeepFlag ? 8 : 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 < (DeepFlag ? 8 : 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 (WriteChunkBytes(iff, (APTR)PlaneBuf, PlanePos) != PlanePos) {
X							PutStr("\n......Error writing to IFF.\n");
X							goto EndWriteIFF;
X						}
X
X						memset((char *)Planes[plane], 0, Cols);
X					}
X				}
X			}
X
X			MyPrintf("\x9B" "5D");
X		}
X
X	}
X
X	if (PopChunk(iff)) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
X
X	if (PopChunk(iff)) {
X		PutStr("\n......Error writing to IFF.\n");
X		goto EndWriteIFF;
X	}
X
X	PutStr("\x9B" "5D\x9BKWritten.\n");
X
XEndWriteIFF:
X	CloseIFF(iff);
X	if (iff->iff_Stream)
X		Close(iff->iff_Stream);
X	FreeIFF(iff);
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}
END_OF_FILE
if test 9234 -ne `wc -c <'Sources/writeiff.c'`; then
    echo shar: \"'Sources/writeiff.c'\" unpacked with wrong size!
fi
# end of 'Sources/writeiff.c'
fi
if test -f 'Sources/xcomp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Sources/xcomp.c'\"
else
echo shar: Extracting \"'Sources/xcomp.c'\" \(2146 characters\)
sed "s/^X//" >'Sources/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
Xvoid DoXComp(void)
X{
X	register UWORD x1;
X	register UWORD x2;
X	register UWORD y;
X	register UWORD num;
X	UWORD ColBuf[3];
X	UWORD NewWidth;
X
X	NewWidth = gdesc.gd_Width >> 1;
X	if (NewWidth & 1)
X		NewWidth++;
X
X	MyPrintf("...Compressing width to %ld.\n......Line ", NewWidth);
X
X        for (y = 0; y < gdesc.gd_Height; y++) {
X		MyPrintf("%5ld", y);
X
X		for (x1 = x2 = 0; x2 < gdesc.gd_Width; x1++, x2 += 2) {
X			num = 4;
X
X			ColBuf[0] = BitPlane[y][x2].rgb_Red * 4;
X			ColBuf[1] = BitPlane[y][x2].rgb_Green * 4;
X			ColBuf[2] = BitPlane[y][x2].rgb_Blue * 4;
X
X			if (x2 > 1) {
X				num += 2;
X
X				ColBuf[0] += BitPlane[y][x2 - 1].rgb_Red * 2;
X				ColBuf[1] += BitPlane[y][x2 - 1].rgb_Green * 2;
X				ColBuf[2] += BitPlane[y][x2 - 1].rgb_Blue * 2;
X			}
X
X			if (x2 + 1 < gdesc.gd_Width) {
X				num += 2;
X
X				ColBuf[0] += BitPlane[y][x2 + 1].rgb_Red * 2;
X				ColBuf[1] += BitPlane[y][x2 + 1].rgb_Green * 2;
X				ColBuf[2] += BitPlane[y][x2 + 1].rgb_Blue * 2;
X			}
X
X			BitPlane[y][x1].rgb_Red   = ((ColBuf[0] + num / 2) / num);
X			BitPlane[y][x1].rgb_Green = ((ColBuf[1] + num / 2) / num);
X			BitPlane[y][x1].rgb_Blue  = ((ColBuf[2] + num / 2) / num);
X		}
X
X		BitPlane[y][x1].rgb_Red = BitPlane[y][x1].rgb_Green = BitPlane[y][x1].rgb_Blue = 0;
X
X		if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
X			MyPrintf("\n%s", AbortMsg);
X			MyExit(ABORTEXITVAL);
X		}
X
X		PutStr("\x9B" "5D");
X	}
X
X	PutStr("\x9B" "5DCompressed.\n");
X
X	gdesc.gd_Width = NewWidth;
X}
END_OF_FILE
if test 2146 -ne `wc -c <'Sources/xcomp.c'`; then
    echo shar: \"'Sources/xcomp.c'\" unpacked with wrong size!
fi
# end of 'Sources/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.misc.