/*
 * gifanim -- build animated gifs. Netscape2.0 and xanim play them.
 *
 * 10.5.96 jw.
 */
#include <stdio.h>
char copyright[] = "gifanim 0.1 (c) 1996 by Juergen Weigert";

int verbose = 0;

#define BYTE(c)   do { (c) = getc(fp); if (copy_it) putchar((c)); } while (0)

int
read_header(fp, copy_it)
FILE *fp;
int copy_it;
{
  int i, c, n;
  for (i = 0; i < 10; i++)
    BYTE(c);
  BYTE(c);
  i = 3 * (2 << (c & 0x07));
  BYTE(c);
  BYTE(c);
  if (c == EOF) return -1;
  while (i--)	/* read colormap */
    BYTE(c);
  if (c == EOF) return -1;
  for (;;)
    {
      c = getc(fp);
      if (c != ',' && copy_it) 
        putchar(c);

      if (c == '!')
        {
	  /* read extension */
	  BYTE(n);
	  if (verbose) fprintf(stderr, "\tgif extension 0x%02x\n", n);
	  BYTE(i);
	  while (i > 0)
	    {
	      while (i--)
	        BYTE(n);
	      BYTE(i);		/* continuation chunk ? */
	    }
	  continue;
	}
      if (c == EOF) return -1;
      if (c == ';') return 1;	/* we did not expect that here */
      if (c == ',') break;
    }
  return 0;
}

int
read_image(fp)
FILE *fp;
{
#define copy_it 1
  int i, c, l, h, width, height;
  BYTE(l); BYTE(h);			/* left */
  BYTE(l); BYTE(h);			/* top */
  BYTE(l); BYTE(h); width = h << 8 | l;
  BYTE(l); BYTE(h); height = h << 8 | l;
  BYTE(c); i = (c & 0x07);		/* imaged */
  if (verbose)
    fprintf(stderr, "\tsize %dx%d\n", width, height);
  if (c & 0x80)				/* we have a colormap here */ 
    {
      for (l = 3 * (2 << i); l > 0; l--)
        BYTE(c);
    }
  l = getc(fp);
  while ((c = getc(fp)) != EOF)
    {
      putchar(l);
      l = c;
    }
  return 0;
}

int
usage(name, problem, arg)
char *name, *problem, *arg;
{
  if (problem && *problem)
    fprintf(stderr, "%s error: ", name);
  if (problem)
    fprintf(stderr, problem, arg);
  fprintf(stderr, "\nUsage:\n%s [-v] [-n] [-s msecs] image.gif [ [-s msecs] ... ] > animfile.gif\n", name);
  return 1;
}

int
main(ac, av)
int ac;
char **av;
{
  char *av0 = *av++;
  int speed = 300;		/* milliseconds per frame */
  int imagecount = 0;
  int dontloop = 0;

  while (*av)
    {
      if (!strcmp("-h", *av) || !strcmp("-?", *av) || !strcmp("--help", *av))
        {
	  return usage(av0, "", NULL);
	}
      else if (!strcmp("-s", *av))
        {
	  if (!*(++av)) return usage(av0, "-s: parameter missing", NULL);
	  speed = strtol(*av, NULL, 0);
	}
      else if (!strcmp("-v", *av))
	verbose++;
      else if (!strcmp("-n", *av))
	dontloop++;
      else if (*av[0] == '-' && *av[1] == '\0')
        return usage(av0, "%s: unknown option", *av);
      else
        {
	  FILE *fp;
	  if (verbose)
	    fprintf(stderr, "%s: image '%s' \tfor %d msecs\n", av0, *av, speed);
	  /* it is an image */
	  if (!(fp = fopen(*av, "r"))) { perror(*av); return 2; }
	  if (read_header(fp, imagecount ? 0 : 1))
	    { fprintf(stderr, "%s: not at all a gif image\n", *av); return 3; }

	  if (!imagecount)
	    { 
	      /* A comment to to store my name */
	      putchar('!'); putchar(0xfd); putchar(strlen(copyright));
	      fwrite(copyright, strlen(copyright), 1, stdout);
	      putchar(0);

	      if (!dontloop)
		{
		  /* Extension that makes the animation loop under netscape  */
		  putchar('!'); putchar(0xff); putchar(0x0b);
		  fwrite("NETSCAPE2.0", 11, 1, stdout); putchar(3); putchar(1);
		  putchar(0); putchar(0); putchar(0);
		}
	    }

	  /* 
	   * Extension that makes the gif file an animation. 
	   * The inter image delay is stored here.
	   */
	  putchar('!'); putchar(0xf9); putchar(4);
	  putchar(4); putchar((speed/10) & 0xff);
	  putchar((speed/10) >> 8); putchar(0xff); putchar(0);
	  
	  putchar(',');
	  read_image(fp);
	  fclose(fp);
	  imagecount++;
	}
      av++;
    }
  putchar(';');
  return imagecount ? 0 : usage(av0, "No images?", NULL);
}

