gifdecode.c

Go to the documentation of this file.
00001 /* @(#)root/win32gdk:$Id: gifdecode.c 20882 2007-11-19 11:31:26Z rdm $ */
00002 /* Author: Rene Brun   11/06/97*/
00003 #include <stdio.h>
00004 #include <string.h>
00005 
00006 
00007 #define BITS    12                      /* largest code size */
00008 #define TSIZE   4096                    /* tables size */
00009 
00010 typedef unsigned char byte;
00011 
00012 static int      Prefix[TSIZE];          /* prefix table */
00013 static byte     Suffix[TSIZE];          /* suffix table */
00014 static byte     OutCode[TSIZE];         /* output stack */
00015 
00016 static byte     *ptr1,                  /* pointer to GIF array */
00017                 *ptr2;                  /* pointer to PIX array */
00018 
00019 static int      CurCodeSize,            /* current number of bits per code */
00020                 CurMaxCode;             /* maximum code, given CurCodeSize */
00021 
00022 static long     CurBit;                 /* current bit in GIF image data */
00023 
00024 /***************************************************************
00025  *                                                             *
00026  ***************************************************************/
00027 static int ReadCode()
00028 {
00029   static long   b3[3], CurByte;
00030   static byte   lblk;
00031   int           shift, nbyte;
00032   long          OldByte;
00033 
00034   if (CurBit == -1) {
00035     lblk = 0;
00036     CurByte = -1;
00037   }
00038 
00039   CurBit += CurCodeSize;
00040   OldByte = CurByte;
00041   CurByte = CurBit/8;
00042   nbyte   = CurByte - OldByte;
00043   shift   = 17 + (CurBit%8) - CurCodeSize;
00044   while (nbyte-- > 0) {
00045     if (lblk == 0) {
00046       lblk = *ptr1++;
00047       if (lblk == 0) return -1;
00048     }
00049     b3[0] = b3[1];
00050     b3[1] = b3[2];
00051     b3[2] = *ptr1++;
00052     lblk--;
00053   }
00054   return (((b3[0]+0x100*b3[1]+0x10000*b3[2])>>shift) & (CurMaxCode-1));
00055 }
00056 
00057 /***************************************************************
00058  *                                                             *
00059  ***************************************************************/
00060 static void OutPixel(byte pix)
00061 {
00062   *ptr2++ = pix;
00063 }
00064 
00065 /***************************************************************
00066  *                                                             *
00067  * Name: GIFinfo                                Date: 03.10.94 *
00068  *                                                             *
00069  * Function: Get information on GIF image                      *
00070  *                                                             *
00071  * Input: GIFarr[] - compressed image in GIF format            *
00072  *                                                             *
00073  * Output: Width    - image width                              *
00074  *         Height   - image height                             *
00075  *         Ncols    - number of colors                         *
00076  *         return   - 0 - if O.K.                              *
00077  *                    1 - if error                             *
00078  *                                                             *
00079  ***************************************************************/
00080 int GIFinfo(byte *GIFarr, int *Width, int *Height, int *Ncols)
00081 {
00082   byte          b;
00083 
00084   ptr1 = GIFarr;
00085 
00086   /*   R E A D   H E A D E R   */
00087 
00088   if (strncmp((char *)GIFarr,"GIF87a",6) && strncmp((char *)GIFarr,"GIF89a",6))
00089   {
00090     fprintf(stderr,"\nGIFinfo: not a GIF\n");
00091     return 1;
00092   }
00093 
00094   ptr1 += 6;
00095 
00096   ptr1 += 2;                            /* screen width ... ignore */
00097   ptr1 += 2;                            /* screen height ... ignore */
00098 
00099   b         = *ptr1++;
00100   *Ncols    = 1 << ((b & 7) + 1);
00101   if ((b & 0x80) == 0) {                /* is there color map? */
00102     fprintf(stderr,"\nGIFinfo: warning! no color map\n");
00103     *Ncols = 0;
00104   }
00105 
00106   ++ptr1;                               /* background color ... ignore */
00107   b      = *ptr1++;                     /* supposed to be NULL */
00108   if (b) {
00109     fprintf(stderr,"\nGIFdecode: bad screen descriptor\n");
00110     return 1;
00111   }
00112 
00113   ptr1 += (*Ncols) * 3;                 /* skip color map */
00114 
00115   b      = *ptr1++;                     /* image separator */
00116   if (b != ',') {
00117     fprintf(stderr,"\nGIFinfo: no image separator\n");
00118     return 1;
00119   }
00120 
00121   ptr1   += 2;                          /* left offset ... ignore */
00122   ptr1   += 2;                          /* top offset ... ignore */
00123   b       = *ptr1++;                    /* image width */
00124   *Width  = b + 0x100*(*ptr1++);
00125   b       = *ptr1++;                    /* image height */
00126   *Height = b + 0x100*(*ptr1++);
00127   return 0;
00128 }
00129 
00130 /***************************************************************
00131  *                                                             *
00132  * Name: GIFdecode                              Date: 06.10.92 *
00133  *                                                             *
00134  * Function: Decode image from GIF array                       *
00135  *                                                             *
00136  * Input: GIFarr[] - compressed image in GIF format            *
00137  *                                                             *
00138  * Output: PIXarr[] - image (byte per pixel)                   *
00139  *         Width    - image width                              *
00140  *         Height   - image height                             *
00141  *         Ncols    - number of colors                         *
00142  *         R[]      - red components                           *
00143  *         G[]      - green components                         *
00144  *         B[]      - blue components                          *
00145  *         return   - 0 - if O.K.                              *
00146  *                    1 - if error                             *
00147  *                                                             *
00148  ***************************************************************/
00149 int GIFdecode(byte *GIFarr, byte *PIXarr, int *Width, int *Height, int *Ncols, byte *R, byte *G, byte *B)
00150 {
00151   byte          b,                      /* working variable */
00152                 FinChar;                /* final character */
00153 
00154   int           i,                      /* working variable for loops */
00155                 BitsPixel,              /* number of bits per pixel */
00156                 IniCodeSize,            /* initial number of bits per code */
00157                 ClearCode,              /* reset code */
00158                 EOFCode,                /* end of file code */
00159                 FreeCode,               /* first unused entry */
00160                 CurCode,                /* current code */
00161                 InCode,                 /* input code */
00162                 OldCode,                /* previous code */
00163                 PixMask,                /* mask for pixel */
00164                 OutCount;               /* output stack counter */
00165 
00166   long          Npix;                   /* number of pixels */
00167 
00168   ptr1    = GIFarr;
00169   ptr2    = PIXarr;
00170   OldCode = 0;
00171   FinChar = 0;
00172 
00173   /*   R E A D   H E A D E R   */
00174   if (strncmp((char *)GIFarr,"GIF87a",6) && strncmp((char *)GIFarr,"GIF89a",6))
00175   {
00176     fprintf(stderr,"\nGIFinfo: not a GIF\n");
00177     return 1;
00178   }
00179 
00180   ptr1 += 6;
00181 
00182   ptr1 += 2;                            /* screen width ... ignore */
00183   ptr1 += 2;                            /* screen height ... ignore */
00184 
00185   b         = *ptr1++;
00186   BitsPixel = (b & 7) + 1;              /* # of bits per pixel */
00187   *Ncols    = 1 << BitsPixel;
00188   PixMask   = (*Ncols) - 1;             /* mask for pixel code */
00189   if ((b & 0x80) == 0) {                /* is there color map? */
00190     fprintf(stderr,"\nGIFdecode: warning! no color map\n");
00191     *Ncols = 0;
00192   }
00193 
00194   ++ptr1;                               /* background color ... ignore */
00195   b      = *ptr1++;                     /* supposed to be NULL */
00196   if (b) {
00197     fprintf(stderr,"\nGIFdecode: bad screen descriptor\n");
00198     return 1;
00199   }
00200 
00201   for (i=0; i<(*Ncols); i++) {          /* global color map */
00202     R[i] = *ptr1++;
00203     G[i] = *ptr1++;
00204     B[i] = *ptr1++;
00205   }
00206 
00207   b      = *ptr1++;                     /* image separator */
00208   if (b != ',') {
00209     fprintf(stderr,"\nGIFdecode: no image separator\n");
00210     return 1;
00211   }
00212 
00213   ptr1   += 2;                          /* left offset ... ignore */
00214   ptr1   += 2;                          /* top offset ... ignore */
00215   b       = *ptr1++;                    /* image width */
00216   *Width  = b + 0x100*(*ptr1++);
00217   b       = *ptr1++;                    /* image height */
00218   *Height = b + 0x100*(*ptr1++);
00219 
00220   b       = *ptr1++;                    /* local colors, interlace */
00221   if ((b & 0xc0) != 0) {
00222     fprintf(stderr,
00223             "\nGIFdecode: unexpected item (local colors or interlace)\n");
00224     return 1;
00225   }
00226 
00227   IniCodeSize = *ptr1++;
00228   CurCodeSize = ++IniCodeSize;
00229   CurMaxCode  = (1 << IniCodeSize);
00230   ClearCode   = (1 << (IniCodeSize - 1));
00231   EOFCode     = ClearCode + 1;
00232   FreeCode    = ClearCode + 2;
00233 
00234   /*   D E C O D E    I M A G E   */
00235 
00236   Npix     =(long) (*Width) * (*Height);
00237   OutCount = 0;
00238   CurBit   = -1;
00239   CurCode  = ReadCode();
00240   while (Npix > 0) {
00241 
00242     if (CurCode < 0) {
00243       fprintf(stderr,"\nGIFdecode: corrupted GIF (zero block length)\n");
00244       return 1;
00245     }
00246 
00247     if (CurCode == EOFCode) {
00248       fprintf(stderr,"\nGIFdecode: corrupted GIF (unexpected EOF)\n");
00249       return 1;
00250     }
00251 
00252     if (CurCode == ClearCode) {         /* clear code ... reset */
00253 
00254       CurCodeSize = IniCodeSize;
00255       CurMaxCode  = (1 << IniCodeSize);
00256       FreeCode    = ClearCode + 2;
00257       OldCode     = CurCode = ReadCode();
00258       FinChar     = CurCode;
00259       OutPixel(FinChar);
00260       Npix--;
00261 
00262     } else {                            /* image code */
00263 
00264       InCode = CurCode;
00265       if (CurCode >= FreeCode) {
00266         CurCode = OldCode;
00267         OutCode[OutCount++] = FinChar;
00268       }
00269       while (CurCode > PixMask) {       /* build output pixel chain */
00270         if (OutCount >= TSIZE) {
00271           fprintf(stderr,"\nGIFdecode: corrupted GIF (big output count)\n");
00272           return 1;
00273         }
00274       OutCode[OutCount++] = Suffix[CurCode];
00275       CurCode = Prefix[CurCode];
00276       }
00277       FinChar = CurCode;
00278       OutCode[OutCount++] = FinChar;
00279 
00280       for (i=OutCount-1; i>=0; i--) {   /* put out pixel chain */
00281         OutPixel(OutCode[i]);
00282         Npix--;
00283       }
00284       OutCount = 0;
00285 
00286       Prefix[FreeCode] = OldCode;       /* build the tables */
00287       Suffix[FreeCode] = FinChar;
00288       OldCode = InCode;
00289 
00290       FreeCode++;                       /* move pointer */
00291       if (FreeCode >= CurMaxCode) {
00292         if (CurCodeSize < BITS) {
00293           CurCodeSize++;
00294           CurMaxCode *= 2;
00295         }
00296       }
00297     }
00298     CurCode = ReadCode();
00299   }
00300   return 0;
00301 }

Generated on Tue Jul 5 14:14:44 2011 for ROOT_528-00b_version by  doxygen 1.5.1