/* Bring in the gd library functions */ #include "gd.h" /* Bring in standard I/O and string manipulation functions */ #include #include /* for atoi() */ #include #ifdef _WIN32 #include int getpid () { return _getpid (); } #else #include /* 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; }