#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/* Bring in the gd library functions */
#include "gd.h"

/* Bring in standard I/O and string manipulation functions */
#include <stdio.h>
#include <stdlib.h>		/* for atoi() */
#include <string.h>

#ifdef _WIN32
#include <process.h>
int
getpid ()
{
  return _getpid ();
}
#else
#include <unistd.h>		/* for getpid(), unlink() */
#endif
int
main (int argc, char **argv)
{
  FILE *in;
  FILE *out;
  char outFn[20];
  int useStdinStdout = 0;

  /* Declare our image pointer */
  gdImagePtr im = 0;
  int i;
  /* We'll clear 'no' once we know the user has made a
     reasonable request. */
  int no = 1;
  /* We'll set 'write' once we know the user's request
     requires that the image be written back to disk. */
  int write = 0;
  /* C programs always get at least one argument; we want at
     least one more (the image), more in practice. */
  if (argc < 2 || !strcmp (argv[1], "--help"))
    {
      no = 1;
      goto usage;
    }

  /* The last argument should be the image. Open the file. */
  if (strcmp ("-", argv[argc - 1]) == 0)
    {				/* - is synonymous with STDIN */
      useStdinStdout = 1;
      in = stdin;
    }
  else
    {
      in = fopen (argv[argc - 1], "rb");
    }
  if (!in)
    {
      fprintf (stderr, "Error: can't open file %s.\n", argv[argc - 1]);
      exit (1);
    }
  /* Now load the image. */
#ifdef HAVE_LIBPNG
  im = gdImageCreateFromPng (in);
#else
  fprintf (stderr, "No PNG library support.\n");
#endif
  fclose (in);
  /* If the load failed, it must not be a PNG file. */
  if (!im)
    {
      fprintf (stderr,
	       "Error: %s is not a valid PNG file.\n", argv[argc - 1]);
      exit (1);
    }
  /* Consider each argument in turn. */
  for (i = 1; (i < (argc - 1)); i++)
    {
      /* -i turns on and off interlacing. */
      if (!strcmp (argv[i], "--help"))
	{
	  /* Every program should use this for help! :) */
	  no = 1;
	  goto usage;
	}
      else if (!strcmp (argv[i], "-i"))
	{
	  if (i == (argc - 2))
	    {
	      fprintf (stderr, "Error: -i specified without y or n.\n");
	      no = 1;
	      goto usage;
	    }
	  if (!strcmp (argv[i + 1], "y"))
	    {
	      /* Set interlace. */
	      gdImageInterlace (im, 1);
	    }
	  else if (!strcmp (argv[i + 1], "n"))
	    {
	      /* Clear interlace. */
	      gdImageInterlace (im, 0);
	    }
	  else
	    {
	      fprintf (stderr, "Error: -i specified without y or n.\n");
	      no = 1;
	      goto usage;
	    }
	  i++;
	  no = 0;
	  write = 1;
	}
      else if (!strcmp (argv[i], "-t"))
	{
	  /* Set transparent index (or none). */
	  int index;
	  if (i == (argc - 2))
	    {
	      fprintf (stderr,
		       "Error: -t specified without a color table index.\n");
	      no = 1;
	      goto usage;
	    }
	  if (!strcmp (argv[i + 1], "none"))
	    {
	      /* -1 means not transparent. */
	      gdImageColorTransparent (im, -1);
	    }
	  else
	    {
	      /* OK, get an integer and set the index. */
	      index = atoi (argv[i + 1]);
	      gdImageColorTransparent (im, index);
	    }
	  i++;
	  write = 1;
	  no = 0;
	}
      else if (!strcmp (argv[i], "-l"))
	{
	  /* List the colors in the color table. */
	  int j;
	  if (!im->trueColor)
	    {
	      /* Tabs used below. */
	      printf ("Index	Red	Green	Blue Alpha\n");
	      for (j = 0; (j < gdImageColorsTotal (im)); j++)
		{
		  /* Use access macros to learn colors. */
		  printf ("%d	%d	%d	%d	%d\n",
			  j,
			  gdImageRed (im, j),
			  gdImageGreen (im, j),
			  gdImageBlue (im, j), gdImageAlpha (im, j));
		}
	    }
	  else
	    {
	      printf ("Truecolor image, no palette entries to list.\n");
	    }
	  no = 0;
	}
      else if (!strcmp (argv[i], "-d"))
	{
	  /* Output dimensions, etc. */
	  int t;
	  printf ("Width: %d Height: %d Colors: %d\n",
		  gdImageSX (im), gdImageSY (im), gdImageColorsTotal (im));
	  t = gdImageGetTransparent (im);
	  if (t != (-1))
	    {
	      printf ("First 100%% transparent index: %d\n", t);
	    }
	  else
	    {
	      /* -1 means the image is not transparent. */
	      printf ("First 100%% transparent index: none\n");
	    }
	  if (gdImageGetInterlaced (im))
	    {
	      printf ("Interlaced: yes\n");
	    }
	  else
	    {
	      printf ("Interlaced: no\n");
	    }
	  no = 0;
	}
      else if (!strcmp (argv[i], "-a"))
	{
	  /* Alpha channel info -- thanks to Wez Furlong */
	  int maxx, maxy, x, y, alpha, pix, nalpha = 0;

	  maxx = gdImageSX (im);
	  maxy = gdImageSY (im);

	  printf ("alpha channel information:\n");

	  if (im->trueColor)
	    {
	      for (y = 0; y < maxy; y++)
		{
		  for (x = 0; x < maxx; x++)
		    {
		      pix = gdImageGetPixel (im, x, y);
		      alpha = gdTrueColorGetAlpha (pix);

		      if (alpha > gdAlphaOpaque)
			{
			  /* Use access macros to learn colors. */
			  printf ("%d	%d	%d	%d\n",
				  gdTrueColorGetRed (pix),
				  gdTrueColorGetGreen (pix),
				  gdTrueColorGetBlue (pix), alpha);
			  nalpha++;
			}

		    }
		}
	    }
	  else
	    printf ("NOT a true color image\n");
	  no = 0;
	  printf ("%d alpha channels\n", nalpha);

	}
      else
	{
	  fprintf (stderr, "Unknown argument: %s\n", argv[i]);
	  break;
	}
    }
usage:
  if (no)
    {
      /* If the command failed, output an explanation. */
      fprintf (stderr,
	       "Usage: webpng [-i y|n ] [-l] [-t index|none ] [-d] pngname.png\n"
	       "  -i [y|n]   Turns on/off interlace\n"
	       "  -l         Prints the table of color indexes\n"
	       "  -t [index] Set the transparent color to the specified index (0-255 or \"none\")\n"
	       "  -d         Reports the dimensions and other characteristics of the image.\n"
	       "  -a         Prints all alpha channels that are not 100%% opaque.\n"
	       "\n"
	       "If you specify '-' as the input file, stdin/stdout will be used input/output.\n");
    }
  if (write)
    {
      if (useStdinStdout)
	{
	  out = stdout;
	}
      else
	{
	  /* Open a temporary file. */

	  /* "temp.tmp" is not good temporary filename. */
	  sprintf (outFn, "webpng.tmp%d", getpid ());
	  out = fopen (outFn, "wb");

	  if (!out)
	    {
	      fprintf (stderr, "Unable to write to %s -- exiting\n", outFn);
	      exit (1);
	    }
	}

      /* Write the new PNG. */
#ifdef HAVE_LIBPNG
      gdImagePng (im, out);
#else
      fprintf (stderr, "No PNG library support.\n");
#endif
      if (!useStdinStdout)
	{
	  fclose (out);
	  /* Erase the old PNG. */
	  unlink (argv[argc - 1]);
	  /* Rename the new to the old. */
	  if (rename (outFn, argv[argc - 1]) != 0)
	    {
	      perror ("rename");
	      exit (1);
	    }
	}
    }
  /* Delete the image from memory. */
  if (im)
    {
      gdImageDestroy (im);
    }
  /* All's well that ends well. */
  return 0;
}
