Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

whirlgif.c

Go to the documentation of this file.
00001   
00002 /*
00003  * whirlgif.c
00004  *
00005  * Copyright (C) 1995,1996 by Kevin Kadow (kadokev@msg.net)
00006  * 
00007  * Based on txtmerge.c
00008  * Copyright (C) 1990,1991,1992,1993 by Mark Podlipec. 
00009  * All rights reserved.
00010  *
00011  * This software may be freely copied, modified and redistributed
00012  * without fee provided that this copyright notice is preserved 
00013  * intact on all copies and modified copies.
00014  * 
00015  * There is no warranty or other guarantee of fitness of this software.
00016  * It is provided solely "as is". The author(s) disclaim(s) all
00017  * responsibility and liability with respect to this software's usage
00018  * or its effect upon hardware or computer systems.
00019  *
00020  */
00021  /*
00022   * Description:
00023   *
00024   * This program reads in a sequence of single-image GIF format files and
00025   * outputs a single multi-image GIF file, suitable for use as an animation.
00026   *
00027   * TODO:
00028   *
00029   * More options for dealing with the colormap
00030   *
00031   * Eventually, I'd like to have this program compare the current image
00032   * with the previous image and check to see if only a small section of
00033   * the screen changed from the previous image. Worth a shot.
00034   */
00035 
00036  /*
00037   * Rev 2.00    05Feb96 Kevin Kadow
00038   *     transparency, gif comments,
00039   * Rev 1.10    29Jan96 Kevin Kadow
00040   *     first release of whirlgif
00041   *
00042   * txtmerge:
00043   * Rev 1.00    23Jul91 Mark Podlipec
00044   *     creation
00045   * Rev 1.01    08Jan92 Mark Podlipec
00046   *     use all colormaps, not just 1st.
00047   *
00048   * 
00049   */
00050 #define DA_REV 1.00
00051 
00052 #include "whirlgif.h"
00053 #include <stdlib.h>
00054 #include <string.h>
00055 
00056 #define MAXVAL  4100            /* maxval of lzw coding size */
00057 #define MAXVALP 4200
00058 
00059 /*
00060  * Set some defaults, these can be changed on the command line
00061  */
00062 unsigned int loop=DEFAULT_LOOP,loopcount=0,
00063         use_colormap=DEFAULT_USE_COLORMAP,
00064         debug_flag=0,
00065         verbose=0;
00066 
00067 int imagex = 0;
00068 int imagey = 0;
00069 int imagec = 0;
00070 
00071 /* global settings for offset, transparency */
00072 Global global;
00073 
00074 GIF_Color gif_cmap[256];
00075 
00076 ULONG GIF_Get_Code();
00077 void GIF_Decompress();
00078 void GIF_Get_Next_Entry();
00079 void GIF_Add_To_Table();
00080 void GIF_Send_Data();
00081 void GIF_Clear_Table();
00082 void GIF_Screen_Header();
00083 void GIF_Image_Header();
00084 void GIF_Read_File();
00085 void GIF_Comment();
00086 void GIF_Loop();
00087 void GIF_GCL();
00088 void Calc_Trans();
00089 void set_offset();
00090 
00091 GIF_Screen_Hdr gifscrn;
00092 GIF_Image_Hdr gifimage;
00093 GIF_Table table[MAXVALP];
00094 
00095 ULONG root_code_size,code_size,CLEAR,EOI,INCSIZE;
00096 ULONG nextab;
00097 ULONG gif_mask[16] = {1,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,0,0};
00098 ULONG gif_ptwo[16] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,0,0};
00099 
00100 
00101 UBYTE gif_buff[MAXVALP];
00102 ULONG gif_block_size;
00103 int num_bits,bits;
00104 
00105 int pic_i;
00106 char gif_file_name[BIGSTRING];
00107 int screen_was_last;
00108 
00109 
00110 void TheEnd()
00111 {
00112  exit(0);
00113 }
00114 
00115 void TheEnd1(p)
00116 char *p;
00117 {
00118  fprintf(stderr,"%s",p);
00119  TheEnd();
00120 }
00121 
00122 Usage()
00123 {
00124   fprintf(stderr,"\nUsage: whirlgif [-o outfile] [-loop [count]] [-time #delay]\n");
00125   fprintf(stderr,"\t[ -i listfile] file1 [ -time #delay] file2 ...\n");
00126   fprintf(stderr,"\nTry whirlgif -help for more information\n") ;
00127   exit(0);
00128 }
00129 
00130 main(argc,argv)
00131 int argc;
00132 char *argv[];
00133 {
00134  FILE * infile, *fout;
00135  char temp[BIGSTRING];
00136  int ret,i;
00137  int count=0;
00138 
00139  fprintf(stderr,"whirlgif Rev %2.2f (C) 1996 by Kevin Kadow\n",DA_REV);
00140  fprintf(stderr,"                  (C) 1991,1992 by Mark Podlipec\n");
00141  
00142  if (argc < 2) Usage();
00143  
00144  /* set global values */
00145  screen_was_last = FALSE;
00146  global.trans.type=TRANS_NONE;
00147  global.trans.valid=FALSE;
00148  global.time=DEFAULT_TIME;
00149  global.left=0;
00150  global.top=0;
00151 
00152 
00153  fout=stdout;
00154  i = 1;
00155  while( i < argc)
00156  {
00157   char *p;
00158   p = argv[i];
00159   /*fprintf(stderr,"Option: %s\n",p);*/
00160   if ( (p[0] == '-') || (p[0] == '+') )
00161   { 
00162    ++p; /* strip off the - */
00163    switch(p[0])
00164    {
00165     case 'v':   /* Give lots of information */
00166                 verbose++;
00167                 i++;
00168                 break;
00169 
00170     case 'd':   /* Debug mode */
00171                 debug_flag++;
00172                 i++;
00173                 fprintf(stderr,"DEBUG: Debug Level %d\n",debug_flag);
00174                 break;
00175 
00176     case 'l':   /* Enable looping */
00177                 loop=TRUE;
00178                 i++;
00179                 if(*argv[i] !='-') {
00180                   /* a loop count was given */
00181                   loopcount=atoi(argv[i++]);
00182                   if(verbose) fprintf(stderr,"Loop %d times\n",loopcount);
00183                   }
00184                 else {
00185                   /* default to infinite loop */
00186                   loopcount=0;
00187                   if(verbose) fputs("Looping enabled\n",stderr);
00188                   }
00189                 break;
00190 
00191     case 'u':   /* Use colormap? true or false */
00192                 i++;
00193                 if(atoi(argv[i]) || !strcmp("true",argv[i])) use_colormap=1;
00194                 else use_colormap=0;
00195                 i++;
00196                 break;
00197 
00198     case 't':   /* either time or transparent */
00199                 i++;
00200                 if(!strcmp("time",p)) {
00201                         /* Delay time in 1/100's of a second */
00202                         global.time=atoi(argv[i++]);
00203                         }
00204                 else if(!strncmp("trans",p,4)) Calc_Trans(argv[i++]);
00205                 break;
00206 
00207     case 'o':   /* Output file - send output to a given filename */
00208                 i++;
00209                 if(!strncmp("off",p,3)) set_offset(argv[i]);
00210                 else
00211                 /* It must be 'output, so do that */
00212                 if(NULL==(fout=fopen(argv[i],"w")))
00213                         {
00214                         fprintf(stderr,"Cannot open %s for output\n",argv[i]);
00215                         exit(1);
00216                         }
00217                 i++;
00218                 break;
00219     case 'i':   /* input file - file with a list of images */
00220                 i++;
00221                 if(NULL != (infile=fopen(argv[i],"r"))) {
00222                         while(fgets(gif_file_name,BIGSTRING,infile)) {
00223                                 strtok(gif_file_name,"\n");
00224                                 if(!count) GIF_Read_File(fout,gif_file_name,1);
00225                                 else       GIF_Read_File(fout,gif_file_name,0);
00226                                 count++;
00227                                 }
00228                         fclose(infile);
00229                         }
00230                 else fprintf(stderr,"Cannot read list file %s\n",argv[i]);
00231                 i++;
00232                 break;
00233 
00234     case 'h':   /* big help, added by RWCox */
00235                 big_Usage() ;
00236                 exit(0) ;
00237                 break ;
00238 
00239     default: 
00240                 Usage();
00241                 exit(0);
00242                 break;
00243    }
00244    continue;
00245   }
00246   /* Not an option, must be the name of an input file */
00247   if(!count) GIF_Read_File(fout,argv[i],1);
00248   else       GIF_Read_File(fout,argv[i],0);
00249   count++;
00250   i++;
00251  }
00252  /* We're done with all the options, finish up */
00253  if(count >0)
00254   {
00255   fputc(';',fout); /* image separator */
00256   sprintf(temp,"whirlgif %2.2f (C) kadokev@msg.net. %d images",DA_REV,count);
00257   GIF_Comment(fout,temp);
00258   }
00259 
00260  fclose(fout);
00261  fprintf(stderr,"Processed %d files.\n",count);
00262 }
00263 
00264 
00265 /*
00266  * Read a GIF file, outputting to fname as we go.
00267  * It would be faster to read and write the individual blocks,
00268  * but eventually we'd like to optimize based on changes from
00269  * previous images(ie only a small section of the image changed.
00270  */
00271 void
00272 GIF_Read_File(fout,fname,first_image)
00273 FILE * fout;
00274 char *fname;
00275 int first_image;
00276 {
00277  FILE *fp;
00278  int ret,i,exit_flag;
00279 
00280  if ( (fp=fopen(fname,"r"))==0)
00281  { 
00282   fprintf(stderr,"Can't open %s for reading.\n",fname); 
00283   TheEnd();
00284  }
00285 
00286  GIF_Screen_Header(fp,fout,first_image);
00287 
00288  /*** read until  ,  separator */
00289  do
00290  {
00291   i=fgetc(fp);
00292   if ( (i<0) && feof(fp))
00293   {
00294    fclose(fp);
00295    TheEnd1("GIF_Read_Header: Unexpected End of File\n");
00296   }
00297  } while(i != ',');
00298 
00299  if(first_image)
00300   {
00301    /* stuff we only do once */
00302    if(loop) GIF_Loop(fout,loopcount);
00303    }
00304  if(global.time||(global.trans.type!=TRANS_NONE && global.trans.valid))
00305         GIF_GCL(fout,global.time);
00306 
00307  fputc(',',fout); /* image separator */
00308 
00309  GIF_Image_Header(fp,fout,first_image);
00310 
00311  /*FOO*/
00312 
00313  /*** Setup ACTION for IMAGE */
00314 
00315  GIF_Decompress(fp,fout,0);
00316  fputc(0,fout);  /* block count of zero */
00317 
00318  fclose(fp);
00319 }
00320 
00321 void GIF_Decompress(fp,fout)
00322 FILE *fp,*fout;
00323 {
00324  register ULONG code,old;
00325 
00326  pic_i = 0;
00327  bits=0;
00328  num_bits=0;
00329  gif_block_size=0;
00330     /* starting code size of LZW */
00331  root_code_size=(fgetc(fp) & 0xff); fputc(root_code_size,fout);
00332  GIF_Clear_Table();                /* clear decoding symbol table */
00333 
00334  code=GIF_Get_Code(fp,fout);
00335 
00336  if (code==CLEAR) 
00337  {
00338   GIF_Clear_Table(); 
00339   code=GIF_Get_Code(fp,fout);
00340  }
00341  /* write code(or what it currently stands for) to file */
00342  GIF_Send_Data(code);   
00343  old=code;
00344  code=GIF_Get_Code(fp,fout);
00345  do
00346  {
00347   if (table[code].valid==1)    /* if known code */
00348   {
00349        /* send it's associated string to file */
00350     GIF_Send_Data(code);
00351     GIF_Get_Next_Entry(fp);       /* get next table entry (nextab) */
00352     GIF_Add_To_Table(old,code,nextab);  /* add old+code to table */
00353     old=code;
00354   }
00355   else      /* code doesn't exist */
00356   {
00357     GIF_Add_To_Table(old,old,code);   /* add old+old to table */
00358     GIF_Send_Data(code);
00359     old=code;
00360   }
00361   code=GIF_Get_Code(fp,fout);
00362   if (code==CLEAR)
00363   { 
00364    GIF_Clear_Table();
00365    code=GIF_Get_Code(fp,fout);
00366    GIF_Send_Data(code);
00367    old=code;
00368    code=GIF_Get_Code(fp,fout);
00369   }
00370  } while(code!=EOI);
00371 }
00372 
00373 void GIF_Get_Next_Entry(fp)
00374 FILE *fp;
00375 {
00376    /* table walk to empty spot */
00377  while(  (table[nextab].valid==1)
00378        &&(nextab<MAXVAL)
00379       ) nextab++;
00380  /* 
00381   * Ran out of space??!?  Something's roached 
00382   */
00383  if (nextab>=MAXVAL)    
00384  { 
00385   fprintf(stderr,"Error: GetNext nextab=%ld\n",(long)nextab);
00386   fclose(fp);
00387   TheEnd();
00388  }
00389  if (nextab==INCSIZE)   /* go to next table size (and LZW code size ) */
00390  {
00391    /* fprintf(stderr,"GetNext INCSIZE was %ld ",nextab); */
00392    code_size++; INCSIZE=(INCSIZE*2)+1;
00393    if (code_size>=12) code_size=12;
00394 /*   fprintf(stderr,"<%ld>",INCSIZE); */
00395  }
00396 
00397 }
00398 /*  body is associated string
00399     next is code to add to that string to form associated string for
00400     index
00401 */     
00402 
00403 void GIF_Add_To_Table(body,next,index)
00404 register ULONG body,next,index;
00405 {
00406  if (index>MAXVAL)
00407  { 
00408   fprintf(stderr,"Error index=%ld\n",(long)index);
00409  }
00410  else
00411  {
00412   table[index].valid=1;
00413   table[index].data=table[next].first;
00414   table[index].first=table[body].first;
00415   table[index].last=body;
00416  }
00417 }
00418 
00419 void GIF_Send_Data(index)
00420 register int index;
00421 {
00422  register int i,j;
00423  i=0;
00424  do         /* table walk to retrieve string associated with index */
00425  { 
00426   gif_buff[i]=table[index].data; 
00427   i++;
00428   index=table[index].last;
00429   if (i>MAXVAL)
00430   { 
00431    fprintf(stderr,"Error: Sending i=%ld index=%ld\n",(long)i,(long)index);
00432    TheEnd();
00433   }
00434  } while(index>=0);
00435 
00436  /* now invert that string since we retreived it backwards */
00437  i--;
00438  for(j=i;j>=0;j--)
00439  {
00440   /*pic[pic_i] = gif_buff[j] | gif_pix_offset;*/
00441   pic_i++;
00442  }
00443 }
00444 
00445 
00446 /* 
00447  * initialize string table 
00448  */
00449 void GIF_Init_Table()       
00450 {
00451  register int maxi,i;
00452 
00453 if (debug_flag) fprintf(stderr,"Initing Table...");
00454  maxi=gif_ptwo[root_code_size];
00455  for(i=0; i<maxi; i++)
00456  {
00457   table[i].data=i;   
00458   table[i].first=i;
00459   table[i].valid=1;  
00460   table[i].last = -1;
00461  }
00462  CLEAR=maxi; 
00463  EOI=maxi+1; 
00464  nextab=maxi+2;
00465  INCSIZE = (2*maxi)-1;
00466  code_size=root_code_size+1;
00467 }
00468 
00469 
00470 /* 
00471  * clear table 
00472  */
00473 void GIF_Clear_Table()   
00474 {
00475  register int i;
00476 if (debug_flag) fprintf(stderr,"Clearing Table...\n");
00477  for(i=0;i<MAXVAL;i++) table[i].valid=0;
00478  GIF_Init_Table();
00479 }
00480 
00481 /*CODE*/
00482 ULONG GIF_Get_Code(fp,fout) /* get code depending of current LZW code size */
00483 FILE *fp,*fout;
00484 {
00485  ULONG code;
00486  register int tmp;
00487 
00488  while(num_bits < code_size)
00489  {
00490   /**** if at end of a block, start new block */
00491   if (gif_block_size==0) 
00492   {
00493    tmp = fgetc(fp);
00494    if (tmp >= 0 )
00495    {
00496     fputc(tmp,fout);
00497     gif_block_size=(ULONG)(tmp);
00498    }
00499    else TheEnd1("EOF in data stream\n");
00500   }
00501 
00502   tmp = fgetc(fp);   gif_block_size--;
00503   if (tmp >= 0)
00504   {
00505    fputc(tmp,fout);
00506    bits |= ( ((ULONG)(tmp) & 0xff) << num_bits );
00507    num_bits+=8;
00508   }
00509   else TheEnd1("EOF in data stream\n");
00510  }
00511   
00512  code = bits & gif_mask[code_size];
00513  bits >>= code_size;
00514  num_bits -= code_size; 
00515 
00516 
00517  if (code>MAXVAL)
00518  { 
00519   fprintf(stderr,"\nError! in stream=%lx \n",(unsigned long)code); 
00520   fprintf(stderr,"CLEAR=%lx INCSIZE=%lx EOI=%lx code_size=%lx \n",
00521           (unsigned long)CLEAR,(unsigned long)INCSIZE,(unsigned long)EOI,(unsigned long)code_size); 
00522   code=EOI;
00523  }
00524 
00525  if (code==INCSIZE)
00526  {
00527   if (code_size<12)
00528   {
00529    code_size++; INCSIZE=(INCSIZE*2)+1;
00530   }
00531   else if (debug_flag) fprintf(stderr,"<13?>"); 
00532  }
00533 
00534  return(code);
00535 }
00536 
00537 
00538 /* 
00539  * read GIF header 
00540  */
00541 void GIF_Screen_Header(fp,fout,first_time)
00542 FILE *fp,*fout;
00543 int first_time;
00544 {
00545  int temp,i;
00546 
00547  for(i=0;i<6;i++)
00548  {
00549   temp = fgetc(fp);
00550   if(i==4 && temp == '7') temp='9';
00551   if (first_time==TRUE) fputc(temp,fout);
00552  }
00553 
00554  gifscrn.width  = GIF_Get_Short(fp,fout,first_time);
00555  gifscrn.height = GIF_Get_Short(fp,fout,first_time);
00556  temp=fgetc(fp);                 if (first_time==TRUE) fputc(temp,fout);
00557  gifscrn.m       =  temp & 0x80;
00558  gifscrn.cres    = (temp & 0x70) >> 4;
00559  gifscrn.pixbits =  temp & 0x07;
00560 
00561  gifscrn.bc  = fgetc(fp);
00562  if (first_time==TRUE) 
00563         {
00564         /* we really should set the background color to the transparent color */
00565         fputc(gifscrn.bc,fout);
00566         }
00567 
00568  temp=fgetc(fp);                 if (first_time==TRUE) fputc(temp,fout);
00569  imagec=gif_ptwo[(1+gifscrn.pixbits)];
00570 
00571  if (verbose)
00572   fprintf(stderr,"Screen: %ldx%ldx%ld m=%ld cres=%ld bkgnd=%ld pix=%ld\n",
00573     (long)gifscrn.width,(long)gifscrn.height,(long)imagec,(long)gifscrn.m,(long)gifscrn.cres,
00574     (long)gifscrn.bc,(long)gifscrn.pixbits);
00575 
00576  if(global.trans.type==TRANS_RGB) global.trans.valid=0;
00577  if (gifscrn.m)
00578  {
00579   for(i=0;i<imagec;i++)
00580   {
00581    gif_cmap[i].cmap.red   = temp = fgetc(fp); 
00582            if (first_time==TRUE) fputc(temp,fout);
00583    gif_cmap[i].cmap.green = temp = fgetc(fp); 
00584            if (first_time==TRUE) fputc(temp,fout);
00585    gif_cmap[i].cmap.blue  = temp = fgetc(fp); 
00586            if (first_time==TRUE) fputc(temp,fout);
00587 
00588    if(global.trans.type==TRANS_RGB && !global.trans.valid)
00589         if(global.trans.red==gif_cmap[i].cmap.red &&
00590         global.trans.green==gif_cmap[i].cmap.green &&
00591         global.trans.blue==gif_cmap[i].cmap.blue) {
00592           if(debug_flag>1) fprintf(stderr," Transparent match at %d\n",i);
00593             global.trans.map=i;
00594         global.trans.valid=TRUE;
00595         }
00596   }
00597  }
00598  screen_was_last = TRUE;
00599 }
00600 
00601 void GIF_Image_Header(fp,fout,first_time)
00602 FILE *fp,*fout;
00603 int first_time;
00604 {
00605  int temp,tnum,i,r,g,b;
00606 
00607  gifimage.left   = GIF_Get_Short(fp,fout,1);
00608  if(global.left) gifimage.left+=global.left;
00609 
00610  gifimage.top    = GIF_Get_Short(fp,fout,1);
00611  if(global.top) gifimage.top+=global.top;
00612 
00613  gifimage.width  = GIF_Get_Short(fp,fout,1);
00614  gifimage.height = GIF_Get_Short(fp,fout,1);
00615  temp=fgetc(fp); 
00616 
00617 
00618         
00619  gifimage.i        = temp & 0x40;
00620  gifimage.pixbits  = temp & 0x07;
00621  gifimage.m        = temp & 0x80;
00622 
00623  /* this sets the local colormap bit to true */
00624  if (screen_was_last && (first_time==FALSE)) temp |= 0x80;
00625 
00626  temp &= 0xf8;
00627  temp |= gifscrn.pixbits;
00628  fputc(temp,fout);
00629 
00630  imagex=gifimage.width;
00631  imagey=gifimage.height;
00632  tnum=gif_ptwo[(1+gifimage.pixbits)];
00633  if (verbose)
00634   fprintf(stderr,"Image: %ldx%ldx%ld (%ld,%ld) m=%ld i=%ld pix=%ld \n",
00635     (long)imagex,(long)imagey,(long)tnum,(long)gifimage.left,(long)gifimage.top,
00636         (long)gifimage.m,(long)gifimage.i,(long)gifimage.pixbits);
00637 
00638  /* if there is an image cmap, then use it */
00639 
00640  if (gifimage.m)
00641  {
00642 /*  if(debug_flag) fprintf(stderr,"DEBUG:Transferring colormap of %d colors\n"); */
00643   for(i=0;i<tnum;i++)
00644   {
00645    gif_cmap[i].cmap.red   = r = fgetc(fp);
00646    gif_cmap[i].cmap.green = g = fgetc(fp);
00647    gif_cmap[i].cmap.blue  = b = fgetc(fp);
00648    fputc(r,fout);
00649    fputc(g,fout);
00650    fputc(b,fout);
00651   }
00652  }  /* else if screen was last not 1st time */
00653  else if (screen_was_last && (first_time==FALSE))
00654  {
00655 /*  if(debug_flag>1) fprintf(stderr,"DEBUG:Writing colormap of %d colors\n"); */
00656   for(i=0;i<imagec;i++)
00657   {
00658    fputc(gif_cmap[i].cmap.red  ,fout);
00659    fputc(gif_cmap[i].cmap.green,fout);
00660    fputc(gif_cmap[i].cmap.blue ,fout);
00661   }
00662  }
00663  screen_was_last = FALSE; 
00664 }
00665 
00666 
00667 /*
00668  *
00669  */
00670 int GIF_Get_Short(fp,fout,first_time)
00671 FILE *fp,*fout;
00672 int first_time;
00673 {
00674  register int temp,tmp1;
00675  temp=fgetc(fp);         if (first_time==TRUE) fputc(temp,fout);
00676  tmp1=fgetc(fp);         if (first_time==TRUE) fputc(tmp1,fout);
00677  return(temp|( (tmp1) << 8 ));
00678 }
00679 
00680 void GIF_Comment(fout,string)
00681 FILE *fout;
00682 char *string;
00683 {
00684 if(!string || !strlen(string))
00685         {
00686         /* Bogus string */
00687         if(debug_flag) fprintf(stderr,"GIF_Comment: invalid argument");
00688         return;
00689         }
00690 fputc(0x21,fout);
00691 fputc(0xF9,fout);
00692 fputs(string,fout);
00693 fputc(0,fout);
00694 }
00695 
00696 /*
00697  * Write a Netscape loop marker.
00698  */
00699 void GIF_Loop(fout,repeats)
00700 FILE *fout;
00701 unsigned int repeats;
00702 {
00703 UBYTE low=0,high=0;
00704 if(repeats) {
00705         /* non-zero repeat count- Netscape hasn't implemented this yet */
00706         high=repeats / 256;
00707         low=repeats % 256;
00708         }
00709 
00710 fputc(0x21,fout);
00711 fputc(0xFF,fout);
00712 fputc(0x0B,fout);
00713 fputs("NETSCAPE2.0",fout);
00714 fputc(0x03,fout);
00715 fputc(0x01,fout);
00716 fputc(0x00,fout);
00717 
00718 
00719 fputc(low,fout); /* the delay count - 0 for infinite */
00720 fputc(high,fout); /* second byte of delay count */
00721 
00722 if(verbose) fprintf(stderr,"Wrote loop extension\n");
00723 }
00724 
00725 /*
00726  * GIF_GCL - add a Control Label to set an inter-frame delay value.
00727  */
00728 void GIF_GCL(fout,delay)
00729 FILE * fout;
00730 unsigned int delay;
00731 {
00732 UBYTE low=0,high=0,flag=0;
00733 if(delay) {
00734         /* non-zero delay, figure out low/high bytes */
00735         high=delay / 256;
00736         low=delay % 256;
00737         }
00738 
00739 fputc(0x21,fout);
00740 fputc(0xF9,fout);
00741 fputc(0x04,fout);
00742 
00743 if(delay) flag |=0x80;
00744 if(global.trans.valid) flag |=0x01;
00745 fputc(flag,fout);
00746 
00747 fputc(low,fout); /* the delay speed - 0 is instantaneous */
00748 fputc(high,fout); /* second byte of delay count */
00749 
00750 fputc(global.trans.map,fout);
00751 fputc(0,fout);
00752 if(debug_flag>1) {
00753   fprintf(stderr,"GCL: delay %d",delay);
00754   if(global.trans.valid) fprintf(stderr," Transparent: %d",global.trans.map);
00755   fputc('\n',stderr);
00756   }
00757 }
00758 
00759 
00760 void Calc_Trans(string)
00761 char * string;
00762 {
00763 if(string[0] != '#') {
00764   global.trans.type=TRANS_MAP;
00765   global.trans.map=atoi(string);
00766   global.trans.valid=1;
00767   }
00768 else
00769   {
00770   /* it's an RGB value */
00771   int r,g,b;
00772   string++;
00773   if(3==sscanf(string,"%2x%2x%2x",&r,&g,&b)) {
00774         global.trans.red=r;
00775         global.trans.green=g;
00776         global.trans.blue=b;
00777         global.trans.type=TRANS_RGB;
00778         if(debug_flag) fprintf(stderr,"Transparent RGB=(%x,%x,%x)\n",r,g,b);
00779         }
00780   }
00781 if(debug_flag) fprintf(stderr,"DEBUG:Calc_trans is %d\n",global.trans.type);
00782 }
00783 
00784 void set_offset(string)
00785 char * string;
00786 {
00787 char *off_x,*off_y;
00788 off_x=(char *) strtok(string,",");
00789 off_y=(char *)strtok((char *)NULL,",");
00790 if(off_x && off_y) {
00791         /* set the offset */
00792         global.left=atoi(off_x);
00793         global.top=atoi(off_y);
00794         if(debug_flag>1) fprintf(stderr,"Offset changed to %d,%d\n",
00795                 global.left,global.top);
00796         return;
00797         }
00798 if(debug_flag>1) fprintf(stderr,"Couldn't parse offset values.\n");
00799 exit(0);
00800 }
00801 
00802 big_Usage()
00803 {
00804    printf("\n"
00805      "whirlgif is a quick program that reads a series of GIF files, and produces\n"
00806      "a single gif file composed of those images.\n"
00807      "\n"
00808      "Usage: whirlgif [-v] [-trans index ] [-time delay] [-o outfile]\n"
00809      "                [-loop] [-i incfile] file1 [ -time delay] file2\n"
00810      "\n"
00811      "options:\n"
00812      "   -v              verbose mode\n"
00813      "   -loop [count]   add the Netscape 'loop' extension.\n"
00814      "   -time delay     inter-frame timing.\n"
00815      "   -trans index    set the colormap index 'index' to be transparent\n"
00816      "   -o outfile      write the results to 'outfile'\n"
00817      "   -i incfile      read a list of names from 'incfile'\n"
00818      "\n"
00819      "TIPS\n"
00820      "\n"
00821      "If you don't specify an output file, the GIF will be sent to stdout. This is\n"
00822      "a good thing if you're using this in a CGI script, a very bad thing if you\n"
00823      "run this from a terminal and forget to redirect stdout.\n"
00824      "\n"
00825      "The output file (if any) and -loop _MUST_ be specified before any gif images.\n"
00826      "\n"
00827      "You can specify several delay statements on the command line to change\n"
00828      "the delay between images in the middle of an animation, e.g.\n"
00829      "\n"
00830      "      whirlgif -time 5 a.gif b.gif c.gif -time 100 d.gif -time 5 e.gif f.gif\n"
00831      "\n"
00832      "Although it's generally considered to be evil, you can also specify\n"
00833      "several transparency statements on the command line, to change the transparent\n"
00834      "color in the middle of an animation. This may cause problems for some programs.\n"
00835      "\n"
00836      "\n"
00837      "BUGS\n"
00838      "  + The loop 'count' is ineffective because Netspcape always loops infinitely.\n"
00839      "  + Should be able to specify delay in an 'incfile' list (see next bug).\n"
00840      "  + Does not handle filenames starting with a - (hypen), except in 'incfile'.\n"
00841      "\n"
00842      "This program is available from http://www.msg.net/utility/whirlgif/\n"
00843      "-------------------------------------------------------------------\n"
00844      "Kevin Kadow     kadokev@msg.net\n"
00845      "Based on 'txtmerge' written by:\n"
00846      "Mark Podlipec   podlipec@wellfleet.com\n"
00847    ) ;
00848    exit(0) ;
00849 }
 

Powered by Plone

This site conforms to the following standards: