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