webpng.c   [plain text]


/* 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. */
  im = gdImageCreateFromPng (in);
  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"))
		{
			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. */
	  snprintf (outFn, sizeof(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. */
      gdImagePng (im, out);

      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;
}