home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / disks / disk405.lzh / GIFMachine / Sources / doimage.c < prev    next >
C/C++ Source or Header  |  1990-11-17  |  5KB  |  245 lines

  1. /* Copyright 1990 by Christopher A. Wichura.
  2.    See file GIFMachine.doc for full description of rights.
  3. */
  4.  
  5. #include "GIFMachine.h"
  6.  
  7. extern struct GIFdescriptor gdesc;
  8. EXTERNBITPLANE;
  9.  
  10. static struct ImageDesc idesc;
  11. extern struct RGB GlobalColourTable[256];
  12. static struct RGB LocalColourTable[256];
  13. extern ULONG ImageNumber;
  14.  
  15. extern char *AbortMsg;
  16.  
  17. static UWORD Xpos, Ypos;
  18. static BOOL interleave;
  19.  
  20. static UBYTE LeaveStep[5]  = {1, 8, 8, 4, 2};
  21. static UBYTE LeaveFirst[5] = {0, 0, 4, 2, 1};
  22.  
  23. /* some variables used by the decompressor */
  24. static int ReadError;
  25. static UBYTE CodeSize;
  26. static int EOFCode;
  27. static UBYTE ReadMask;
  28. static int CompDataPointer;
  29. static int CompDataCount;
  30. static UBYTE CompData[256];
  31.  
  32. /* tables used by the decompressor */
  33. static UWORD Prefix[4096];
  34. static UBYTE Suffix[4096];
  35. static UBYTE OutCode[1025];
  36.  
  37. BOOL DoImage(BPTR fh)
  38. {
  39.     register int index;
  40.     register int colours;
  41.     int Code;
  42.  
  43.     MyPrintf("...Image #%ld encountered.\n", ImageNumber++);
  44.  
  45.     if (FRead(fh, (char *)&idesc, 1, 9) != 9) {
  46.         PutStr("......Error reading image descriptor.\n");
  47.         return TRUE;
  48.     }
  49.  
  50.     FlipWord(&idesc.id_Left);
  51.     FlipWord(&idesc.id_Top);
  52.     FlipWord(&idesc.id_Width);
  53.     FlipWord(&idesc.id_Height);
  54.  
  55.     interleave = idesc.id_Info & 1L << 6;
  56.     if (interleave)
  57.         interleave = 1;
  58.  
  59.     MyPrintf("......Xpos from %ld to %ld, Ypos from %ld to %ld, %sinterlaced.\n",
  60.         idesc.id_Left, idesc.id_Left + idesc.id_Width - 1,
  61.         idesc.id_Top, idesc.id_Top + idesc.id_Height - 1,
  62.         interleave ? "" : "not ");
  63.  
  64.     if (idesc.id_Info & 1L << 7) {
  65.         colours = 1L << ((idesc.id_Info & 7) + 1);
  66.         MyPrintf("......Local colour map contains %ld entries.\n", colours);
  67.  
  68.         for (index = 0; index < colours; index++) {
  69.             if (FRead(fh, &LocalColourTable[index], 1, 3) != 3) {
  70.                 MyPrintf("......Error reading local colour #%ld.\n",
  71.                     index);
  72.                 return TRUE;
  73.             }
  74.         }
  75.     } else {
  76.         colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
  77.         CopyMem((char *)GlobalColourTable, (char *)LocalColourTable,
  78.             sizeof(LocalColourTable));
  79.     }
  80.  
  81.     Xpos = Ypos = 0;
  82.  
  83.     /* now we are ready to read the image in so do it! */
  84.  
  85.     {
  86.         int MaxCode, ClearCode, CurCode,
  87.             OldCode, InCode, FreeCode;
  88.         int OutCount;
  89.         int FirstFree;
  90.         UBYTE InitCodeSize, FinChar, BitMask;
  91.  
  92.         MyPrintf("......Decompressing line number %5ld", Ypos);
  93.  
  94.         /* get the codesize and do general setup for decompression */
  95.         if ((CodeSize = FGetC(fh)) == -1) {
  96.             PutStr("\n......I/O Error during decompression.\n");
  97.             return TRUE;
  98.         }
  99.  
  100.         ClearCode = 1L << CodeSize;
  101.         EOFCode = ClearCode + 1;
  102.         FreeCode = FirstFree = ClearCode + 2;
  103.  
  104.         CodeSize++;    /* per GIF spec */
  105.         InitCodeSize = CodeSize;
  106.         MaxCode = 1L << CodeSize;
  107.         ReadError = ReadMask = OutCount = 0;
  108.         CompDataPointer = CompDataCount = 0;
  109.  
  110.         BitMask = colours - 1;
  111.  
  112.         Code = ReadCode(fh);
  113.         while (Code != EOFCode) {
  114.             if (ReadError)
  115.                 return TRUE;
  116.  
  117.             if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
  118.                 MyPrintf("\n%s", AbortMsg);
  119.                 MyExit(ABORTEXITVAL);
  120.             }
  121.  
  122.             if (Code == ClearCode) {
  123.                 CodeSize = InitCodeSize;
  124.                 MaxCode = 1L << CodeSize;
  125.                 FreeCode = FirstFree;
  126.                 FinChar = CurCode = OldCode = Code = ReadCode(fh);
  127.                 AddPixel(FinChar);
  128.             } else {
  129.                 CurCode = InCode = Code;
  130.  
  131.                 if (CurCode >= FreeCode) {
  132.                     CurCode = OldCode;
  133.                     OutCode[OutCount++] = FinChar;
  134.                 }
  135.  
  136.                 while (CurCode > BitMask) {
  137.                     if (OutCount > 1024) {
  138.                         PutStr("\n......Corrupt GIF file (OutCount)\n");
  139.                         return TRUE;
  140.                     }
  141.  
  142.                     OutCode[OutCount++] = Suffix[CurCode];
  143.                     CurCode = Prefix[CurCode];
  144.                 }
  145.  
  146.                 FinChar = CurCode;
  147.                 AddPixel(FinChar);
  148.  
  149.                 for (index = OutCount - 1; index >= 0; index--)
  150.                     AddPixel(OutCode[index]);
  151.                 OutCount = 0;
  152.  
  153.                 Prefix[FreeCode] = OldCode;
  154.                 Suffix[FreeCode] = FinChar;
  155.                 OldCode = InCode;
  156.  
  157.                 if (++FreeCode >= MaxCode) {
  158.                     if (CodeSize < 12) {
  159.                         CodeSize++;
  160.                         MaxCode <<= 1;
  161.                     }
  162.                 }
  163.             }
  164.  
  165.             Code = ReadCode(fh);
  166.         }
  167.     }
  168.  
  169.     if ((Code = FGetC(fh)) == -1)
  170.         return TRUE;
  171.  
  172.     /* done decompressing.  Erase decompressing message and exit */
  173.     PutStr("\x9B" "22D\x9BKed.\n");
  174.  
  175.     if (Code != 0) {
  176.         PutStr("......Warning:  Unaligned packet.\n");
  177.         UnGetC(fh, Code);
  178.     }
  179.  
  180.     return FALSE;
  181. }
  182.  
  183. static UBYTE ByteBuf;
  184.  
  185. int ReadCode(BPTR fh)
  186. {
  187.     register int temp;
  188.     register int DstMasked;
  189.     register int DstMask;
  190.     register LONG size;
  191.  
  192.     temp = 0;
  193.     DstMasked = 1L << CodeSize;
  194.     for (DstMask = 1; DstMask != DstMasked; DstMask <<= 1) {
  195.         if (!ReadMask) {
  196.             if (CompDataPointer == CompDataCount) {
  197.                 if ((size = FGetC(fh)) == -1) {
  198.                     PutStr("\n......I/O Error during decompression.\n");
  199.                     ReadError = 1;
  200.                     return EOFCode;
  201.                 }
  202.  
  203.                 if (FRead(fh, (char *)CompData, 1, size) != size) {
  204.                     PutStr("\n......I/O Error during decompression.\n");
  205.                     ReadError = 1;
  206.                     return EOFCode;
  207.                 }
  208.  
  209.                 CompDataCount = size;
  210.                 CompDataPointer = 0;
  211.             }
  212.  
  213.             ReadMask = 1;
  214.             ByteBuf = CompData[CompDataPointer++];
  215.         }
  216.  
  217.         if (ByteBuf & ReadMask)
  218.             temp |= DstMask;
  219.  
  220.         ReadMask <<= 1;
  221.     }
  222.  
  223.     return temp;
  224. }
  225.  
  226. void AddPixel(UBYTE index)
  227. {
  228.     register UWORD XStore;
  229.     register UWORD YStore;
  230.  
  231.     XStore = Xpos + idesc.id_Left;
  232.     YStore = Ypos + idesc.id_Top;
  233.  
  234.     BitPlane[YStore][XStore] = LocalColourTable[index];
  235.  
  236.     if (++Xpos == idesc.id_Width) {
  237.         Xpos = 0;
  238.         Ypos += LeaveStep[interleave];
  239.         if (Ypos >= idesc.id_Height)
  240.             Ypos = LeaveFirst[++interleave];
  241.  
  242.         MyPrintf("\x9B" "5D%5ld", Ypos + idesc.id_Top);
  243.     }
  244. }
  245.