gifencode.c

Go to the documentation of this file.
00001 /* @(#)root/x11:$Id: gifencode.c 20882 2007-11-19 11:31:26Z rdm $ */
00002 /* Author: E.Chernyaev   19/01/94*/
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <string.h>
00006 
00007 #ifdef __STDC__
00008 #define ARGS(alist) alist
00009 #else
00010 #define ARGS(alist) ()
00011 #endif
00012 
00013 #define BITS     12                     /* largest code size */
00014 #define THELIMIT 4096                   /* NEVER generate this */
00015 #define HSIZE    5003                   /* hash table size */
00016 #define SHIFT    4                      /* shift for hashing */
00017 
00018 #define put_byte(A) (*put_b)((byte)(A)); Nbyte++
00019 
00020 typedef unsigned char byte;
00021 
00022 static long     HashTab [HSIZE];        /* hash table */
00023 static int      CodeTab [HSIZE];        /* code table */
00024 
00025 static int      BitsPixel,              /* number of bits per pixel */
00026                 IniCodeSize,            /* initial number of bits per code */
00027                 CurCodeSize,            /* current number of bits per code */
00028                 CurMaxCode,             /* maximum code, given CurCodeSize */
00029                 ClearCode,              /* reset code */
00030                 EOFCode,                /* end of file code */
00031                 FreeCode;               /* first unused entry */
00032 
00033 static long      Nbyte;
00034 static void     (*put_b) ARGS((byte));
00035 
00036 static void     output ARGS((int));
00037 static void     char_init();
00038 static void     char_out ARGS((int));
00039 static void     char_flush();
00040 static void     put_short ARGS((int));
00041 
00042 /***********************************************************************
00043  *                                                                     *
00044  * Name: GIFencode                                   Date:    02.10.92 *
00045  * Author: E.Chernyaev (IHEP/Protvino)               Revised:          *
00046  *                                                                     *
00047  * Function: GIF compression of the image                              *
00048  *                                                                     *
00049  * Input: Width      - image width  (must be >= 8)                     *
00050  *        Height     - image height (must be >= 8)                     *
00051  *        Ncol       - number of colors                                *
00052  *        R[]        - red components                                  *
00053  *        G[]        - green components                                *
00054  *        B[]        - blue components                                 *
00055  *        ScLine[]   - array for scan line (byte per pixel)            *
00056  *        get_scline - user routine to read scan line:                 *
00057  *                       get_scline(y, Width, ScLine)                  *
00058  *        pb         - user routine for "put_byte": pb(b)              *
00059  *                                                                     *
00060  * Return: size of GIF                                                 *
00061  *                                                                     *
00062  ***********************************************************************/
00063 long GIFencode(Width, Height, Ncol, R, G, B, ScLine, get_scline, pb)
00064           int  Width, Height, Ncol;
00065           byte R[], G[], B[], ScLine[];
00066           void (*get_scline) ARGS((int, int, byte *)), (*pb) ARGS((byte));
00067 {
00068   long          CodeK;
00069   int           ncol, i, x, y, disp, Code, K;
00070 
00071   /*   C H E C K   P A R A M E T E R S   */
00072 
00073   Code = 0;
00074   if (Width <= 0 || Width > 4096 || Height <= 0 || Height > 4096) {
00075     fprintf(stderr,
00076             "\nGIFencode: incorrect image size: %d x %d\n", Width, Height);
00077     return 0;
00078   }
00079 
00080   if (Ncol <= 0 || Ncol > 256) {
00081     fprintf(stderr,"\nGIFencode: wrong number of colors: %d\n", Ncol);
00082     return 0;
00083   }
00084 
00085   /*   I N I T I A L I S A T I O N   */
00086 
00087   put_b  = pb;
00088   Nbyte  = 0;
00089   char_init();                          /* initialise "char_..." routines */
00090 
00091   /*   F I N D   #   O F   B I T S   P E R    P I X E L   */
00092 
00093   BitsPixel = 1;
00094   if (Ncol > 2)   BitsPixel = 2;
00095   if (Ncol > 4)   BitsPixel = 3;
00096   if (Ncol > 8)   BitsPixel = 4;
00097   if (Ncol > 16)  BitsPixel = 5;
00098   if (Ncol > 32)  BitsPixel = 6;
00099   if (Ncol > 64)  BitsPixel = 7;
00100   if (Ncol > 128) BitsPixel = 8;
00101 
00102   ncol  = 1 << BitsPixel;
00103   IniCodeSize = BitsPixel;
00104   if (BitsPixel <= 1) IniCodeSize = 2;
00105 
00106   /*   W R I T E   H E A D E R  */
00107 
00108   put_byte('G');                        /* magic number: GIF87a */
00109   put_byte('I');
00110   put_byte('F');
00111   put_byte('8');
00112   put_byte('7');
00113   put_byte('a');
00114 
00115   put_short(Width);                     /* screen size */
00116   put_short(Height);
00117 
00118   K  = 0x80;                            /* yes, there is a color map */
00119   K |= (8-1)<<4;                        /* OR in the color resolution */
00120   K |= (BitsPixel - 1);                 /* OR in the # of bits per pixel */
00121   put_byte(K);
00122 
00123   put_byte(0);                          /* background color */
00124   put_byte(0);                          /* future expansion byte */
00125 
00126   for (i=0; i<Ncol; i++) {              /* global colormap */
00127     put_byte(R[i]);
00128     put_byte(G[i]);
00129     put_byte(B[i]);
00130   }
00131   for (; i<ncol; i++) {
00132     put_byte(0);
00133     put_byte(0);
00134     put_byte(0);
00135   }
00136 
00137   put_byte(',');                        /* image separator */
00138   put_short(0);                         /* left offset of image */
00139   put_short(0);                         /* top offset of image */
00140   put_short(Width);                     /* image size */
00141   put_short(Height);
00142   put_byte(0);                          /* no local colors, no interlace */
00143   put_byte(IniCodeSize);                /* initial code size */
00144 
00145   /*   L W Z   C O M P R E S S I O N   */
00146 
00147   CurCodeSize = ++IniCodeSize;
00148   CurMaxCode  = (1 << (IniCodeSize)) - 1;
00149   ClearCode   = (1 << (IniCodeSize - 1));
00150   EOFCode     = ClearCode + 1;
00151   FreeCode    = ClearCode + 2;
00152   output(ClearCode);
00153   for (y=0; y<Height; y++) {
00154     (*get_scline)(y, Width, ScLine);
00155     x     = 0;
00156     if (y == 0)
00157       Code  = ScLine[x++];
00158     while(x < Width) {
00159       K     = ScLine[x++];              /* next symbol */
00160       CodeK = ((long) K << BITS) + Code;  /* set full code */
00161       i     = (K << SHIFT) ^ Code;      /* xor hashing */
00162 
00163       if (HashTab[i] == CodeK) {        /* full code found */
00164         Code = CodeTab[i];
00165         continue;
00166       }
00167       else if (HashTab[i] < 0 )         /* empty slot */
00168         goto NOMATCH;
00169 
00170       disp  = HSIZE - i;                /* secondary hash */
00171       if (i == 0) disp = 1;
00172 
00173 PROBE:
00174       if ((i -= disp) < 0)
00175         i  += HSIZE;
00176 
00177       if (HashTab[i] == CodeK) {        /* full code found */
00178         Code = CodeTab[i];
00179         continue;
00180       }
00181 
00182       if (HashTab[i] > 0)               /* try again */
00183         goto PROBE;
00184 
00185 NOMATCH:
00186       output(Code);                     /* full code not found */
00187       Code = K;
00188 
00189       if (FreeCode < THELIMIT) {
00190         CodeTab[i] = FreeCode++;        /* code -> hashtable */
00191         HashTab[i] = CodeK;
00192       }
00193       else
00194         output(ClearCode);
00195     }
00196   }
00197    /*   O U T P U T   T H E   R E S T  */
00198 
00199   output(Code);
00200   output(EOFCode);
00201   put_byte(0);                          /* zero-length packet (EOF) */
00202   put_byte(';');                        /* GIF file terminator */
00203 
00204   return (Nbyte);
00205 }
00206 
00207 static unsigned long cur_accum;
00208 static int           cur_bits;
00209 static int           a_count;
00210 static char          accum[256];
00211 static unsigned long masks[] = { 0x0000,
00212                                  0x0001, 0x0003, 0x0007, 0x000F,
00213                                  0x001F, 0x003F, 0x007F, 0x00FF,
00214                                  0x01FF, 0x03FF, 0x07FF, 0x0FFF,
00215                                  0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
00216 
00217 /***************************************************************
00218  *                                                             *
00219  * Name: output                                 Date: 02.10.92 *
00220  *                                                             *
00221  * Function: output GIF code                                   *
00222  *                                                             *
00223  * Input: code - GIF code                                      *
00224  *                                                             *
00225  ***************************************************************/
00226 static void output(code)
00227                int code;
00228 {
00229   /*   O U T P U T   C O D E   */
00230 
00231    cur_accum &= masks[cur_bits];
00232    if (cur_bits > 0)
00233      cur_accum |= ((long)code << cur_bits);
00234    else
00235      cur_accum = code;
00236    cur_bits += CurCodeSize;
00237    while( cur_bits >= 8 ) {
00238      char_out( (unsigned int) (cur_accum & 0xFF) );
00239      cur_accum >>= 8;
00240      cur_bits -= 8;
00241    }
00242 
00243   /*   R E S E T   */
00244 
00245   if (code == ClearCode ) {
00246     memset((char *) HashTab, -1, sizeof(HashTab));
00247     FreeCode = ClearCode + 2;
00248     CurCodeSize = IniCodeSize;
00249     CurMaxCode  = (1 << (IniCodeSize)) - 1;
00250   }
00251 
00252   /*   I N C R E A S E   C O D E   S I Z E   */
00253 
00254   if (FreeCode > CurMaxCode ) {
00255       CurCodeSize++;
00256       if ( CurCodeSize == BITS )
00257         CurMaxCode = THELIMIT;
00258       else
00259         CurMaxCode = (1 << (CurCodeSize)) - 1;
00260    }
00261 
00262   /*   E N D   O F   F I L E :  write the rest of the buffer  */
00263 
00264   if( code == EOFCode ) {
00265     while( cur_bits > 0 ) {
00266       char_out( (unsigned int)(cur_accum & 0xff) );
00267       cur_accum >>= 8;
00268       cur_bits -= 8;
00269     }
00270     char_flush();
00271   }
00272 }
00273 
00274 static void char_init()
00275 {
00276    a_count = 0;
00277    cur_accum = 0;
00278    cur_bits  = 0;
00279 }
00280 
00281 static void char_out(c)
00282                  int c;
00283 {
00284    accum[a_count++] = c;
00285    if (a_count >= 254)
00286       char_flush();
00287 }
00288 
00289 static void char_flush()
00290 {
00291   int i;
00292 
00293   if (a_count == 0) return;
00294   put_byte(a_count);
00295   for (i=0; i<a_count; i++) {
00296     put_byte(accum[i]);
00297   }
00298   a_count = 0;
00299 }
00300 
00301 static void put_short(word)
00302                   int word;
00303 {
00304   put_byte(word & 0xFF);
00305   put_byte((word>>8) & 0xFF);
00306 }

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