home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Amiga / Jeux / demos / crystalPPC.lha / gifload.c < prev    next >
C/C++ Source or Header  |  1998-02-05  |  13KB  |  460 lines

  1. /*
  2.  * gifload.c: based strongly on gifload.c from wt which
  3.  * in turn was based on gif2ras.c.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdarg.h>
  10.  
  11. #if 0
  12. #include "wt.h"
  13. #include "error.h"
  14. #include "wtmem.h"
  15. #include "color.h"
  16. #endif
  17.  
  18. typedef int BOOL;
  19. typedef unsigned char byte;
  20.  
  21. #include "gifload.h"
  22.  
  23. //vonmir
  24. extern long myfread(char *fname,char *ptr,long filesize);
  25. //eingefⁿgt
  26.  
  27. #define NEXTBYTE      (*ptr++)
  28. #define IMAGESEP      0x2c
  29. #define GRAPHIC_EXT   0xf9
  30. #define PLAINTEXT_EXT 0x01
  31. #define APPLICATION_EXT 0xff
  32. #define COMMENT_EXT   0xfe
  33. #define START_EXTENSION 0x21
  34. #define INTERLACEMASK 0x40
  35. #define COLORMAPMASK  0x80
  36.  
  37. int BitOffset = 0,              /* Bit Offset of next code */
  38.     XC = 0, YC = 0,             /* Output X and Y coords of current pixel */
  39.     Pass = 0,                   /* Used by output routine if interlaced pic */
  40.     OutCount = 0,               /* Decompressor output 'stack count' */
  41.     RWidth, RHeight,            /* screen dimensions */
  42.     Width, Height,              /* image dimensions */
  43.     LeftOfs, TopOfs,            /* image offset */
  44.     BitsPerPixel,               /* Bits per pixel, read from GIF header */
  45.     BytesPerScanline,           /* bytes per scanline in output raster */
  46.     ColorMapSize,               /* number of colors */
  47.     Background,                 /* background color */
  48.     CodeSize,                   /* Code size, read from GIF header */
  49.     InitCodeSize,               /* Starting code size, used during Clear */
  50.     Code,                       /* Value returned by ReadCode */
  51.     MaxCode,                    /* limiting value for current code size */
  52.     ClearCode,                  /* GIF clear code */
  53.     EOFCode,                    /* GIF end-of-information code */
  54.     CurCode, OldCode, InCode,   /* Decompressor variables */
  55.     FirstFree,                  /* First free code, generated per GIF spec */
  56.     FreeCode,                   /* Decompressor, next free slot in hash table*/
  57.     FinChar,                    /* Decompressor variable */
  58.     BitMask,                    /* AND mask for data size */
  59.     ReadMask;                   /* Code AND mask for current code size */
  60.  
  61. #define True     1
  62. #define False    0
  63.  
  64. BOOL Interlace, HasColormap;
  65. BOOL Verbose = True;
  66.  
  67. byte *Image;                    /* The result array */
  68. byte *RawGIF;                   /* The heap array to hold it, raw */
  69. byte *Raster;                   /* The raster data stream, unblocked */
  70.  
  71.     /* The hash table used by the decompressor */
  72. int Prefix[4096];
  73. int Suffix[4096];
  74.  
  75.     /* An output array used by the decompressor */
  76. int OutCode[1025];
  77.  
  78.     /* The color map, read from the GIF header */
  79. byte Red[256], Green[256], Blue[256], used[256];
  80. int  numused;
  81.  
  82. char *id87 = "GIF87a";
  83. char *id89 = "GIF89a";
  84.  
  85. int   ReadCode( void );
  86. int   log2( int );
  87. void  AddToPixel( byte );
  88.  
  89. void fatal_error(char *message)
  90. {
  91.      fprintf(stderr, message);
  92.      putc('\n', stderr);
  93.  
  94. //vonmir
  95. //     exit(EXIT_FAILURE);
  96.      exit(0);
  97. //
  98. }
  99.  
  100. Graphic_file *new_graphic_file()
  101. {
  102.      Graphic_file *gf = (Graphic_file*)malloc(sizeof(Graphic_file));
  103.  
  104.      gf->transparent_entry = -1;
  105.  
  106.      return gf;
  107. }
  108.  
  109.  
  110. Graphic_file *
  111. LoadGIF(FILE *fp, char *fname )
  112. {
  113.   Graphic_file      *gfile;
  114.   int                filesize, numcols;
  115.   register unsigned  char ch, ch1;
  116.   register byte     *ptr, *ptr1;
  117.   register int   i;
  118.   short transparency = -1;
  119.  
  120.   BitOffset = 0;
  121.   XC = YC = 0;
  122.   Pass = 0;
  123.   OutCount = 0;
  124.  
  125.   /* find the size of the file */
  126.   fseek(fp, 0L, SEEK_END);
  127.   filesize = ftell(fp);
  128.   fseek(fp, 0L, SEEK_SET);
  129.  
  130.   if (!(ptr = RawGIF = (byte *) malloc(filesize)))
  131.     fatal_error("not enough memory to read gif file");
  132.  
  133.   if (!(Raster = (byte *) malloc(filesize))) {
  134.     free( ptr );
  135.     fatal_error("not enough memory to read gif file");
  136.   }
  137.  
  138. //vonmir
  139. //  if (fread(ptr, filesize, 1, fp) != 1)
  140. //    fatal_error("GIF data read failed");
  141.    if(myfread(fname,ptr,filesize)!=0) fatal_error("GIF data read failed");
  142. //
  143.   if (strncmp((char *) ptr, id87, 6))
  144.        if (strncmp((char *) ptr, id89, 6))
  145.                fatal_error("not a GIF file");
  146.  
  147.   ptr += 6;
  148.  
  149. /* Get variables from the GIF screen descriptor */
  150.  
  151.   ch           = NEXTBYTE;
  152.   RWidth       = ch + 0x100 * NEXTBYTE; /* screen dimensions... not used. */
  153.   ch           = NEXTBYTE;
  154.   RHeight      = ch + 0x100 * NEXTBYTE;
  155.  
  156.   ch           = NEXTBYTE;
  157.   HasColormap  = ((ch & COLORMAPMASK) ? True : False);
  158.  
  159.   BitsPerPixel = (ch & 7) + 1;
  160.   numcols      = ColorMapSize = 1 << BitsPerPixel;
  161.   BitMask      = ColorMapSize - 1;
  162.  
  163.   Background   = NEXTBYTE;              /* background color... not used. */
  164.   
  165.   if (NEXTBYTE)         /* supposed to be NULL */
  166.     fatal_error("corrupt GIF file (bad screen descriptor)");
  167.  
  168. /* Read in global colormap. */
  169.  
  170.   if (HasColormap) {
  171.     if (Verbose)
  172.       fprintf(stderr, "%s is %dx%d, %d bits/pixel, (%d colors).\n",
  173.               fname, RWidth,RHeight,BitsPerPixel, ColorMapSize);
  174.  
  175.     for (i = 0; i < ColorMapSize; i++) {
  176.       Red[i]   = NEXTBYTE;
  177.       Green[i] = NEXTBYTE;
  178.       Blue[i]  = NEXTBYTE;
  179.       used[i]  = 0;
  180.     }
  181.  
  182.     numused = 0;
  183.   } /* else no colormap in GIF file */
  184.  
  185.   /* look for image separator */
  186.  
  187.   for (ch = NEXTBYTE ; ch != IMAGESEP ; ch = NEXTBYTE) {
  188.           i = ch;
  189.       fprintf(stderr, "EXTENSION CHARACTER: %x\n", i);
  190.           if (ch != START_EXTENSION)
  191.                   fatal_error("corrupt GIF89a file");
  192.  
  193.           /* handle image extensions */
  194.           switch (ch = NEXTBYTE) {
  195.                 case GRAPHIC_EXT:
  196.                   ch = NEXTBYTE;
  197.                   if (ptr[0] & 0x1) {
  198.                           transparency = ptr[3];   /* transparent color index */
  199.                           fprintf(stderr, "transparency index: %i\n", transparency);
  200.                   }
  201.                   ptr += ch;
  202.                   break;
  203.                 case PLAINTEXT_EXT:
  204.                   break;
  205.                 case APPLICATION_EXT:
  206.                   break;
  207.                 case COMMENT_EXT:
  208.                   break;
  209.                 default:
  210.                   fatal_error("invalid GIF89 extension");
  211.           }
  212.  
  213.           while ((ch = NEXTBYTE))
  214.                   ptr += ch;
  215.   }
  216.  
  217. /* Now read in values from the image descriptor */
  218.  
  219.   ch        = NEXTBYTE;
  220.   LeftOfs   = ch + 0x100 * NEXTBYTE;
  221.   ch        = NEXTBYTE;
  222.   TopOfs    = ch + 0x100 * NEXTBYTE;
  223.   ch        = NEXTBYTE;
  224.   Width     = ch + 0x100 * NEXTBYTE;
  225.   ch        = NEXTBYTE;
  226.   Height    = ch + 0x100 * NEXTBYTE;
  227.   Interlace = ((NEXTBYTE & INTERLACEMASK) ? True : False);
  228.  
  229.   gfile = new_graphic_file();
  230.   gfile->palette = (RGBcolor*)malloc(sizeof(RGBcolor) * ColorMapSize);
  231.   for (i = 0; i < ColorMapSize; i++) {
  232.        gfile->palette[i].red = Red[i];
  233.        gfile->palette[i].green = Green[i];
  234.        gfile->palette[i].blue = Blue[i];
  235.   }
  236.   gfile->bitmap = (unsigned char*)malloc(Width * Height);
  237.   gfile->type = gfPaletted;
  238.   gfile->width = Width;
  239.   gfile->height = Height;
  240.   gfile->transparent_entry = transparency;
  241.   gfile->palette_entries = ColorMapSize;
  242.  
  243. /* Note that I ignore the possible existence of a local color map.
  244.  * I'm told there aren't many files around that use them, and the spec
  245.  * says it's defined for future use.  This could lead to an error
  246.  * reading some files. 
  247.  */
  248.  
  249. /* Start reading the raster data. First we get the intial code size
  250.  * and compute decompressor constant values, based on this code size.
  251.  */
  252.  
  253.     CodeSize  = NEXTBYTE;
  254.     ClearCode = (1 << CodeSize);
  255.     EOFCode   = ClearCode + 1;
  256.     FreeCode  = FirstFree = ClearCode + 2;
  257.  
  258. /* The GIF spec has it that the code size is the code size used to
  259.  * compute the above values is the code size given in the file, but the
  260.  * code size used in compression/decompression is the code size given in
  261.  * the file plus one. (thus the ++).
  262.  */
  263.  
  264.     CodeSize++;
  265.     InitCodeSize = CodeSize;
  266.     MaxCode      = (1 << CodeSize);
  267.     ReadMask     = MaxCode - 1;
  268.  
  269. /* Read the raster data.  Here we just transpose it from the GIF array
  270.  * to the Raster array, turning it from a series of blocks into one long
  271.  * data stream, which makes life much easier for ReadCode().
  272.  */
  273.  
  274.     ptr1 = Raster;
  275.     do {
  276.         ch = ch1 = NEXTBYTE;
  277.         while (ch--) *ptr1++ = NEXTBYTE;
  278.         if ((ptr1 - Raster) > filesize)
  279.             fatal_error("corrupt GIF file (unblock)");
  280.     } while(ch1);
  281.  
  282.     free(RawGIF);               /* We're done with the raw data now... */
  283.  
  284.     Image               = gfile->bitmap;
  285.     BytesPerScanline    = Width;
  286.  
  287.  
  288. /* Decompress the file, continuing until you see the GIF EOF code.
  289.  * One obvious enhancement is to add checking for corrupt files here.
  290.  */
  291.  
  292.     Code = ReadCode();
  293.     while (Code != EOFCode) {
  294.  
  295. /* Clear code sets everything back to its initial value, then reads the
  296.  * immediately subsequent code as uncompressed data.
  297.  */
  298.  
  299.         if (Code == ClearCode) {
  300.             CodeSize = InitCodeSize;
  301.             MaxCode  = (1 << CodeSize);
  302.             ReadMask = MaxCode - 1;
  303.             FreeCode = FirstFree;
  304.             CurCode  = OldCode = Code = ReadCode();
  305.             FinChar  = CurCode & BitMask;
  306.             AddToPixel(FinChar);
  307.         }
  308.         else {
  309.  
  310. /* If not a clear code, then must be data: save same as CurCode and InCode */
  311.  
  312.             CurCode = InCode = Code;
  313.  
  314. /* If greater or equal to FreeCode, not in the hash table yet;
  315.  * repeat the last character decoded
  316.  */
  317.  
  318.             if (CurCode >= FreeCode) {
  319.                 CurCode = OldCode;
  320.                 OutCode[OutCount++] = FinChar;
  321.             }
  322.  
  323. /* Unless this code is raw data, pursue the chain pointed to by CurCode
  324.  * through the hash table to its end; each code in the chain puts its
  325.  * associated output code on the output queue.
  326.  */
  327.  
  328.             while (CurCode > BitMask) {
  329.                 if (OutCount > 1024) {
  330.                     fprintf(stderr,"\nCorrupt GIF file (OutCount)!\n");
  331.                     //_exit(-1);  /* calling 'exit(-1)' dumps core, so I don't */
  332.                     }
  333.                 OutCode[OutCount++] = Suffix[CurCode];
  334.                 CurCode = Prefix[CurCode];
  335.             }
  336.  
  337. /* The last code in the chain is treated as raw data. */
  338.  
  339.             FinChar             = CurCode & BitMask;
  340.             OutCode[OutCount++] = FinChar;
  341.  
  342. /* Now we put the data out to the Output routine.
  343.  * It's been stacked LIFO, so deal with it that way...
  344.  */
  345.  
  346.             for (i = OutCount - 1; i >= 0; i--)
  347.                 AddToPixel(OutCode[i]);
  348.             OutCount = 0;
  349.  
  350. /* Build the hash table on-the-fly. No table is stored in the file. */
  351.  
  352.             Prefix[FreeCode] = OldCode;
  353.             Suffix[FreeCode] = FinChar;
  354.             OldCode          = InCode;
  355.  
  356. /* Point to the next slot in the table.  If we exceed the current
  357.  * MaxCode value, increment the code size unless it's already 12.  If it
  358.  * is, do nothing: the next code decompressed better be CLEAR
  359.  */
  360.  
  361.             FreeCode++;
  362.             if (FreeCode >= MaxCode) {
  363.                 if (CodeSize < 12) {
  364.                     CodeSize++;
  365.                     MaxCode *= 2;
  366.                     ReadMask = (1 << CodeSize) - 1;
  367.                 }
  368.             }
  369.         }
  370.         Code = ReadCode();
  371.     }
  372.  
  373.     free(Raster);
  374.  
  375.     if (!Verbose)
  376.         fprintf(stderr,"(of which %d are used)\n",numused);
  377.  
  378.  
  379.   return gfile;
  380. }
  381.  
  382.  
  383. /* Fetch the next code from the raster data stream.  The codes can be
  384.  * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
  385.  * maintain our location in the Raster array as a BIT Offset.  We compute
  386.  * the byte Offset into the raster array by dividing this by 8, pick up
  387.  * three bytes, compute the bit Offset into our 24-bit chunk, shift to
  388.  * bring the desired code to the bottom, then mask it off and return it. 
  389.  */
  390. int
  391. ReadCode( void )
  392. {
  393.     int RawCode, ByteOffset;
  394.  
  395.     ByteOffset = BitOffset / 8;
  396.     RawCode    = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
  397.  
  398.     if (CodeSize >= 8)
  399.         RawCode += (0x10000 * Raster[ByteOffset + 2]);
  400.  
  401.     RawCode  >>= (BitOffset % 8);
  402.     BitOffset += CodeSize;
  403.  
  404.     return(RawCode & ReadMask);
  405. }
  406.  
  407. void
  408. AddToPixel(byte Index)
  409. {
  410.     if (YC<Height)
  411.         *(Image + YC * BytesPerScanline + XC) = Index;
  412.  
  413.     if (!used[Index]) { used[Index]=1;  numused++; }
  414.  
  415. /* Update the X-coordinate, and if it overflows, update the Y-coordinate */
  416.  
  417.     if (++XC == Width) {
  418.  
  419. /* If a non-interlaced picture, just increment YC to the next scan line. 
  420.  * If it's interlaced, deal with the interlace as described in the GIF
  421.  * spec.  Put the decoded scan line out to the screen if we haven't gone
  422.  * past the bottom of it
  423.  */
  424.  
  425.         XC = 0;
  426.         if (!Interlace) YC++;
  427.         else {
  428.             switch (Pass) {
  429.                 case 0:
  430.                     YC += 8;
  431.                     if (YC >= Height) {
  432.                         Pass++;
  433.                         YC = 4;
  434.                     }
  435.                 break;
  436.                 case 1:
  437.                     YC += 8;
  438.                     if (YC >= Height) {
  439.                         Pass++;
  440.                         YC = 2;
  441.                     }
  442.                 break;
  443.                 case 2:
  444.                     YC += 4;
  445.                     if (YC >= Height) {
  446.                         Pass++;
  447.                         YC = 1;
  448.                     }
  449.                 break;
  450.                 case 3:
  451.                     YC += 2;
  452.                 break;
  453.                 default:
  454.                 break;
  455.             }
  456.         }
  457.     }
  458. }
  459.  
  460.