/* Copyright 1990 by Christopher A. Wichura. See file GIFMachine.doc for full description of rights. */ #include "GIFMachine.h" extern struct GIFdescriptor gdesc; EXTERNBITPLANE; static struct ImageDesc idesc; extern struct RGB GlobalColourTable[256]; static struct RGB LocalColourTable[256]; extern ULONG ImageNumber; extern char *AbortMsg; static UWORD Xpos, Ypos; static BOOL interleave; static UBYTE LeaveStep[5] = {1, 8, 8, 4, 2}; static UBYTE LeaveFirst[5] = {0, 0, 4, 2, 1}; /* some variables used by the decompressor */ static int ReadError; static UBYTE CodeSize; static int EOFCode; static UBYTE ReadMask; static int CompDataPointer; static int CompDataCount; static UBYTE CompData[256]; /* tables used by the decompressor */ static UWORD Prefix[4096]; static UBYTE Suffix[4096]; static UBYTE OutCode[1025]; BOOL DoImage(BPTR fh) { register int index; register int colours; int Code; MyPrintf("...Image #%ld encountered.\n", ImageNumber++); if (FRead(fh, (char *)&idesc, 1, 9) != 9) { PutStr("......Error reading image descriptor.\n"); return TRUE; } FlipWord(&idesc.id_Left); FlipWord(&idesc.id_Top); FlipWord(&idesc.id_Width); FlipWord(&idesc.id_Height); interleave = idesc.id_Info & 1L << 6; if (interleave) interleave = 1; MyPrintf("......Xpos from %ld to %ld, Ypos from %ld to %ld, %sinterlaced.\n", idesc.id_Left, idesc.id_Left + idesc.id_Width - 1, idesc.id_Top, idesc.id_Top + idesc.id_Height - 1, interleave ? "" : "not "); if (idesc.id_Info & 1L << 7) { colours = 1L << ((idesc.id_Info & 7) + 1); MyPrintf("......Local colour map contains %ld entries.\n", colours); for (index = 0; index < colours; index++) { if (FRead(fh, &LocalColourTable[index], 1, 3) != 3) { MyPrintf("......Error reading local colour #%ld.\n", index); return TRUE; } } } else { colours = 1L << ((gdesc.gd_ColInfo & 7) + 1); CopyMem((char *)GlobalColourTable, (char *)LocalColourTable, sizeof(LocalColourTable)); } Xpos = Ypos = 0; /* now we are ready to read the image in so do it! */ { int MaxCode, ClearCode, CurCode, OldCode, InCode, FreeCode; int OutCount; int FirstFree; UBYTE InitCodeSize, FinChar, BitMask; MyPrintf("......Decompressing line number %5ld", Ypos); /* get the codesize and do general setup for decompression */ if ((CodeSize = FGetC(fh)) == -1) { PutStr("\n......I/O Error during decompression.\n"); return TRUE; } ClearCode = 1L << CodeSize; EOFCode = ClearCode + 1; FreeCode = FirstFree = ClearCode + 2; CodeSize++; /* per GIF spec */ InitCodeSize = CodeSize; MaxCode = 1L << CodeSize; ReadError = ReadMask = OutCount = 0; CompDataPointer = CompDataCount = 0; BitMask = colours - 1; Code = ReadCode(fh); while (Code != EOFCode) { if (ReadError) return TRUE; if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { MyPrintf("\n%s", AbortMsg); MyExit(ABORTEXITVAL); } if (Code == ClearCode) { CodeSize = InitCodeSize; MaxCode = 1L << CodeSize; FreeCode = FirstFree; FinChar = CurCode = OldCode = Code = ReadCode(fh); AddPixel(FinChar); } else { CurCode = InCode = Code; if (CurCode >= FreeCode) { CurCode = OldCode; OutCode[OutCount++] = FinChar; } while (CurCode > BitMask) { if (OutCount > 1024) { PutStr("\n......Corrupt GIF file (OutCount)\n"); return TRUE; } OutCode[OutCount++] = Suffix[CurCode]; CurCode = Prefix[CurCode]; } FinChar = CurCode; AddPixel(FinChar); for (index = OutCount - 1; index >= 0; index--) AddPixel(OutCode[index]); OutCount = 0; Prefix[FreeCode] = OldCode; Suffix[FreeCode] = FinChar; OldCode = InCode; if (++FreeCode >= MaxCode) { if (CodeSize < 12) { CodeSize++; MaxCode <<= 1; } } } Code = ReadCode(fh); } } if ((Code = FGetC(fh)) == -1) return TRUE; /* done decompressing. Erase decompressing message and exit */ PutStr("\x9B" "22D\x9BKed.\n"); if (Code != 0) { PutStr("......Warning: Unaligned packet.\n"); UnGetC(fh, Code); } return FALSE; } static UBYTE ByteBuf; int ReadCode(BPTR fh) { register int temp; register int DstMasked; register int DstMask; register LONG size; temp = 0; DstMasked = 1L << CodeSize; for (DstMask = 1; DstMask != DstMasked; DstMask <<= 1) { if (!ReadMask) { if (CompDataPointer == CompDataCount) { if ((size = FGetC(fh)) == -1) { PutStr("\n......I/O Error during decompression.\n"); ReadError = 1; return EOFCode; } if (FRead(fh, (char *)CompData, 1, size) != size) { PutStr("\n......I/O Error during decompression.\n"); ReadError = 1; return EOFCode; } CompDataCount = size; CompDataPointer = 0; } ReadMask = 1; ByteBuf = CompData[CompDataPointer++]; } if (ByteBuf & ReadMask) temp |= DstMask; ReadMask <<= 1; } return temp; } void AddPixel(UBYTE index) { register UWORD XStore; register UWORD YStore; XStore = Xpos + idesc.id_Left; YStore = Ypos + idesc.id_Top; BitPlane[YStore][XStore] = LocalColourTable[index]; if (++Xpos == idesc.id_Width) { Xpos = 0; Ypos += LeaveStep[interleave]; if (Ypos >= idesc.id_Height) Ypos = LeaveFirst[++interleave]; MyPrintf("\x9B" "5D%5ld", Ypos + idesc.id_Top); } }