Mercurial > hg > xemacs-beta
comparison src/dgif_lib.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 0293115a14e9 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 /* Synched up with: Not in FSF. */ | |
2 | |
3 /****************************************************************************** | |
4 * "Gif-Lib" - Yet another gif library. * | |
5 * * | |
6 * Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990 * | |
7 ******************************************************************************* | |
8 * The kernel of the GIF Decoding process can be found here. * | |
9 ******************************************************************************* | |
10 * History: * | |
11 * 16 Jun 89 - Version 1.0 by Gershon Elber. * | |
12 * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). * | |
13 ******************************************************************************/ | |
14 | |
15 #ifdef __MSDOS__ | |
16 #include <io.h> | |
17 #include <alloc.h> | |
18 #include <stdlib.h> | |
19 #include <sys\stat.h> | |
20 #else | |
21 #include <sys/types.h> | |
22 #include <sys/stat.h> | |
23 #endif /* __MSDOS__ */ | |
24 | |
25 #include <fcntl.h> | |
26 #include <stdio.h> | |
27 #include <string.h> | |
28 | |
29 #ifdef emacs | |
30 #include <config.h> | |
31 void *xmalloc (unsigned int size); | |
32 void *xrealloc (void *ptr, unsigned int size); | |
33 #ifdef ERROR_CHECK_MALLOC | |
34 void *xfree_1 (void *); | |
35 #define xfree xfree_1 | |
36 #else | |
37 void *xfree (void *); | |
38 #endif | |
39 #endif | |
40 | |
41 #include "gif_lib.h" | |
42 #ifndef emacs | |
43 #include "gif_hash.h" | |
44 #endif | |
45 | |
46 #define PROGRAM_NAME "GIF_LIBRARY" | |
47 | |
48 #define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for comment. */ | |
49 #define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */ | |
50 #define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1 | |
51 #define GIF_VERSION_POS 3 /* Version first character in stamp. */ | |
52 | |
53 #define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ | |
54 #define LZ_BITS 12 | |
55 | |
56 #define FILE_STATE_READ 0x01/* 1 write, 0 read - EGIF_LIB compatible.*/ | |
57 | |
58 #define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */ | |
59 #define FIRST_CODE 4097 /* Impossible code, to signal first. */ | |
60 #define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */ | |
61 | |
62 #define IS_READABLE(Private) (!(Private->FileState & FILE_STATE_READ)) | |
63 | |
64 typedef struct GifFilePrivateType { | |
65 int FileState, | |
66 FileHandle, /* Where all this data goes to! */ | |
67 BitsPerPixel, /* Bits per pixel (Codes uses at list this + 1). */ | |
68 ClearCode, /* The CLEAR LZ code. */ | |
69 EOFCode, /* The EOF LZ code. */ | |
70 RunningCode, /* The next code algorithm can generate. */ | |
71 RunningBits,/* The number of bits required to represent RunningCode. */ | |
72 MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */ | |
73 LastCode, /* The code before the current code. */ | |
74 CrntCode, /* Current algorithm code. */ | |
75 StackPtr, /* For character stack (see below). */ | |
76 CrntShiftState; /* Number of bits in CrntShiftDWord. */ | |
77 unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */ | |
78 long PixelCount; /* Number of pixels in image. */ | |
79 FILE *File; /* File as stream. */ | |
80 GifByteType Buf[256]; /* Compressed input is buffered here. */ | |
81 GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */ | |
82 GifByteType Suffix[LZ_MAX_CODE+1]; /* So we can trace the codes. */ | |
83 unsigned int Prefix[LZ_MAX_CODE+1]; | |
84 } GifFilePrivateType; | |
85 | |
86 #ifndef emacs | |
87 #ifdef SYSV | |
88 static char *VersionStr = | |
89 "Gif library module,\t\tGershon Elber\n\ | |
90 (C) Copyright 1989 Gershon Elber, Non commercial use only.\n"; | |
91 #else | |
92 static char *VersionStr = | |
93 PROGRAM_NAME | |
94 " IBMPC " | |
95 GIF_LIB_VERSION | |
96 " Gershon Elber, " | |
97 __DATE__ ", " __TIME__ "\n" | |
98 "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n"; | |
99 #endif /* SYSV */ | |
100 #endif /* !emacs */ | |
101 | |
102 extern int _GifError; | |
103 | |
104 static int DGifGetWord(FILE *File, int *Word); | |
105 static int DGifSetupDecompress(GifFileType *GifFile); | |
106 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, | |
107 int LineLen); | |
108 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode); | |
109 static int DGifDecompressInput(GifFilePrivateType *Private, int *Code); | |
110 static int DGifBufferedInput(FILE *File, GifByteType *Buf, | |
111 GifByteType *NextByte); | |
112 | |
113 /****************************************************************************** | |
114 * Open a new gif file for read, given by its name. * | |
115 * Returns GifFileType pointer dynamically allocated which serves as the gif * | |
116 * info record. _GifError is cleared if succesfull. * | |
117 ******************************************************************************/ | |
118 GifFileType *DGifOpenFileName(const char *FileName) | |
119 { | |
120 int FileHandle; | |
121 | |
122 if ((FileHandle = open(FileName, O_RDONLY | |
123 #ifdef __MSDOS__ | |
124 | O_BINARY | |
125 #endif /* __MSDOS__ */ | |
126 )) == -1) { | |
127 _GifError = D_GIF_ERR_OPEN_FAILED; | |
128 return NULL; | |
129 } | |
130 | |
131 return DGifOpenFileHandle(FileHandle); | |
132 } | |
133 | |
134 /****************************************************************************** | |
135 * Update a new gif file, given its file handle. * | |
136 * Returns GifFileType pointer dynamically allocated which serves as the gif * | |
137 * info record. _GifError is cleared if succesfull. * | |
138 ******************************************************************************/ | |
139 GifFileType *DGifOpenFileHandle(int FileHandle) | |
140 { | |
141 char Buf[GIF_STAMP_LEN+1]; | |
142 GifFileType *GifFile; | |
143 GifFilePrivateType *Private; | |
144 FILE *f; | |
145 | |
146 #ifdef __MSDOS__ | |
147 setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ | |
148 f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ | |
149 setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/ | |
150 #else | |
151 f = fdopen(FileHandle, "r"); /* Make it into a stream: */ | |
152 #endif /* __MSDOS__ */ | |
153 | |
154 if ((GifFile = (GifFileType *) xmalloc(sizeof(GifFileType))) == NULL) { | |
155 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; | |
156 return NULL; | |
157 } | |
158 | |
159 memset(GifFile, '\0', sizeof(GifFileType)); | |
160 | |
161 if ((Private = (GifFilePrivateType *) xmalloc(sizeof(GifFilePrivateType))) | |
162 == NULL) { | |
163 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; | |
164 xfree((char *) GifFile); | |
165 return NULL; | |
166 } | |
167 GifFile->Private = (VoidPtr) Private; | |
168 Private->FileHandle = FileHandle; | |
169 Private->File = f; | |
170 Private->FileState = 0; /* Make sure bit 0 = 0 (File open for read). */ | |
171 | |
172 /* Lets see if this is a GIF file: */ | |
173 if (fread(Buf, 1, GIF_STAMP_LEN, Private->File) != GIF_STAMP_LEN) { | |
174 _GifError = D_GIF_ERR_READ_FAILED; | |
175 xfree((char *) Private); | |
176 xfree((char *) GifFile); | |
177 return NULL; | |
178 } | |
179 | |
180 /* The GIF Version number is ignored at this time. Maybe we should do */ | |
181 /* something more useful with it. */ | |
182 Buf[GIF_STAMP_LEN] = 0; | |
183 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { | |
184 _GifError = D_GIF_ERR_NOT_GIF_FILE; | |
185 xfree((char *) Private); | |
186 xfree((char *) GifFile); | |
187 return NULL; | |
188 } | |
189 | |
190 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { | |
191 xfree((char *) Private); | |
192 xfree((char *) GifFile); | |
193 return NULL; | |
194 } | |
195 | |
196 _GifError = 0; | |
197 | |
198 return GifFile; | |
199 } | |
200 | |
201 /****************************************************************************** | |
202 * This routine should be called before any other DGif calls. Note that * | |
203 * this routine is called automatically from DGif file open routines. * | |
204 ******************************************************************************/ | |
205 int DGifGetScreenDesc(GifFileType *GifFile) | |
206 { | |
207 int i, BitsPerPixel; | |
208 GifByteType Buf[3]; | |
209 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
210 | |
211 if (!IS_READABLE(Private)) { | |
212 /* This file was NOT open for reading: */ | |
213 _GifError = D_GIF_ERR_NOT_READABLE; | |
214 return GIF_ERROR; | |
215 } | |
216 | |
217 /* Put the screen descriptor into the file: */ | |
218 if (DGifGetWord(Private->File, &GifFile->SWidth) == GIF_ERROR || | |
219 DGifGetWord(Private->File, &GifFile->SHeight) == GIF_ERROR) | |
220 return GIF_ERROR; | |
221 | |
222 if (fread(Buf, 1, 3, Private->File) != 3) { | |
223 _GifError = D_GIF_ERR_READ_FAILED; | |
224 return GIF_ERROR; | |
225 } | |
226 GifFile->SColorResolution = ((int) ((Buf[0] & 0x70) + 1) >> 4) + 1; | |
227 BitsPerPixel = (Buf[0] & 0x07) + 1; | |
228 GifFile->SBackGroundColor = Buf[1]; | |
229 if (Buf[0] & 0x80) { /* Do we have global color map? */ | |
230 | |
231 GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL); | |
232 | |
233 /* Get the global color map: */ | |
234 for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { | |
235 if (fread(Buf, 1, 3, Private->File) != 3) { | |
236 _GifError = D_GIF_ERR_READ_FAILED; | |
237 return GIF_ERROR; | |
238 } | |
239 GifFile->SColorMap->Colors[i].Red = Buf[0]; | |
240 GifFile->SColorMap->Colors[i].Green = Buf[1]; | |
241 GifFile->SColorMap->Colors[i].Blue = Buf[2]; | |
242 } | |
243 } | |
244 | |
245 return GIF_OK; | |
246 } | |
247 | |
248 /****************************************************************************** | |
249 * This routine should be called before any attemp to read an image. * | |
250 ******************************************************************************/ | |
251 int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type) | |
252 { | |
253 GifByteType Buf; | |
254 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
255 | |
256 if (!IS_READABLE(Private)) { | |
257 /* This file was NOT open for reading: */ | |
258 _GifError = D_GIF_ERR_NOT_READABLE; | |
259 return GIF_ERROR; | |
260 } | |
261 | |
262 if (fread(&Buf, 1, 1, Private->File) != 1) { | |
263 _GifError = D_GIF_ERR_READ_FAILED; | |
264 return GIF_ERROR; | |
265 } | |
266 | |
267 switch (Buf) { | |
268 case ',': | |
269 *Type = IMAGE_DESC_RECORD_TYPE; | |
270 break; | |
271 case '!': | |
272 *Type = EXTENSION_RECORD_TYPE; | |
273 break; | |
274 case ';': | |
275 *Type = TERMINATE_RECORD_TYPE; | |
276 break; | |
277 default: | |
278 *Type = UNDEFINED_RECORD_TYPE; | |
279 _GifError = D_GIF_ERR_WRONG_RECORD; | |
280 return GIF_ERROR; | |
281 } | |
282 | |
283 return GIF_OK; | |
284 } | |
285 | |
286 /****************************************************************************** | |
287 * This routine should be called before any attemp to read an image. * | |
288 * Note it is assumed the Image desc. header (',') has been read. * | |
289 ******************************************************************************/ | |
290 int DGifGetImageDesc(GifFileType *GifFile) | |
291 { | |
292 int i, BitsPerPixel; | |
293 GifByteType Buf[3]; | |
294 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
295 | |
296 if (!IS_READABLE(Private)) { | |
297 /* This file was NOT open for reading: */ | |
298 _GifError = D_GIF_ERR_NOT_READABLE; | |
299 return GIF_ERROR; | |
300 } | |
301 | |
302 if (DGifGetWord(Private->File, &GifFile->Image.Left) == GIF_ERROR || | |
303 DGifGetWord(Private->File, &GifFile->Image.Top) == GIF_ERROR || | |
304 DGifGetWord(Private->File, &GifFile->Image.Width) == GIF_ERROR || | |
305 DGifGetWord(Private->File, &GifFile->Image.Height) == GIF_ERROR) | |
306 return GIF_ERROR; | |
307 if (fread(Buf, 1, 1, Private->File) != 1) { | |
308 _GifError = D_GIF_ERR_READ_FAILED; | |
309 return GIF_ERROR; | |
310 } | |
311 BitsPerPixel = (Buf[0] & 0x07) + 1; | |
312 GifFile->Image.Interlace = (Buf[0] & 0x40); | |
313 if (Buf[0] & 0x80) { /* Does this image have local color map? */ | |
314 | |
315 if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL) | |
316 FreeMapObject(GifFile->Image.ColorMap); | |
317 | |
318 GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL); | |
319 | |
320 /* Get the image local color map: */ | |
321 for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { | |
322 if (fread(Buf, 1, 3, Private->File) != 3) { | |
323 _GifError = D_GIF_ERR_READ_FAILED; | |
324 return GIF_ERROR; | |
325 } | |
326 GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; | |
327 GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; | |
328 GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; | |
329 } | |
330 } | |
331 | |
332 if (GifFile->SavedImages) { | |
333 SavedImage *sp; | |
334 | |
335 if ((GifFile->SavedImages = (SavedImage *)xrealloc(GifFile->SavedImages, | |
336 sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) { | |
337 _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; | |
338 return GIF_ERROR; | |
339 } | |
340 | |
341 sp = &GifFile->SavedImages[GifFile->ImageCount]; | |
342 memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); | |
343 if (GifFile->Image.ColorMap) | |
344 { | |
345 sp->ImageDesc.ColorMap = | |
346 MakeMapObject (GifFile->Image.ColorMap->ColorCount, | |
347 GifFile->Image.ColorMap->Colors); | |
348 } | |
349 sp->RasterBits = (GifPixelType *)NULL; | |
350 sp->ExtensionBlockCount = 0; | |
351 sp->ExtensionBlocks = (ExtensionBlock *)NULL; | |
352 } | |
353 | |
354 GifFile->ImageCount++; | |
355 | |
356 Private->PixelCount = (long) GifFile->Image.Width * | |
357 (long) GifFile->Image.Height; | |
358 | |
359 DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */ | |
360 | |
361 return GIF_OK; | |
362 } | |
363 | |
364 /****************************************************************************** | |
365 * Get one full scanned line (Line) of length LineLen from GIF file. * | |
366 ******************************************************************************/ | |
367 int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) | |
368 { | |
369 GifByteType *Dummy; | |
370 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
371 | |
372 if (!IS_READABLE(Private)) { | |
373 /* This file was NOT open for reading: */ | |
374 _GifError = D_GIF_ERR_NOT_READABLE; | |
375 return GIF_ERROR; | |
376 } | |
377 | |
378 if (!LineLen) LineLen = GifFile->Image.Width; | |
379 | |
380 #ifdef __MSDOS__ | |
381 if ((Private->PixelCount -= LineLen) > 0xffff0000UL) { | |
382 #else | |
383 if ((unsigned) (Private->PixelCount -= LineLen) > 0xffff0000) { | |
384 #endif /* __MSDOS__ */ | |
385 _GifError = D_GIF_ERR_DATA_TOO_BIG; | |
386 return GIF_ERROR; | |
387 } | |
388 | |
389 if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) { | |
390 if (Private->PixelCount == 0) { | |
391 /* We probably would not be called any more, so lets clean */ | |
392 /* everything before we return: need to flush out all rest of */ | |
393 /* image until empty block (size 0) detected. We use GetCodeNext.*/ | |
394 do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) | |
395 return GIF_ERROR; | |
396 while (Dummy != NULL); | |
397 } | |
398 return GIF_OK; | |
399 } | |
400 else | |
401 return GIF_ERROR; | |
402 } | |
403 | |
404 /****************************************************************************** | |
405 * Put one pixel (Pixel) into GIF file. * | |
406 ******************************************************************************/ | |
407 int DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel) | |
408 { | |
409 GifByteType *Dummy; | |
410 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
411 | |
412 if (!IS_READABLE(Private)) { | |
413 /* This file was NOT open for reading: */ | |
414 _GifError = D_GIF_ERR_NOT_READABLE; | |
415 return GIF_ERROR; | |
416 } | |
417 | |
418 #ifdef __MSDOS__ | |
419 if (--Private->PixelCount > 0xffff0000UL) | |
420 #else | |
421 if ((unsigned) --Private->PixelCount > 0xffff0000) | |
422 #endif /* __MSDOS__ */ | |
423 { | |
424 _GifError = D_GIF_ERR_DATA_TOO_BIG; | |
425 return GIF_ERROR; | |
426 } | |
427 | |
428 if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) { | |
429 if (Private->PixelCount == 0) { | |
430 /* We probably would not be called any more, so lets clean */ | |
431 /* everything before we return: need to flush out all rest of */ | |
432 /* image until empty block (size 0) detected. We use GetCodeNext.*/ | |
433 do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) | |
434 return GIF_ERROR; | |
435 while (Dummy != NULL); | |
436 } | |
437 return GIF_OK; | |
438 } | |
439 else | |
440 return GIF_ERROR; | |
441 } | |
442 | |
443 /****************************************************************************** | |
444 * Get an extension block (see GIF manual) from gif file. This routine only * | |
445 * returns the first data block, and DGifGetExtensionNext shouldbe called * | |
446 * after this one until NULL extension is returned. * | |
447 * The Extension should NOT be freed by the user (not dynamically allocated).* | |
448 * Note it is assumed the Extension desc. header ('!') has been read. * | |
449 ******************************************************************************/ | |
450 int DGifGetExtension(GifFileType *GifFile, int *ExtCode, | |
451 GifByteType **Extension) | |
452 { | |
453 GifByteType Buf; | |
454 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
455 | |
456 if (!IS_READABLE(Private)) { | |
457 /* This file was NOT open for reading: */ | |
458 _GifError = D_GIF_ERR_NOT_READABLE; | |
459 return GIF_ERROR; | |
460 } | |
461 | |
462 if (fread(&Buf, 1, 1, Private->File) != 1) { | |
463 _GifError = D_GIF_ERR_READ_FAILED; | |
464 return GIF_ERROR; | |
465 } | |
466 *ExtCode = Buf; | |
467 | |
468 return DGifGetExtensionNext(GifFile, Extension); | |
469 } | |
470 | |
471 /****************************************************************************** | |
472 * Get a following extension block (see GIF manual) from gif file. This * | |
473 * routine sould be called until NULL Extension is returned. * | |
474 * The Extension should NOT be freed by the user (not dynamically allocated).* | |
475 ******************************************************************************/ | |
476 int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension) | |
477 { | |
478 GifByteType Buf; | |
479 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
480 | |
481 if (fread(&Buf, 1, 1, Private->File) != 1) { | |
482 _GifError = D_GIF_ERR_READ_FAILED; | |
483 return GIF_ERROR; | |
484 } | |
485 if (Buf > 0) { | |
486 *Extension = Private->Buf; /* Use private unused buffer. */ | |
487 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ | |
488 if (fread(&((*Extension)[1]), 1, Buf, Private->File) != Buf) { | |
489 _GifError = D_GIF_ERR_READ_FAILED; | |
490 return GIF_ERROR; | |
491 } | |
492 } | |
493 else | |
494 *Extension = NULL; | |
495 | |
496 return GIF_OK; | |
497 } | |
498 | |
499 /****************************************************************************** | |
500 * This routine should be called last, to close the GIF file. * | |
501 ******************************************************************************/ | |
502 int DGifCloseFile(GifFileType *GifFile) | |
503 { | |
504 GifFilePrivateType *Private; | |
505 FILE *File; | |
506 | |
507 if (GifFile == NULL) return GIF_ERROR; | |
508 | |
509 Private = (GifFilePrivateType *) GifFile->Private; | |
510 | |
511 if (!IS_READABLE(Private)) { | |
512 /* This file was NOT open for reading: */ | |
513 _GifError = D_GIF_ERR_NOT_READABLE; | |
514 return GIF_ERROR; | |
515 } | |
516 | |
517 File = Private->File; | |
518 | |
519 if (GifFile->Image.ColorMap) | |
520 { | |
521 FreeMapObject(GifFile->Image.ColorMap); | |
522 GifFile->Image.ColorMap = 0; | |
523 } | |
524 if (GifFile->SColorMap) | |
525 { | |
526 FreeMapObject(GifFile->SColorMap); | |
527 GifFile->SColorMap = 0; | |
528 } | |
529 if (Private) | |
530 { | |
531 xfree((char *) Private); | |
532 GifFile->Private = 0; | |
533 } | |
534 if (GifFile->SavedImages) | |
535 { | |
536 FreeSavedImages(GifFile); | |
537 GifFile->SavedImages = 0; | |
538 } | |
539 xfree(GifFile); | |
540 | |
541 if (fclose(File) != 0) { | |
542 _GifError = D_GIF_ERR_CLOSE_FAILED; | |
543 return GIF_ERROR; | |
544 } | |
545 return GIF_OK; | |
546 } | |
547 | |
548 /****************************************************************************** | |
549 * Get 2 bytes (word) from the given file: * | |
550 ******************************************************************************/ | |
551 static int DGifGetWord(FILE *File, int *Word) | |
552 { | |
553 unsigned char c[2]; | |
554 | |
555 if (fread(c, 1, 2, File) != 2) { | |
556 _GifError = D_GIF_ERR_READ_FAILED; | |
557 return GIF_ERROR; | |
558 } | |
559 | |
560 *Word = (((unsigned int) c[1]) << 8) + c[0]; | |
561 return GIF_OK; | |
562 } | |
563 | |
564 /****************************************************************************** | |
565 * Get the image code in compressed form. his routine can be called if the * | |
566 * information needed to be piped out as is. Obviously this is much faster * | |
567 * than decoding and encoding again. This routine should be followed by calls * | |
568 * to DGifGetCodeNext, until NULL block is returned. * | |
569 * The block should NOT be freed by the user (not dynamically allocated). * | |
570 ******************************************************************************/ | |
571 int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock) | |
572 { | |
573 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
574 | |
575 if (!IS_READABLE(Private)) { | |
576 /* This file was NOT open for reading: */ | |
577 _GifError = D_GIF_ERR_NOT_READABLE; | |
578 return GIF_ERROR; | |
579 } | |
580 | |
581 *CodeSize = Private->BitsPerPixel; | |
582 | |
583 return DGifGetCodeNext(GifFile, CodeBlock); | |
584 } | |
585 | |
586 /****************************************************************************** | |
587 * Continue to get the image code in compressed form. This routine should be * | |
588 * called until NULL block is returned. * | |
589 * The block should NOT be freed by the user (not dynamically allocated). * | |
590 ******************************************************************************/ | |
591 int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) | |
592 { | |
593 GifByteType Buf; | |
594 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
595 | |
596 if (fread(&Buf, 1, 1, Private->File) != 1) { | |
597 _GifError = D_GIF_ERR_READ_FAILED; | |
598 return GIF_ERROR; | |
599 } | |
600 | |
601 if (Buf > 0) { | |
602 *CodeBlock = Private->Buf; /* Use private unused buffer. */ | |
603 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ | |
604 if (fread(&((*CodeBlock)[1]), 1, Buf, Private->File) != Buf) { | |
605 _GifError = D_GIF_ERR_READ_FAILED; | |
606 return GIF_ERROR; | |
607 } | |
608 } | |
609 else { | |
610 *CodeBlock = NULL; | |
611 Private->Buf[0] = 0; /* Make sure the buffer is empty! */ | |
612 Private->PixelCount = 0; /* And local info. indicate image read. */ | |
613 } | |
614 | |
615 return GIF_OK; | |
616 } | |
617 | |
618 /****************************************************************************** | |
619 * Setup the LZ decompression for this image: * | |
620 ******************************************************************************/ | |
621 static int DGifSetupDecompress(GifFileType *GifFile) | |
622 { | |
623 int i, BitsPerPixel; | |
624 GifByteType CodeSize; | |
625 unsigned int *Prefix; | |
626 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
627 | |
628 fread(&CodeSize, 1, 1, Private->File); /* Read Code size from file. */ | |
629 BitsPerPixel = CodeSize; | |
630 | |
631 Private->Buf[0] = 0; /* Input Buffer empty. */ | |
632 Private->BitsPerPixel = BitsPerPixel; | |
633 Private->ClearCode = (1 << BitsPerPixel); | |
634 Private->EOFCode = Private->ClearCode + 1; | |
635 Private->RunningCode = Private->EOFCode + 1; | |
636 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */ | |
637 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */ | |
638 Private->StackPtr = 0; /* No pixels on the pixel stack. */ | |
639 Private->LastCode = NO_SUCH_CODE; | |
640 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */ | |
641 Private->CrntShiftDWord = 0; | |
642 | |
643 Prefix = Private->Prefix; | |
644 for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE; | |
645 | |
646 return GIF_OK; | |
647 } | |
648 | |
649 /****************************************************************************** | |
650 * The LZ decompression routine: * | |
651 * This version decompress the given gif file into Line of length LineLen. * | |
652 * This routine can be called few times (one per scan line, for example), in * | |
653 * order the complete the whole image. * | |
654 ******************************************************************************/ | |
655 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, | |
656 int LineLen) | |
657 { | |
658 int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; | |
659 GifByteType *Stack, *Suffix; | |
660 unsigned int *Prefix; | |
661 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
662 | |
663 StackPtr = Private->StackPtr; | |
664 Prefix = Private->Prefix; | |
665 Suffix = Private->Suffix; | |
666 Stack = Private->Stack; | |
667 EOFCode = Private->EOFCode; | |
668 ClearCode = Private->ClearCode; | |
669 LastCode = Private->LastCode; | |
670 | |
671 if (StackPtr != 0) { | |
672 /* Let pop the stack off before continueing to read the gif file: */ | |
673 while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr]; | |
674 } | |
675 | |
676 while (i < LineLen) { /* Decode LineLen items. */ | |
677 if (DGifDecompressInput(Private, &CrntCode) == GIF_ERROR) | |
678 return GIF_ERROR; | |
679 | |
680 if (CrntCode == EOFCode) { | |
681 /* Note however that usually we will not be here as we will stop */ | |
682 /* decoding as soon as we got all the pixel, or EOF code will */ | |
683 /* not be read at all, and DGifGetLine/Pixel clean everything. */ | |
684 if (i != LineLen - 1 || Private->PixelCount != 0) { | |
685 _GifError = D_GIF_ERR_EOF_TOO_SOON; | |
686 return GIF_ERROR; | |
687 } | |
688 i++; | |
689 } | |
690 else if (CrntCode == ClearCode) { | |
691 /* We need to start over again: */ | |
692 for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE; | |
693 Private->RunningCode = Private->EOFCode + 1; | |
694 Private->RunningBits = Private->BitsPerPixel + 1; | |
695 Private->MaxCode1 = 1 << Private->RunningBits; | |
696 LastCode = Private->LastCode = NO_SUCH_CODE; | |
697 } | |
698 else { | |
699 /* Its regular code - if in pixel range simply add it to output */ | |
700 /* stream, otherwise trace to codes linked list until the prefix */ | |
701 /* is in pixel range: */ | |
702 if (CrntCode < ClearCode) { | |
703 /* This is simple - its pixel scalar, so add it to output: */ | |
704 Line[i++] = CrntCode; | |
705 } | |
706 else { | |
707 /* Its a code to needed to be traced: trace the linked list */ | |
708 /* until the prefix is a pixel, while pushing the suffix */ | |
709 /* pixels on our stack. If we done, pop the stack in reverse */ | |
710 /* (thats what stack is good for!) order to output. */ | |
711 if (Prefix[CrntCode] == NO_SUCH_CODE) { | |
712 /* Only allowed if CrntCode is exactly the running code: */ | |
713 /* In that case CrntCode = XXXCode, CrntCode or the */ | |
714 /* prefix code is last code and the suffix char is */ | |
715 /* exactly the prefix of last code! */ | |
716 if (CrntCode == Private->RunningCode - 2) { | |
717 CrntPrefix = LastCode; | |
718 Suffix[Private->RunningCode - 2] = | |
719 Stack[StackPtr++] = DGifGetPrefixChar(Prefix, | |
720 LastCode, ClearCode); | |
721 } | |
722 else { | |
723 _GifError = D_GIF_ERR_IMAGE_DEFECT; | |
724 return GIF_ERROR; | |
725 } | |
726 } | |
727 else | |
728 CrntPrefix = CrntCode; | |
729 | |
730 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */ | |
731 /* During the trace. As we might loop forever, in case of */ | |
732 /* defective image, we count the number of loops we trace */ | |
733 /* and stop if we got LZ_MAX_CODE. obviously we can not */ | |
734 /* loop more than that. */ | |
735 j = 0; | |
736 while (j++ <= LZ_MAX_CODE && | |
737 CrntPrefix > ClearCode && | |
738 CrntPrefix <= LZ_MAX_CODE) { | |
739 Stack[StackPtr++] = Suffix[CrntPrefix]; | |
740 CrntPrefix = Prefix[CrntPrefix]; | |
741 } | |
742 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) { | |
743 _GifError = D_GIF_ERR_IMAGE_DEFECT; | |
744 return GIF_ERROR; | |
745 } | |
746 /* Push the last character on stack: */ | |
747 Stack[StackPtr++] = CrntPrefix; | |
748 | |
749 /* Now lets pop all the stack into output: */ | |
750 while (StackPtr != 0 && i < LineLen) | |
751 Line[i++] = Stack[--StackPtr]; | |
752 } | |
753 if (LastCode != NO_SUCH_CODE) { | |
754 Prefix[Private->RunningCode - 2] = LastCode; | |
755 | |
756 if (CrntCode == Private->RunningCode - 2) { | |
757 /* Only allowed if CrntCode is exactly the running code: */ | |
758 /* In that case CrntCode = XXXCode, CrntCode or the */ | |
759 /* prefix code is last code and the suffix char is */ | |
760 /* exactly the prefix of last code! */ | |
761 Suffix[Private->RunningCode - 2] = | |
762 DGifGetPrefixChar(Prefix, LastCode, ClearCode); | |
763 } | |
764 else { | |
765 Suffix[Private->RunningCode - 2] = | |
766 DGifGetPrefixChar(Prefix, CrntCode, ClearCode); | |
767 } | |
768 } | |
769 LastCode = CrntCode; | |
770 } | |
771 } | |
772 | |
773 Private->LastCode = LastCode; | |
774 Private->StackPtr = StackPtr; | |
775 | |
776 return GIF_OK; | |
777 } | |
778 | |
779 /****************************************************************************** | |
780 * Routine to trace the Prefixes linked list until we get a prefix which is * | |
781 * not code, but a pixel value (less than ClearCode). Returns that pixel value.* | |
782 * If image is defective, we might loop here forever, so we limit the loops to * | |
783 * the maximum possible if image O.k. - LZ_MAX_CODE times. * | |
784 ******************************************************************************/ | |
785 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode) | |
786 { | |
787 int i = 0; | |
788 | |
789 while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code]; | |
790 return Code; | |
791 } | |
792 | |
793 /****************************************************************************** | |
794 * Interface for accessing the LZ codes directly. Set Code to the real code * | |
795 * (12bits), or to -1 if EOF code is returned. * | |
796 ******************************************************************************/ | |
797 int DGifGetLZCodes(GifFileType *GifFile, int *Code) | |
798 { | |
799 GifByteType *CodeBlock; | |
800 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; | |
801 | |
802 if (!IS_READABLE(Private)) { | |
803 /* This file was NOT open for reading: */ | |
804 _GifError = D_GIF_ERR_NOT_READABLE; | |
805 return GIF_ERROR; | |
806 } | |
807 | |
808 if (DGifDecompressInput(Private, Code) == GIF_ERROR) | |
809 return GIF_ERROR; | |
810 | |
811 if (*Code == Private->EOFCode) { | |
812 /* Skip rest of codes (hopefully only NULL terminating block): */ | |
813 do if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) | |
814 return GIF_ERROR; | |
815 while (CodeBlock != NULL); | |
816 | |
817 *Code = -1; | |
818 } | |
819 else if (*Code == Private->ClearCode) { | |
820 /* We need to start over again: */ | |
821 Private->RunningCode = Private->EOFCode + 1; | |
822 Private->RunningBits = Private->BitsPerPixel + 1; | |
823 Private->MaxCode1 = 1 << Private->RunningBits; | |
824 } | |
825 | |
826 return GIF_OK; | |
827 } | |
828 | |
829 /****************************************************************************** | |
830 * The LZ decompression input routine: * | |
831 * This routine is responsable for the decompression of the bit stream from * | |
832 * 8 bits (bytes) packets, into the real codes. * | |
833 * Returns GIF_OK if read succesfully. * | |
834 ******************************************************************************/ | |
835 static int DGifDecompressInput(GifFilePrivateType *Private, int *Code) | |
836 { | |
837 GifByteType NextByte; | |
838 static unsigned int CodeMasks[] = { | |
839 0x0000, 0x0001, 0x0003, 0x0007, | |
840 0x000f, 0x001f, 0x003f, 0x007f, | |
841 0x00ff, 0x01ff, 0x03ff, 0x07ff, | |
842 0x0fff | |
843 }; | |
844 | |
845 while (Private->CrntShiftState < Private->RunningBits) { | |
846 /* Needs to get more bytes from input stream for next code: */ | |
847 if (DGifBufferedInput(Private->File, Private->Buf, &NextByte) | |
848 == GIF_ERROR) { | |
849 return GIF_ERROR; | |
850 } | |
851 Private->CrntShiftDWord |= | |
852 ((unsigned long) NextByte) << Private->CrntShiftState; | |
853 Private->CrntShiftState += 8; | |
854 } | |
855 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits]; | |
856 | |
857 Private->CrntShiftDWord >>= Private->RunningBits; | |
858 Private->CrntShiftState -= Private->RunningBits; | |
859 | |
860 /* If code cannt fit into RunningBits bits, must raise its size. Note */ | |
861 /* however that codes above 4095 are used for special signaling. */ | |
862 if (++Private->RunningCode > Private->MaxCode1 && | |
863 Private->RunningBits < LZ_BITS) { | |
864 Private->MaxCode1 <<= 1; | |
865 Private->RunningBits++; | |
866 } | |
867 return GIF_OK; | |
868 } | |
869 | |
870 /****************************************************************************** | |
871 * This routines read one gif data block at a time and buffers it internally * | |
872 * so that the decompression routine could access it. * | |
873 * The routine returns the next byte from its internal buffer (or read next * | |
874 * block in if buffer empty) and returns GIF_OK if succesful. * | |
875 ******************************************************************************/ | |
876 static int DGifBufferedInput(FILE *File, GifByteType *Buf, | |
877 GifByteType *NextByte) | |
878 { | |
879 if (Buf[0] == 0) { | |
880 /* Needs to read the next buffer - this one is empty: */ | |
881 if (fread(Buf, 1, 1, File) != 1) | |
882 { | |
883 _GifError = D_GIF_ERR_READ_FAILED; | |
884 return GIF_ERROR; | |
885 } | |
886 if (fread(&Buf[1], 1, Buf[0], File) != Buf[0]) | |
887 { | |
888 _GifError = D_GIF_ERR_READ_FAILED; | |
889 return GIF_ERROR; | |
890 } | |
891 *NextByte = Buf[1]; | |
892 Buf[1] = 2; /* We use now the second place as last char read! */ | |
893 Buf[0]--; | |
894 } | |
895 else { | |
896 *NextByte = Buf[Buf[1]++]; | |
897 Buf[0]--; | |
898 } | |
899 | |
900 return GIF_OK; | |
901 } | |
902 | |
903 /****************************************************************************** | |
904 * This routine reads an entire GIF into core, hanging all its state info off * | |
905 * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() * | |
906 * first to initialize I/O. Its inverse is EGifSpew(). * | |
907 ******************************************************************************/ | |
908 int DGifSlurp(GifFileType *GifFile) | |
909 { | |
910 #if 0 | |
911 int i, j, Error; | |
912 #endif /* 0 */ | |
913 int ImageSize; | |
914 GifRecordType RecordType; | |
915 SavedImage *sp; | |
916 ExtensionBlock *ep; | |
917 GifByteType *ExtData; | |
918 | |
919 /* Some versions of malloc dislike 0-length requests */ | |
920 GifFile->SavedImages = (SavedImage *)xmalloc(sizeof(SavedImage)); | |
921 | |
922 do { | |
923 if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) | |
924 return(GIF_ERROR); | |
925 | |
926 switch (RecordType) { | |
927 case IMAGE_DESC_RECORD_TYPE: | |
928 if (DGifGetImageDesc(GifFile) == GIF_ERROR) | |
929 return(GIF_ERROR); | |
930 | |
931 sp = &GifFile->SavedImages[GifFile->ImageCount-1]; | |
932 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; | |
933 | |
934 sp->RasterBits | |
935 = (GifPixelType*) xmalloc(ImageSize * sizeof(GifPixelType)); | |
936 | |
937 if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) | |
938 == GIF_ERROR) | |
939 return(GIF_ERROR); | |
940 | |
941 break; | |
942 | |
943 case EXTENSION_RECORD_TYPE: | |
944 | |
945 if (DGifGetExtension(GifFile,&sp->Function,&ExtData)==GIF_ERROR) | |
946 return(GIF_ERROR); | |
947 else | |
948 { | |
949 ep = &sp->ExtensionBlocks[sp->ExtensionBlockCount++]; | |
950 | |
951 ep->ByteCount = ExtData[0]; | |
952 ep->Bytes = (GifByteType *)xmalloc(ep->ByteCount * sizeof(GifByteType)); | |
953 memcpy(ep->Bytes, ExtData, ep->ByteCount * sizeof(char)); | |
954 } | |
955 | |
956 while (ExtData != NULL) { | |
957 if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) | |
958 return(GIF_ERROR); | |
959 else | |
960 { | |
961 ep = &sp->ExtensionBlocks[sp->ExtensionBlockCount++]; | |
962 | |
963 ep->ByteCount = ExtData[0]; | |
964 ep->Bytes = (GifByteType *)xmalloc(ep->ByteCount * sizeof(GifByteType)); | |
965 memcpy(ep->Bytes,ExtData,ep->ByteCount * sizeof(char)); | |
966 } | |
967 } | |
968 break; | |
969 | |
970 case TERMINATE_RECORD_TYPE: | |
971 break; | |
972 | |
973 default: /* Should be trapped by DGifGetRecordType */ | |
974 break; | |
975 } | |
976 } | |
977 while | |
978 (RecordType != TERMINATE_RECORD_TYPE); | |
979 | |
980 return(GIF_OK); | |
981 } | |
982 |