00001
00002
00003 #include <stdio.h>
00004 #include <string.h>
00005
00006
00007 #define BITS 12
00008 #define TSIZE 4096
00009
00010 typedef unsigned char byte;
00011
00012 static int Prefix[TSIZE];
00013 static byte Suffix[TSIZE];
00014 static byte OutCode[TSIZE];
00015
00016 static byte *ptr1,
00017 *ptr2;
00018
00019 static int CurCodeSize,
00020 CurMaxCode;
00021
00022 static long CurBit;
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
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 int GIFinfo(byte *GIFarr, int *Width, int *Height, int *Ncols)
00081 {
00082 byte b;
00083
00084 ptr1 = GIFarr;
00085
00086
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;
00097 ptr1 += 2;
00098
00099 b = *ptr1++;
00100 *Ncols = 1 << ((b & 7) + 1);
00101 if ((b & 0x80) == 0) {
00102 fprintf(stderr,"\nGIFinfo: warning! no color map\n");
00103 *Ncols = 0;
00104 }
00105
00106 ++ptr1;
00107 b = *ptr1++;
00108 if (b) {
00109 fprintf(stderr,"\nGIFdecode: bad screen descriptor\n");
00110 return 1;
00111 }
00112
00113 ptr1 += (*Ncols) * 3;
00114
00115 b = *ptr1++;
00116 if (b != ',') {
00117 fprintf(stderr,"\nGIFinfo: no image separator\n");
00118 return 1;
00119 }
00120
00121 ptr1 += 2;
00122 ptr1 += 2;
00123 b = *ptr1++;
00124 *Width = b + 0x100*(*ptr1++);
00125 b = *ptr1++;
00126 *Height = b + 0x100*(*ptr1++);
00127 return 0;
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
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,
00152 FinChar;
00153
00154 int i,
00155 BitsPixel,
00156 IniCodeSize,
00157 ClearCode,
00158 EOFCode,
00159 FreeCode,
00160 CurCode,
00161 InCode,
00162 OldCode,
00163 PixMask,
00164 OutCount;
00165
00166 long Npix;
00167
00168 ptr1 = GIFarr;
00169 ptr2 = PIXarr;
00170 OldCode = 0;
00171 FinChar = 0;
00172
00173
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;
00183 ptr1 += 2;
00184
00185 b = *ptr1++;
00186 BitsPixel = (b & 7) + 1;
00187 *Ncols = 1 << BitsPixel;
00188 PixMask = (*Ncols) - 1;
00189 if ((b & 0x80) == 0) {
00190 fprintf(stderr,"\nGIFdecode: warning! no color map\n");
00191 *Ncols = 0;
00192 }
00193
00194 ++ptr1;
00195 b = *ptr1++;
00196 if (b) {
00197 fprintf(stderr,"\nGIFdecode: bad screen descriptor\n");
00198 return 1;
00199 }
00200
00201 for (i=0; i<(*Ncols); i++) {
00202 R[i] = *ptr1++;
00203 G[i] = *ptr1++;
00204 B[i] = *ptr1++;
00205 }
00206
00207 b = *ptr1++;
00208 if (b != ',') {
00209 fprintf(stderr,"\nGIFdecode: no image separator\n");
00210 return 1;
00211 }
00212
00213 ptr1 += 2;
00214 ptr1 += 2;
00215 b = *ptr1++;
00216 *Width = b + 0x100*(*ptr1++);
00217 b = *ptr1++;
00218 *Height = b + 0x100*(*ptr1++);
00219
00220 b = *ptr1++;
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
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) {
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 {
00263
00264 InCode = CurCode;
00265 if (CurCode >= FreeCode) {
00266 CurCode = OldCode;
00267 OutCode[OutCount++] = FinChar;
00268 }
00269 while (CurCode > PixMask) {
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--) {
00281 OutPixel(OutCode[i]);
00282 Npix--;
00283 }
00284 OutCount = 0;
00285
00286 Prefix[FreeCode] = OldCode;
00287 Suffix[FreeCode] = FinChar;
00288 OldCode = InCode;
00289
00290 FreeCode++;
00291 if (FreeCode >= CurMaxCode) {
00292 if (CurCodeSize < BITS) {
00293 CurCodeSize++;
00294 CurMaxCode *= 2;
00295 }
00296 }
00297 }
00298 CurCode = ReadCode();
00299 }
00300 return 0;
00301 }