00001
00002
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
00014 #define THELIMIT 4096
00015 #define HSIZE 5003
00016 #define SHIFT 4
00017
00018 #define put_byte(A) (*put_b)((byte)(A)); Nbyte++
00019
00020 typedef unsigned char byte;
00021
00022 static long HashTab [HSIZE];
00023 static int CodeTab [HSIZE];
00024
00025 static int BitsPixel,
00026 IniCodeSize,
00027 CurCodeSize,
00028 CurMaxCode,
00029 ClearCode,
00030 EOFCode,
00031 FreeCode;
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
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
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
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
00086
00087 put_b = pb;
00088 Nbyte = 0;
00089 char_init();
00090
00091
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
00107
00108 put_byte('G');
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);
00116 put_short(Height);
00117
00118 K = 0x80;
00119 K |= (8-1)<<4;
00120 K |= (BitsPixel - 1);
00121 put_byte(K);
00122
00123 put_byte(0);
00124 put_byte(0);
00125
00126 for (i=0; i<Ncol; i++) {
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(',');
00138 put_short(0);
00139 put_short(0);
00140 put_short(Width);
00141 put_short(Height);
00142 put_byte(0);
00143 put_byte(IniCodeSize);
00144
00145
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++];
00160 CodeK = ((long) K << BITS) + Code;
00161 i = (K << SHIFT) ^ Code;
00162
00163 if (HashTab[i] == CodeK) {
00164 Code = CodeTab[i];
00165 continue;
00166 }
00167 else if (HashTab[i] < 0 )
00168 goto NOMATCH;
00169
00170 disp = HSIZE - i;
00171 if (i == 0) disp = 1;
00172
00173 PROBE:
00174 if ((i -= disp) < 0)
00175 i += HSIZE;
00176
00177 if (HashTab[i] == CodeK) {
00178 Code = CodeTab[i];
00179 continue;
00180 }
00181
00182 if (HashTab[i] > 0)
00183 goto PROBE;
00184
00185 NOMATCH:
00186 output(Code);
00187 Code = K;
00188
00189 if (FreeCode < THELIMIT) {
00190 CodeTab[i] = FreeCode++;
00191 HashTab[i] = CodeK;
00192 }
00193 else
00194 output(ClearCode);
00195 }
00196 }
00197
00198
00199 output(Code);
00200 output(EOFCode);
00201 put_byte(0);
00202 put_byte(';');
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
00220
00221
00222
00223
00224
00225
00226 static void output(code)
00227 int code;
00228 {
00229
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
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
00253
00254 if (FreeCode > CurMaxCode ) {
00255 CurCodeSize++;
00256 if ( CurCodeSize == BITS )
00257 CurMaxCode = THELIMIT;
00258 else
00259 CurMaxCode = (1 << (CurCodeSize)) - 1;
00260 }
00261
00262
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 }