home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / GRAPHICS / MISC / PVQUAN15.ZIP / GIFLIB.ZIP / DGIF_LIB.C next >
Encoding:
C/C++ Source or Header  |  1991-11-21  |  17.1 KB  |  468 lines

  1. /******************************************************************************
  2. *   "Gif-Lib" - Yet another gif library.                      *
  3. *                                          *
  4. * Written by:  Gershon Elber            IBM PC Ver 1.1,    Aug. 1990     *
  5. *******************************************************************************
  6. * The kernel of the GIF Decoding process can be found here.              *
  7. *******************************************************************************
  8. * History:                                      *
  9. * 16 Jun 89 - Version 1.0 by Gershon Elber.                      *
  10. *  3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
  11. ******************************************************************************/
  12.  
  13.  
  14. #include <io.h>
  15. #include <alloc.h>
  16. #include <stdlib.h>
  17. #include <sys\stat.h>
  18.  
  19. #include <fcntl.h>
  20. #include <string.h>
  21.  
  22. #include "gif_lib.h"
  23. #include "gif_hash.h"
  24.  
  25. #define LZ_MAX_CODE    4095        /* Biggest code possible in 12 bits. */
  26. #define LZ_BITS        12
  27.  
  28. #define GIF_STAMP_LEN    sizeof(GIF_STAMP) - 1
  29. #define GIF_STAMP    "GIFVER"     /* First chars in file - GIF stamp. */
  30. #define GIF_VERSION_POS    3        /* Version first character in stamp. */
  31.  
  32. #define NO_SUCH_CODE        4098    /* Impossible code, to signal empty. */
  33.  
  34. #define RED        0
  35. #define GREEN    1
  36. #define BLUE    2
  37.  
  38. static int
  39.     priv_BitsPerPixel,        /* Bits per pixel (Codes uses at list this + 1). */
  40.     priv_ClearCode,                       /* The CLEAR LZ code. */
  41.     priv_EOFCode,                         /* The EOF LZ code. */
  42.     priv_RunningCode,            /* The next code algorithm can generate. */
  43.     priv_RunningBits,/* The number of bits required to represent RunningCode. */
  44.     priv_MaxCode1,  /* 1 bigger than max. possible code, in RunningBits bits. */
  45.     priv_LastCode,                /* The code before the current code. */
  46.     priv_StackPtr,                 /* For character stack (see below). */
  47.     priv_CrntShiftState;                /* Number of bits in CrntShiftDWord. */
  48. static     unsigned long priv_CrntShiftDWord,     /* For bytes decomposition into codes. */
  49.           priv_PixelCount;               /* Number of pixels in image. */
  50. static     FILE *priv_File;                          /* File as stream. */
  51. static     GifByteType priv_Buf[256];           /* Compressed input is buffered here. */
  52. static     GifByteType priv_Stack[LZ_MAX_CODE];     /* Decoded pixels are stacked here. */
  53. static     GifByteType priv_Suffix[LZ_MAX_CODE+1];           /* So we can trace the codes. */
  54. static     unsigned int priv_Prefix[LZ_MAX_CODE+1];
  55.  
  56. static int DGifDecompressLine(GifPixelType *Line, int LineLen);
  57. static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
  58. static int DGifDecompressInput(int *Code);
  59. static int DGifBufferedInput(FILE *File, GifByteType *Buf, unsigned char *NextByte);
  60. static int DGifGetCodeNext(GifByteType **CodeBlock);
  61.  
  62. /******************************************************************************
  63. *   Open a new gif file for read, given by its name.                  *
  64. *   Returns GifFileType pointer dynamically allocated which serves as the gif *
  65. * info record. _GifError is cleared if succesfull.                  *
  66. ******************************************************************************/
  67. FILE *DGifOpenFile(char *name)
  68. {
  69.     char Buf[GIF_STAMP_LEN+1];
  70.  
  71.     if ((priv_File = fopen(name, "rb")) == NULL) return NULL;
  72.  
  73.     /* Lets see if this is GIF file: */
  74.     if (fread(Buf, 1, GIF_STAMP_LEN, priv_File) != GIF_STAMP_LEN) {
  75.         return NULL;
  76.     }
  77.  
  78.     /* The GIF Version number is ignored at this time. Maybe we should do    */
  79.     /* something more useful with it.                         */
  80.     Buf[GIF_STAMP_LEN] = 0;
  81.     if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) return NULL;
  82.     return priv_File;
  83. }
  84.  
  85. /******************************************************************************
  86. *   This routine should be called before any other DGif calls. Note that      *
  87. * this routine is called automatically from DGif file open routines.          *
  88. ******************************************************************************/
  89. void DGifGetScreenDesc(int *Width, int *Height, int *ColorRes, int *BackGround,
  90.     int *BitsPerPixel, char *palette)
  91. {
  92.     int i, Size;
  93.     char Buf;
  94.  
  95.     /* Put the screen descriptor into the file: */
  96.     *Width = getw(priv_File);
  97.     *Height = getw(priv_File);
  98.  
  99.     Buf = fgetc(priv_File);
  100.     *ColorRes = (((Buf & 0x70) + 1) >> 4) + 1;
  101.     *BitsPerPixel = (Buf & 0x07) + 1;
  102.     *BackGround = fgetc(priv_File);
  103.     fgetc(priv_File);
  104.     if (Buf & 0x80) {             /* Do we have global color map? */
  105.         Size = (1 << *BitsPerPixel) * 3;
  106.         /* Get the global color map: */
  107.         for (i = 0; i < Size; i += 3) {
  108.             Buf = getc(priv_File);
  109.             palette[i+RED]   = Buf /*getc(priv_File)*/ >> (8 - *ColorRes);
  110.             palette[i+GREEN] = getc(priv_File) >> (8 - *ColorRes);
  111.             palette[i+BLUE]  = getc(priv_File) >> (8 - *ColorRes);
  112.         }
  113.     }
  114. }
  115.  
  116. /******************************************************************************
  117. *   This routine should be called before any attemp to read an image.         *
  118. ******************************************************************************/
  119. int DGifGetRecordType(GifRecordType *Type)
  120. {
  121.     GifByteType Buf;
  122.  
  123.     if (fread(&Buf, 1, 1, priv_File) != 1) {
  124.     return GIF_ERROR;
  125.     }
  126.  
  127.     switch (Buf) {
  128.     case ',':
  129.         *Type = IMAGE_DESC_RECORD_TYPE;
  130.         break;
  131.     case '!':
  132.         *Type = EXTENSION_RECORD_TYPE;
  133.         break;
  134.     case ';':
  135.         *Type = TERMINATE_RECORD_TYPE;
  136.         break;
  137.     default:
  138.         *Type = UNDEFINED_RECORD_TYPE;
  139.         return GIF_ERROR;
  140.     }
  141.  
  142.     return GIF_OK;
  143. }
  144.  
  145. /******************************************************************************
  146. *   This routine should be called before any attemp to read an image.         *
  147. *   Note it is assumed the Image desc. header (',') has been read.          *
  148. ******************************************************************************/
  149. void     DGifGetImageDesc(unsigned int *Left, unsigned int *Top, unsigned int *Width, unsigned int *Height, char *palette)
  150. {
  151.     int Size, i;
  152.     int ColorRes, BitsPerPixel;
  153.     char Buf;
  154.  
  155.     *Left   = getw(priv_File);
  156.     *Top    = getw(priv_File);
  157.     *Width  = getw(priv_File);
  158.     *Height = getw(priv_File);
  159.     Buf = fgetc(priv_File);
  160.     ColorRes = (((Buf & 0x70) + 1) >> 4) + 1;
  161.     BitsPerPixel = (Buf & 0x07) + 1;
  162.     if (Buf & 0x80) {        /* Does this image have local color map? */
  163.         Size = (1 << BitsPerPixel) * 3;
  164.         /* Get the image local color map: */
  165.         for (i = 0; i < Size; i += 3) {
  166.             palette[i+RED]   = getc(priv_File) >> (8 - ColorRes);
  167.             palette[i+GREEN] = getc(priv_File) >> (8 - ColorRes);
  168.             palette[i+BLUE]  = getc(priv_File) >> (8 - ColorRes);
  169.         }
  170.     }
  171.  
  172.     DGifSetupDecompress((long) *Width * (long) *Height);  /* Reset decompress algorithm parameters. */
  173. }
  174.  
  175. /******************************************************************************
  176. *  Get one full scanned line (Line) of length LineLen from GIF file.          *
  177. ******************************************************************************/
  178. int DGifGetLine(GifPixelType *Line, int LineLen)
  179. {
  180.     GifByteType *Dummy;
  181.  
  182.     if ((priv_PixelCount -= LineLen) < 0)     return GIF_ERROR;
  183.  
  184.     if (DGifDecompressLine(Line, LineLen) != GIF_OK) return GIF_ERROR;
  185.     if (priv_PixelCount == 0) {
  186.         /* We probably would not be called any more, so lets clean          */
  187.         /* everything before we return: need to flush out all rest of    */
  188.         /* image until empty block (size 0) detected. We use GetCodeNext.*/
  189.         do if (DGifGetCodeNext(&Dummy) == GIF_ERROR) return GIF_ERROR;
  190.         while (Dummy != NULL);
  191.     }
  192.     return GIF_OK;
  193. }
  194.  
  195. /******************************************************************************
  196. *   This routine should be called last, to close GIF file.              *
  197. ******************************************************************************/
  198. void DGifCloseFile(void)
  199. {
  200.      fclose(priv_File);
  201. }
  202.  
  203. /******************************************************************************
  204. *   Continue to get the image code in compressed form. This routine should be *
  205. * called until NULL block is returned.                          *
  206. *   The block should NOT be freed by the user (not dynamically allocated).    *
  207. ******************************************************************************/
  208. static int DGifGetCodeNext(GifByteType **CodeBlock)
  209. {
  210.     GifByteType Buf;
  211.  
  212.      if (fread(&Buf, 1, 1, priv_File) != 1)     return GIF_ERROR;
  213.  
  214.     if (Buf > 0) {
  215.     *CodeBlock = priv_Buf;           /* Use private unused buffer. */
  216.     (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
  217.     if (fread(&((*CodeBlock)[1]), 1, Buf, priv_File) != Buf)     return GIF_ERROR;
  218.     }
  219.     else {
  220.     *CodeBlock = NULL;
  221.     priv_Buf[0] = 0;           /* Make sure the buffer is empty! */
  222.     priv_PixelCount = 0;   /* And local info. indicate image read. */
  223.     }
  224.  
  225.     return GIF_OK;
  226. }
  227.  
  228. /******************************************************************************
  229. *   Setup the LZ decompression for this image:                      *
  230. ******************************************************************************/
  231. void DGifSetupDecompress(long size)
  232. {
  233.     int i, BitsPerPixel;
  234.     GifByteType CodeSize;
  235.     unsigned int *Prefix;
  236.  
  237.     priv_PixelCount = size;
  238.  
  239.     fread(&CodeSize, 1, 1, priv_File);    /* Read Code size from file. */
  240.     BitsPerPixel = CodeSize;
  241.  
  242.     priv_Buf[0] = 0;                  /* Input Buffer empty. */
  243.     priv_BitsPerPixel = BitsPerPixel;
  244.     priv_ClearCode = (1 << BitsPerPixel);
  245.     priv_EOFCode = priv_ClearCode + 1;
  246.     priv_RunningCode = priv_EOFCode + 1;
  247.     priv_RunningBits = BitsPerPixel + 1;     /* Number of bits per code. */
  248.     priv_MaxCode1 = 1 << priv_RunningBits;     /* Max. code + 1. */
  249.     priv_StackPtr = 0;            /* No pixels on the pixel stack. */
  250.     priv_LastCode = NO_SUCH_CODE;
  251.     priv_CrntShiftState = 0;    /* No information in CrntShiftDWord. */
  252.     priv_CrntShiftDWord = 0;
  253.  
  254.     Prefix = priv_Prefix;
  255.     for (i = 0; i < LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
  256. }
  257.  
  258. /******************************************************************************
  259. *   The LZ decompression routine:                          *
  260. *   This version decompress the given gif file into Line of length LineLen.   *
  261. *   This routine can be called few times (one per scan line, for example), in *
  262. * order the complete the whole image.                          *
  263. ******************************************************************************/
  264. static int DGifDecompressLine(GifPixelType *Line, int LineLen)
  265. {
  266.     int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
  267.     GifByteType *Stack, *Suffix;
  268.     unsigned int *Prefix;
  269.  
  270.     StackPtr = priv_StackPtr;
  271.     Prefix = priv_Prefix;
  272.     Suffix = priv_Suffix;
  273.     Stack = priv_Stack;
  274.     EOFCode = priv_EOFCode;
  275.     ClearCode = priv_ClearCode;
  276.     LastCode = priv_LastCode;
  277.  
  278.     if (StackPtr != 0) {
  279.     /* Let pop the stack off before continueing to read the gif file: */
  280.     while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
  281.     }
  282.  
  283.     while (i < LineLen) {                /* Decode LineLen items. */
  284.     if (DGifDecompressInput(&CrntCode) == GIF_ERROR)
  285.             return GIF_ERROR;
  286.  
  287.     if (CrntCode == EOFCode) {
  288.         /* Note however that usually we will not be here as we will stop */
  289.         /* decoding as soon as we got all the pixel, or EOF code will    */
  290.         /* not be read at all, and DGifGetLine/Pixel clean everything.   */
  291.         if (i != LineLen - 1 || priv_PixelCount != 0) {
  292.         return GIF_ERROR;
  293.         }
  294.         i++;
  295.     }
  296.     else if (CrntCode == ClearCode) {
  297.         /* We need to start over again: */
  298.         for (j = 0; j < LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
  299.         priv_RunningCode = priv_EOFCode + 1;
  300.         priv_RunningBits = priv_BitsPerPixel + 1;
  301.         priv_MaxCode1 = 1 << priv_RunningBits;
  302.         LastCode = priv_LastCode = NO_SUCH_CODE;
  303.     }
  304.     else {
  305.         /* Its regular code - if in pixel range simply add it to output  */
  306.         /* stream, otherwise trace to codes linked list until the prefix */
  307.         /* is in pixel range:                         */
  308.         if (CrntCode < ClearCode) {
  309.         /* This is simple - its pixel scalar, so add it to output:   */
  310.         Line[i++] = CrntCode;
  311.         }
  312.         else {
  313.         /* Its a code to needed to be traced: trace the linked list  */
  314.         /* until the prefix is a pixel, while pushing the suffix     */
  315.         /* pixels on our stack. If we done, pop the stack in reverse */
  316.         /* (thats what stack is good for!) order to output.         */
  317.         if (Prefix[CrntCode] == NO_SUCH_CODE) {
  318.             /* Only allowed if CrntCode is exactly the running code: */
  319.             /* In that case CrntCode = XXXCode, CrntCode or the         */
  320.             /* prefix code is last code and the suffix char is         */
  321.             /* exactly the prefix of last code!                 */
  322.             if (CrntCode == priv_RunningCode - 2) {
  323.             CrntPrefix = LastCode;
  324.             Suffix[priv_RunningCode - 2] =
  325.             Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
  326.                             LastCode, ClearCode);
  327.             }
  328.             else {
  329.             return GIF_ERROR;
  330.             }
  331.         }
  332.         else
  333.             CrntPrefix = CrntCode;
  334.  
  335.         /* Now (if image is O.K.) we should not get and NO_SUCH_CODE */
  336.         /* During the trace. As we might loop forever, in case of    */
  337.         /* defective image, we count the number of loops we trace    */
  338.         /* and stop if we got LZ_MAX_CODE. obviously we can not      */
  339.         /* loop more than that.                         */
  340.         j = 0;
  341.         while (j++ <= LZ_MAX_CODE &&
  342.                CrntPrefix > ClearCode &&
  343.                CrntPrefix <= LZ_MAX_CODE) {
  344.             Stack[StackPtr++] =    Suffix[CrntPrefix];
  345.             CrntPrefix = Prefix[CrntPrefix];
  346.         }
  347.         if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
  348.             return GIF_ERROR;
  349.         }
  350.         /* Push the last character on stack: */
  351.         Stack[StackPtr++] = CrntPrefix;
  352.  
  353.         /* Now lets pop all the stack into output: */
  354.         while (StackPtr != 0 && i < LineLen)
  355.             Line[i++] = Stack[--StackPtr];
  356.         }
  357.         if (LastCode != NO_SUCH_CODE) {
  358.         Prefix[priv_RunningCode - 2] = LastCode;
  359.  
  360.         if (CrntCode == priv_RunningCode - 2) {
  361.             /* Only allowed if CrntCode is exactly the running code: */
  362.             /* In that case CrntCode = XXXCode, CrntCode or the         */
  363.             /* prefix code is last code and the suffix char is         */
  364.             /* exactly the prefix of last code!                 */
  365.             Suffix[priv_RunningCode - 2] =
  366.             DGifGetPrefixChar(Prefix, LastCode, ClearCode);
  367.         }
  368.         else {
  369.             Suffix[priv_RunningCode - 2] =
  370.             DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
  371.         }
  372.         }
  373.         LastCode = CrntCode;
  374.     }
  375.     }
  376.  
  377.     priv_LastCode = LastCode;
  378.     priv_StackPtr = StackPtr;
  379.  
  380.     return GIF_OK;
  381. }
  382.  
  383. /******************************************************************************
  384. * Routine to trace the Prefixes linked list until we get a prefix which is    *
  385. * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
  386. * If image is defective, we might loop here forever, so we limit the loops to *
  387. * the maximum possible if image O.k. - LZ_MAX_CODE times.              *
  388. ******************************************************************************/
  389. static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
  390. {
  391.     int i = 0;
  392.  
  393.     while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
  394.     return Code;
  395. }
  396.  
  397. /******************************************************************************
  398. *   The LZ decompression input routine:                          *
  399. *   This routine is responsable for the decompression of the bit stream from  *
  400. * 8 bits (bytes) packets, into the real codes.                      *
  401. *   Returns GIF_OK if read succesfully.                          *
  402. ******************************************************************************/
  403. static int DGifDecompressInput(int *Code)
  404. {
  405.     GifByteType NextByte;
  406.     static unsigned int CodeMasks[] = {
  407.     0x0000, 0x0001, 0x0003, 0x0007,
  408.     0x000f, 0x001f, 0x003f, 0x007f,
  409.     0x00ff, 0x01ff, 0x03ff, 0x07ff,
  410.     0x0fff
  411.     };
  412.  
  413.     while (priv_CrntShiftState < priv_RunningBits) {
  414.     /* Needs to get more bytes from input stream for next code: */
  415.     if (DGifBufferedInput(priv_File, priv_Buf, &NextByte)
  416.         == GIF_ERROR) {
  417.         return GIF_ERROR;
  418.     }
  419.     priv_CrntShiftDWord |=
  420.         ((unsigned long) NextByte) << priv_CrntShiftState;
  421.     priv_CrntShiftState += 8;
  422.     }
  423.      *Code = (int) priv_CrntShiftDWord & CodeMasks[priv_RunningBits];
  424.  
  425.     priv_CrntShiftDWord >>= priv_RunningBits;
  426.     priv_CrntShiftState -= priv_RunningBits;
  427.  
  428.     /* If code cannt fit into RunningBits bits, must raise its size. Note */
  429.     /* however that codes above 4095 are used for special signaling.      */
  430.     if (++priv_RunningCode > priv_MaxCode1 &&
  431.     priv_RunningBits < LZ_BITS) {
  432.     priv_MaxCode1 <<= 1;
  433.     priv_RunningBits++;
  434.     }
  435.     return GIF_OK;
  436. }
  437.  
  438. /******************************************************************************
  439. *   This routines read one gif data block at a time and buffers it internally *
  440. * so that the decompression routine could access it.                  *
  441. *   The routine returns the next byte from its internal buffer (or read next  *
  442. * block in if buffer empty) and returns GIF_OK if succesful.              *
  443. ******************************************************************************/
  444. static int DGifBufferedInput(FILE *File, GifByteType *Buf,
  445.                               GifByteType *NextByte)
  446. {
  447.     if (Buf[0] == 0) {
  448.     /* Needs to read the next buffer - this one is empty: */
  449.     if (fread(Buf, 1, 1, File) != 1)
  450.     {
  451.         return GIF_ERROR;
  452.     }
  453.     if (fread(&Buf[1], 1, Buf[0], File) != Buf[0])
  454.     {
  455.         return GIF_ERROR;
  456.     }
  457.     *NextByte = Buf[1];
  458.     Buf[1] = 2;       /* We use now the second place as last char read! */
  459.     Buf[0]--;
  460.     }
  461.     else {
  462.     *NextByte = Buf[Buf[1]++];
  463.     Buf[0]--;
  464.     }
  465.  
  466.     return GIF_OK;
  467. }
  468.