mirror of
https://github.com/php/php-src.git
synced 2024-12-13 03:44:17 +08:00
290 lines
6.3 KiB
C
290 lines
6.3 KiB
C
/* 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;
|
|
}
|