1 /***************************************************/
2 /* Unit GIF : contains procedure to write and load */
3 /*            conpressed gif image.                */
4 /*            Use an ultra fast compression method */
5 /***************************************************/
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <memory.h>
9 #include <string.h>
10 #include "gif.h"
11 
12 #define MAX_GIF_SIZE  1048576    /* Max of comprimed data */
13 #define GIF_SEPARATOR ','
14 #define GIF_EXTENDED  '!'
15 
16 /***************************************************************/
17 
18 FILE *GIF_FILE;
19 static unsigned int GIF_WIDTH;
20 static unsigned int GIF_HEIGHT;
21 static unsigned int GIF_BYTES_PER_PIXEL;
22 static unsigned int GIF_DATA_RESOLUTION;
23 static unsigned int GIF_BACK;
24 static          int GIF_TRANSPARENT;
25 static unsigned int GIF_FORMAT;
26 unsigned char GIF_RCOLORMAP[256];
27 unsigned char GIF_GCOLORMAP[256];
28 unsigned char GIF_BCOLORMAP[256];
29 static unsigned char *GIF_BUFFER=NULL;
30 
31 char GifErrorMessage[1024];
32 
33 #ifdef WITH_COMP
34 short GIF_REL[4096][256];
35 #endif
36 
37 /***************** Variables used by GetCode *******************/
38 
39 static unsigned int	  POS_CODE;
40 static unsigned long  MASK_CODE;
41 static unsigned int   SIZE_CODE;
42 static unsigned long  WORK_CODE;
43 static unsigned int	  WORK_CODE_SIZE;
44 
45 /******************Vars of the analyseur ***********************/
46 
47 static unsigned int EOF_CODE;
48 static unsigned int CLR_CODE;
49 static unsigned short NULL_CODE=0xFFFF;
50 
51 /*****************Vars for table********************************/
52 static unsigned int TABLE_SIZE;
53 static int Prefix[4096];
54 static int Values[4096];
55 static int Length[4096];
56 
57 static int buf_size=0;
58 static int Len=0;
59 static char *TheImage;
60 
61 /************************************************************/
62 /* InitTable() : Initialise table string                    */
63 /************************************************************/
InitTable()64 void InitTable() {
65 int i;
66   for(i=0;i<4096;i++) {
67     Prefix[i]=NULL_CODE;
68 	Values[i]=i;
69 	Length[i]=1;
70   }
71 }
72 
73 
74 /***************************************************************/
75 /* ReadGifHeader : Read gif header                             */
76 /***************************************************************/
ReadGifHeader()77 int ReadGifHeader()
78 {
79   char tmp[128];
80   unsigned int lng;
81   unsigned long lue;
82   unsigned short c16;
83   unsigned char  c8;
84   int i;
85   int eof_extension;
86   int bc;
87   int cmd_code;
88 
89   lng=6;
90 
91   /************************ Signature *************************/
92 
93   lue = (unsigned long)fread(tmp, 1, lng, GIF_FILE);
94   if(lue!=lng) return 0;
95   tmp[3]=0;
96   if(strcmp(tmp,"GIF")!=0)
97   {
98     strcat(GifErrorMessage,"Bad gif signature.\n");
99     return 0;
100   }
101 
102   /************************ Screen descriptor ****************/
103 
104   lng=sizeof(short);
105   lue = (unsigned long)fread(&c16, 1, lng, GIF_FILE);
106   if(lue!=lng) return 0;
107 
108   lng=sizeof(short);
109   lue = (unsigned long)fread(&c16, 1, lng, GIF_FILE);
110   if(lue!=lng) return 0;
111 
112   lng=sizeof(char);
113   lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
114   if(lue!=lng) return 0;
115   GIF_BYTES_PER_PIXEL=(c8 & 0x07)+1;
116   GIF_DATA_RESOLUTION=((c8 & 0x70)>>3)+1;
117 
118   lng=sizeof(char);
119   lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
120   if(lue!=lng) return 0;
121   GIF_BACK=(int)c8;
122 
123   lng=sizeof(char);
124   lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
125   if(lue!=lng) return 0;
126 
127   /*********************** Global color map ****************/
128 
129   for(i=0;i<(1 << GIF_BYTES_PER_PIXEL);i++)
130   {
131 
132     lng=sizeof(char);
133 
134 	lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
135     if(lue!=lng) return 0;
136     GIF_RCOLORMAP[i]=c8;
137 
138 	lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
139     if(lue!=lng) return 0;
140     GIF_GCOLORMAP[i]=c8;
141 
142 	lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
143     if(lue!=lng) return 0;
144     GIF_BCOLORMAP[i]=c8;
145 
146   }
147 
148   /**************************** Extended function ***************/
149 
150   eof_extension=0;
151 
152   while(!eof_extension)
153   {
154 	  lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
155       if(lue!=lng) return 0;
156 
157     switch(c8) {
158       case GIF_SEPARATOR:
159 	   eof_extension=1;
160            break;
161 
162       case GIF_EXTENDED:
163 
164 		    lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
165            if(lue!=lng) return 0;
166 	   cmd_code=(int)c8;
167 
168 	   do {
169 		     lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
170              if(lue!=lng) return 0;
171 	     bc=(int)c8;
172 
173 	     for(i=0;i<bc;i++) {
174 			   lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
175                if(lue!=lng) return 0;
176 	     }
177 
178 	     if(cmd_code==249) {
179 	       GIF_TRANSPARENT=(int)c8;
180 	       cmd_code=-1;
181 	     }
182 
183 	   } while(bc!=0);
184 
185            break;
186 
187       default:
188            strcat(GifErrorMessage,"Unexcepted extension code in gif file.\n");
189            return 0;
190 	   break;
191     }
192   }
193 
194 
195   /**************************** First image descriptor **********/
196 
197 
198   lng=sizeof(short);
199   lue = (unsigned long)fread(&c16, 1, lng, GIF_FILE);
200   if(lue!=lng) return 0;
201 
202   lue = (unsigned long)fread(&c16, 1, lng, GIF_FILE);
203   if(lue!=lng) return 0;
204 
205 
206   lue = (unsigned long)fread(&c16, 1, lng, GIF_FILE);
207   if(lue!=lng) return 0;
208   GIF_WIDTH=c16;
209 
210   lue = (unsigned long)fread(&c16, 1, lng, GIF_FILE);
211   if(lue!=lng) return 0;
212   GIF_HEIGHT=c16;
213 
214 
215   lng=sizeof(char);
216   lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
217   if(lue!=lng) return 0;
218 
219   if(c8 & 0x40)
220      GIF_FORMAT=INTERLACED_FORMAT;
221   else
222      GIF_FORMAT=CONTINOUS_FORMAT;
223 
224   SIZE_CODE=GIF_BYTES_PER_PIXEL+1;
225   WORK_CODE_SIZE=0;
226   WORK_CODE=0;
227   MASK_CODE=((1 << SIZE_CODE)-1);
228   CLR_CODE=1 << GIF_BYTES_PER_PIXEL;
229   EOF_CODE=CLR_CODE+1;
230   TABLE_SIZE = EOF_CODE + 1;
231   POS_CODE=0;
232 
233   InitTable();
234 
235   /******************* Jump code size **********/
236   /************* Supposed equal to 8 ***********/
237 
238   lng=sizeof(char);
239   lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
240   if(lue!=lng) return 0;
241 
242   return 1;
243 }
244 
245 
246 /*************************************************************/
247 /* InitBlocks() : initialise a raster data block             */
248 /*************************************************************/
InitBlocks()249 int InitBlocks() {
250 unsigned long lue,lng;
251 unsigned char c8=1;
252 int cnt=0;
253 
254 while(c8!=0) {
255   lng=sizeof(char);
256   lue = (unsigned long)fread(&c8, 1, lng, GIF_FILE);
257   if(lue!=lng) return 0;
258 
259   if(buf_size+c8>MAX_GIF_SIZE) {
260     strcat(GifErrorMessage,"GIF file too long.\n");
261     return 0;
262   }
263 
264   if(c8>0) {
265     cnt++;
266     lng=c8;
267 	lue = (unsigned long)fread(&GIF_BUFFER[buf_size], 1, lng, GIF_FILE);
268     if(lue!=lng) return 0;
269     buf_size+=lng;
270   }
271 }
272 
273 
274 return 1;
275 }
276 
277 /************************************************************/
278 /* GetCode():return the current code                        */
279 /************************************************************/
GetCode()280 int GetCode()
281 {
282   int   ret;
283 
284   while(WORK_CODE_SIZE<SIZE_CODE)
285   {
286     WORK_CODE |= ((long)(GIF_BUFFER[POS_CODE]) << WORK_CODE_SIZE);
287     POS_CODE++;
288     WORK_CODE_SIZE+=8;
289   }
290 
291   ret=WORK_CODE & MASK_CODE;
292   WORK_CODE>>=SIZE_CODE;
293   WORK_CODE_SIZE-=SIZE_CODE;
294   return ret;
295 }
296 
297 /************************************************************/
298 /* Output(): print the string for code and return the first */
299 /*           code                                           */
300 /************************************************************/
Output(int code)301 int Output(int code) {
302 
303   int i;
304   int l;
305   int r;
306 
307   l=Length[code];
308 
309   for(i=l-1;i>=0;i--) {
310     TheImage[Len+i]=Values[code];
311     code=Prefix[code];
312   }
313 
314   r=TheImage[Len];
315   Len+=l;
316   return r;
317 }
318 
319 
320 
321 /************************************************************/
322 /* AddString() add a string into the string table.          */
323 /************************************************************/
324 
Add_String(int p,int v)325 void Add_String(int p,int v) {
326   Prefix[TABLE_SIZE]=p;
327   Values[TABLE_SIZE]=v;
328   Length[TABLE_SIZE]=Length[p]+1;
329 
330   if( (TABLE_SIZE == MASK_CODE ) && (SIZE_CODE<12))
331   {
332     SIZE_CODE++;
333     MASK_CODE=((1 << SIZE_CODE)-1);
334   }
335 
336   TABLE_SIZE++;
337 }
338 
339 
340 
341 /************************************************************/
342 /* ReadRasterData : ReadFile the compressed data            */
343 /************************************************************/
ReadRasterData()344 int ReadRasterData()
345 {
346   unsigned int code;
347   int prev_code=NULL_CODE;
348   int first;
349 
350   /*************** Read all gif blocks in memory ******/
351   if(!InitBlocks()) return 0;
352 
353   /*************** Initialise analyseur ***************/
354 
355   code=GetCode();
356   if(code==CLR_CODE) code=GetCode();
357   Output(code);
358   prev_code=code;
359 
360   /*************** Start decompression ***************/
361 
362   while(code!=EOF_CODE)
363   {
364   code=GetCode();
365 
366   /******************** Treat sepcial gif code *******/
367 
368   if( code==CLR_CODE || code==EOF_CODE) {
369     SIZE_CODE=GIF_BYTES_PER_PIXEL+1;
370     MASK_CODE=((1 << SIZE_CODE)-1);
371     TABLE_SIZE = EOF_CODE + 1;
372 
373     if(code==CLR_CODE) {
374       code=GetCode();
375       Output(code);
376       prev_code=code;
377     }
378 
379   } else
380 
381   /********************** LZW code *******************/
382 
383     if( code < TABLE_SIZE ) {
384       first=Output(code);
385       Add_String(prev_code,first);
386       prev_code=code;
387     } else {
388       first=Output(prev_code);
389       TheImage[Len++]=first;
390       Add_String(prev_code,first);
391       prev_code=code;
392     }
393 
394  }
395 
396  return 1;
397 }
398 
399 /***********************************************************/
400 /* LoadGifImage : Load a gif file and return uncompressed  */
401 /*                data (malloc)                            */
402 /*                GIF_IMAGE *descr - GIF_FILE descriptor   */
403 /*                return 0 when fail                       */
404 /***********************************************************/
LoadGifImage(GIF_IMAGE * descr)405 int LoadGifImage(GIF_IMAGE *descr)
406 {
407   int i,j;
408 
409   unsigned long TblCol[256];
410   int trouve;
411   unsigned long current;
412   char *tmp_img;
413   int addd,adds;
414 
415   /* Initialise default values */
416   if(!GIF_BUFFER) GIF_BUFFER = (unsigned char *)malloc(MAX_GIF_SIZE);
417   Len=0;
418   buf_size=0;
419   GifErrorMessage[0]='\0';
420 
421   for(i=0;i<256;i++)
422   {
423     descr->Red[i]=-1;
424     descr->Green[i]=-1;
425     descr->Blue[i]=-1;
426     GIF_TRANSPARENT=-1;
427   }
428   GIF_FORMAT=CONTINOUS_FORMAT;
429 
430   /* Open file for Reading */
431 
432   GIF_FILE=fopen(descr->FileName,"rb");
433 
434   if (GIF_FILE==NULL)
435   {
436     sprintf(GifErrorMessage,"Unable to open file.\n%s",descr->FileName);
437     descr->data=NULL;
438     descr->width=0;
439     descr->height=0;
440     return 0;
441   }
442 
443   /* Read the header */
444 
445  if(!ReadGifHeader())  {
446     strcat(GifErrorMessage,"Error occurs during reading gif header.");
447     descr->data=NULL;
448     descr->width=0;
449     descr->height=0;
450     return 0;
451   }
452 
453   /* Update descritpor */
454 
455   descr->data=(char *)malloc(GIF_WIDTH*GIF_HEIGHT);
456   if( descr->data == NULL ) {
457     strcat(GifErrorMessage,"Not enough memory to read GIF.");
458     descr->width=0;
459     descr->height=0;
460     return 0;
461   }
462 
463   TheImage=descr->data;
464   descr->width=GIF_WIDTH;
465   descr->height=GIF_HEIGHT;
466   descr->background=GIF_BACK;
467   descr->pixel=GIF_BYTES_PER_PIXEL;
468   descr->transparent=GIF_TRANSPARENT;
469 
470   for(i=0;i<(1 << GIF_BYTES_PER_PIXEL);i++) {
471     descr->Red[i]  =GIF_RCOLORMAP[i];
472     descr->Green[i]=GIF_GCOLORMAP[i];
473     descr->Blue[i] =GIF_BCOLORMAP[i];
474   }
475 
476   descr->format=GIF_FORMAT;
477 
478   /* Unpacked comprimed blocks */
479 
480   if(!ReadRasterData()) {
481     strcat(GifErrorMessage,"Error occurs during reading raster data.\n");
482     free(descr->data);
483     descr->data=NULL;
484     descr->width=0;
485     descr->height=0;
486     return 0;
487   }
488 
489   /* Regenerate picture when interlaced format */
490 
491   if(descr->format==INTERLACED_FORMAT) {
492 
493     tmp_img=(char *)malloc(GIF_WIDTH*GIF_HEIGHT);
494 	if( tmp_img == NULL ) {
495       strcat(GifErrorMessage,"Not enough memory to read interlaced GIF.");
496       free(descr->data);
497       descr->data=NULL;
498       descr->width=0;
499       descr->height=0;
500       return 0;
501 	}
502     memcpy(tmp_img,TheImage,GIF_WIDTH*GIF_HEIGHT);
503 
504     /* Fisrt passe */
505 
506     for(j=0,i=0;i<(int)GIF_HEIGHT;i+=8,j++) {
507       adds=(j*GIF_WIDTH);
508       addd=(i*GIF_WIDTH);
509       memcpy(&TheImage[addd],&tmp_img[adds],GIF_WIDTH);
510     }
511 
512     /* Second passe */
513 
514     for(i=4;i<(int)GIF_HEIGHT;i+=8,j++) {
515       adds=(j*GIF_WIDTH);
516       addd=(i*GIF_WIDTH);
517       memcpy(&TheImage[addd],&tmp_img[adds],GIF_WIDTH);
518     }
519 
520     /* Third passe */
521 
522     for(i=2;i<(int)GIF_HEIGHT;i+=4,j++) {
523       adds=(j*GIF_WIDTH);
524       addd=(i*GIF_WIDTH);
525       memcpy(&TheImage[addd],&tmp_img[adds],GIF_WIDTH);
526     }
527 
528     /* Fourth passe */
529 
530     for(i=1;i<(int)GIF_HEIGHT;i+=2,j++) {
531       adds=(j*GIF_WIDTH);
532       addd=(i*GIF_WIDTH);
533       memcpy(&TheImage[addd],&tmp_img[adds],GIF_WIDTH);
534     }
535 
536     free(tmp_img);
537 
538 
539   }
540 
541   /* Compute Used color */
542   j=GIF_WIDTH*GIF_HEIGHT;
543   for(i=0;i<256;i++) descr->Used[i]=0;
544   for(i=0;i<j;i++) descr->Used[(unsigned char)TheImage[i]]++;
545 
546   /* Compute Unique color */
547 
548   descr->used_color=0;
549   descr->unique_color=0;
550 
551   for(i=0;i<256;i++)
552     if(descr->Used[i]>0) {
553       descr->used_color++;
554       trouve=0;
555       j=0;
556       current= GIF_RCOLORMAP[i] +
557 	      (((long)GIF_GCOLORMAP[i]) << 8) +
558 	      (((long)GIF_BCOLORMAP[i]) << 16);
559 
560       while( j<descr->unique_color && !trouve )
561       {
562 	    trouve=(current==TblCol[j]);
563 	    if(!trouve) j++;
564       }
565 
566       if(!trouve) {
567 	TblCol[j]=current;
568 	descr->unique_color++;
569       }
570     }
571 
572 
573   fclose(GIF_FILE);
574   return -1;
575 }
576 
577 /************************************************************/
578 /* ComupteUsedColor() : Compute .Used et .unique field      */
579 /************************************************************/
ComputeUsedColor(GIF_IMAGE * descr)580 void ComputeUsedColor(GIF_IMAGE *descr) {
581   int i,j;
582   unsigned long TblCol[256];
583   int trouve;
584   unsigned long current;
585 
586 
587   /* Compute Used color */
588   j=descr->width*descr->height;
589   for(i=0;i<256;i++) descr->Used[i]=0;
590   for(i=0;i<j;i++) descr->Used[(unsigned char)(descr->data[i])]++;
591 
592   /* Compute Unique color */
593 
594   descr->used_color=0;
595   descr->unique_color=0;
596 
597   for(i=0;i<256;i++)
598     if(descr->Used[i]>0) {
599       descr->used_color++;
600       trouve=0;
601       j=0;
602       current= descr->Red[i] +
603 	      (((long)descr->Green[i]) << 8) +
604 	      (((long)descr->Blue[i]) << 16);
605 
606       while( j<descr->unique_color && !trouve )
607       {
608 	trouve=(current==TblCol[j]);
609 	if(!trouve) j++;
610       }
611 
612       if(!trouve) {
613 	TblCol[j]=current;
614 	descr->unique_color++;
615       }
616     }
617 
618 }
619 
620 /*************************************************************/
621 /* Compression Part                                          */
622 /*************************************************************/
623 #ifdef WITH_COMP
624 
Add_String2(int p,int v)625 void Add_String2(int p,int v) {
626 
627   GIF_REL[p][v]=TABLE_SIZE;
628 
629   if( (TABLE_SIZE == (MASK_CODE+1) ) && (SIZE_CODE<12))
630   {
631     SIZE_CODE++;
632     MASK_CODE=((1 << SIZE_CODE)-1);
633   }
634 
635   TABLE_SIZE++;
636 }
637 
InitGifRelation()638 void InitGifRelation() {
639   memset( GIF_REL , NULL_CODE , 4096*512 );
640 }
641 
PutCode(int code)642 void PutCode(int code)
643 {
644 	WORK_CODE |= (long)code << WORK_CODE_SIZE;
645 	WORK_CODE_SIZE+=SIZE_CODE;
646 
647 	while( WORK_CODE_SIZE >= 8 ) {
648 
649 		GIF_BUFFER[POS_CODE]=(unsigned char)(WORK_CODE & 0x000000FF);
650 		WORK_CODE >>= 8;
651 		WORK_CODE_SIZE -=8;
652 		POS_CODE++;
653 	}
654 }
655 
IsInTheStringTable(unsigned int p,unsigned int c,unsigned int * ind)656 int IsInTheStringTable( unsigned int p,unsigned int c,unsigned int *ind)
657 {
658   int trouve;
659   trouve=0;
660 
661   if(p==NULL_CODE) {
662     *ind=c;
663     return 1;
664   } else {
665     *ind=(int)GIF_REL[p][c];
666     return (*ind!=NULL_CODE);
667   }
668 
669 }
670 
671 
672 
673 /************************************************************/
ComprimeData(int size_src,char * source,int * size_dest)674 void ComprimeData(int size_src   ,char *source,
675 		 int *size_dest )
676 {
677  unsigned int prev_code;
678  unsigned int code;
679  unsigned int indice;
680 
681   Len=0;
682   GIF_BYTES_PER_PIXEL=8;
683   SIZE_CODE=9;
684   WORK_CODE_SIZE=0;
685   WORK_CODE=0;
686   MASK_CODE=((1 << SIZE_CODE)-1);
687   CLR_CODE=1 << GIF_BYTES_PER_PIXEL;
688   EOF_CODE=CLR_CODE+1;
689   TABLE_SIZE = EOF_CODE + 1;
690   POS_CODE=0;
691 
692 
693   InitGifRelation();
694   prev_code=NULL_CODE;
695   PutCode(CLR_CODE);
696 
697   while( Len<size_src ) {
698 
699     code=(unsigned char)source[Len++];
700 
701     if(IsInTheStringTable(prev_code,code,&indice)) {
702       prev_code=indice;
703     } else {
704       PutCode(prev_code);
705 
706       if( TABLE_SIZE == 4096 ) {
707 	PutCode(CLR_CODE);
708 	SIZE_CODE=9;
709         MASK_CODE=((1 << SIZE_CODE)-1);
710         TABLE_SIZE = EOF_CODE + 1;
711         InitGifRelation();
712       } else
713         Add_String2(prev_code,code);
714 
715       prev_code=code;
716 
717     }
718 
719   }
720 
721   PutCode(prev_code);
722   PutCode(EOF_CODE);
723 
724   /* Flush the buffer */
725 
726   while( WORK_CODE_SIZE > 0 ) {
727 	GIF_BUFFER[POS_CODE]=(unsigned char)(WORK_CODE & 0x000000FF);
728 	WORK_CODE >>= 8;
729 	WORK_CODE_SIZE -=8;
730 	POS_CODE++;
731   }
732 
733 
734   *size_dest=POS_CODE;
735 }
736 
737 
738 
739 /***********************************************************/
740 /* WriteGifHeader : Write a gif header.                    */
741 /*                GIF_IMAGE descr - GIF_FILE descriptor    */
742 /*                return 0 when fail                       */
743 /***********************************************************/
WriteGifHeader(GIF_IMAGE descr)744 int WriteGifHeader(GIF_IMAGE descr) {
745 
746 int i;
747 unsigned long wrt,lng;
748 unsigned short c16;
749 unsigned char  c8;
750 char tmp[100];
751 
752   /************************ Signature *************************/
753 
754   sprintf(tmp,"GIF89a");
755   lng=6;
756   WriteFile(GIF_FILE,tmp,lng,&wrt,NULL);
757   if(wrt!=lng) return 0;
758 
759   /************************ Screen descriptor ****************/
760 
761   lng=sizeof(short);
762   c16=(unsigned short)descr.width;
763   WriteFile(GIF_FILE,&c16,lng,&wrt,NULL);
764   if(wrt!=lng) return 0;
765 
766   lng=sizeof(short);
767   c16=(unsigned short)descr.height;
768   WriteFile(GIF_FILE,&c16,lng,&wrt,NULL);
769   if(wrt!=lng) return 0;
770 
771   lng=sizeof(char);
772   c8=0xF7;
773   WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
774   if(wrt!=lng) return 0;
775 
776   lng=sizeof(char);
777   c8=descr.background;
778   WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
779   if(wrt!=lng) return 0;
780 
781   lng=sizeof(char);
782   c8=0;
783   WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
784   if(wrt!=lng) return 0;
785 
786   /********************************** global ColorMap ****************/
787 
788   lng=sizeof(char);
789   for(i=0;i<256;i++)
790   {
791     c8=(unsigned char)descr.Red[i];
792     WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
793     if(wrt!=lng) return 0;
794 
795     c8=(unsigned char)descr.Green[i];
796     WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
797     if(wrt!=lng) return 0;
798 
799     c8=(unsigned char)descr.Blue[i];
800     WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
801     if(wrt!=lng) return 0;
802 
803   }
804 
805   /********************************** Extension blocks **************/
806 
807   if(descr.transparent>=0) {
808 
809     c8=GIF_EXTENDED;
810     WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
811     if(wrt!=lng) return 0;
812     c8=249;
813     WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
814     if(wrt!=lng) return 0;
815     c8=4;
816     WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
817     if(wrt!=lng) return 0;
818     c8=1;
819     WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
820     if(wrt!=lng) return 0;
821     c8=0;
822     WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
823     if(wrt!=lng) return 0;
824     c8=0;
825     WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
826     if(wrt!=lng) return 0;
827     c8=(unsigned char)descr.transparent;
828     WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
829     if(wrt!=lng) return 0;
830     c8=0;
831     WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
832     if(wrt!=lng) return 0;
833 
834   }
835 
836   /************************************* Image descriptor ************/
837 
838   c8=GIF_SEPARATOR;
839   WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
840   if(wrt!=lng) return 0;
841 
842   lng=sizeof(short);
843 
844   c16=0;
845   WriteFile(GIF_FILE,&c16,lng,&wrt,NULL);
846   if(wrt!=lng) return 0;
847 
848   WriteFile(GIF_FILE,&c16,lng,&wrt,NULL);
849   if(wrt!=lng) return 0;
850 
851   c16=(unsigned short)descr.width;
852   WriteFile(GIF_FILE,&c16,lng,&wrt,NULL);
853   if(wrt!=lng) return 0;
854 
855   c16=(unsigned short)descr.height;
856   WriteFile(GIF_FILE,&c16,lng,&wrt,NULL);
857   if(wrt!=lng) return 0;
858 
859   c8=(descr.pixel-1);
860 
861   lng=sizeof(char);
862   WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
863   if(wrt!=lng) return 0;
864 
865   return 1;
866 }
867 
868 /***********************************************************/
869 /* WriteBloks : Write blocks into file.                    */
870 /*              int pack_size : lenght of buffer to write  */
871 /*                return 0 when fail                       */
872 /***********************************************************/
WriteBlocks(int pack_size)873 int WriteBlocks(int pack_size) {
874 
875   int p_buf;
876   unsigned char c8;
877   unsigned long wrt,lng;
878   int fin=0;
879 
880   /************* Write size code *********/
881 
882   lng=sizeof(char);
883   c8=8;
884   WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
885   if(wrt!=lng) return 0;
886   p_buf=0;
887 
888   while(!fin) {
889 
890     if( pack_size-p_buf >= 255 ) {
891 
892       lng=sizeof(char);
893       c8=255;
894       WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
895       if(wrt!=lng) return 0;
896 
897       lng=255;
898       WriteFile(GIF_FILE,&(GIF_BUFFER[p_buf]),lng,&wrt,NULL);
899       if(wrt!=lng) return 0;
900       p_buf+=255;
901 
902     } else {
903 
904       c8=(unsigned char)(pack_size-p_buf);
905 
906       if(c8>0) {
907         lng=sizeof(char);
908         WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
909         if(wrt!=lng) return 0;
910 
911         lng=c8;
912         WriteFile(GIF_FILE,&(GIF_BUFFER[p_buf]),lng,&wrt,NULL);
913         if(wrt!=lng) return 0;
914       }
915 
916       lng=sizeof(char);
917       c8=0;
918       WriteFile(GIF_FILE,&c8,lng,&wrt,NULL);
919       if(wrt!=lng) return 0;
920       fin=1;
921     }
922   }
923 
924   return 1;
925 }
926 
927 
928 /***********************************************************/
929 /* SaveGifImage : Save a gif file.                         */
930 /*                GIF_IMAGE descr - GIF_FILE descriptor    */
931 /*                return 0 when fail                       */
932 /***********************************************************/
SaveGifImage(GIF_IMAGE descr)933 int SaveGifImage(GIF_IMAGE descr)
934 {
935   int packed_size;
936 
937   /* Init default */
938 
939   if(!GIF_BUFFER) GIF_BUFFER = (unsigned char *)malloc(MAX_GIF_SIZE);
940   GifErrorMessage[0]='\0';
941 
942   if (descr.width==0 || descr.height==0)
943   {
944     strcat(GifErrorMessage,"No picture to save.\n");
945     return 0;
946   }
947 
948   /* Open file for writing */
949 
950   GIF_FILE=CreateFile(descr.FileName,
951 		              GENERIC_WRITE,
952 					  0,
953 					  NULL,
954 					  CREATE_ALWAYS,
955 					  FILE_ATTRIBUTE_NORMAL,
956 					  NULL);
957 
958 
959   if (GIF_FILE==INVALID_HANDLE_VALUE)
960   {
961     strcat(GifErrorMessage,"Unable to open file for writing.");
962     return 0;
963   }
964 
965   /* Write Gif header */
966 
967   if(WriteGifHeader(descr)==0) {
968     strcat(GifErrorMessage,"Error when writing gif header.");
969     return 0;
970   }
971 
972   /* Comprime data */
973 
974   ComprimeData ( descr.width*descr.height , descr.data , &packed_size );
975 
976   /* Write into Blocks */
977 
978   if(WriteBlocks(packed_size)==0) {
979     strcat(GifErrorMessage,"Error when writing gif blocks.");
980     return 0;
981   }
982 
983   CloseHandle(GIF_FILE);
984   return -1;
985 }
986 
987 #endif /* WITH_COMP */
988