xref: /PHP-8.3/ext/gd/libgd/webpng.c (revision 50ea2676)
1 /* Bring in the gd library functions */
2 #include "gd.h"
3 
4 /* Bring in standard I/O and string manipulation functions */
5 #include <stdio.h>
6 #include <stdlib.h>		/* for atoi() */
7 #include <string.h>
8 
9 #ifdef _WIN32
10 #include <process.h>
11 int
getpid()12 getpid ()
13 {
14   return _getpid ();
15 }
16 #else
17 #include <unistd.h>		/* for getpid(), unlink() */
18 #endif
19 int
main(int argc,char ** argv)20 main (int argc, char **argv)
21 {
22   FILE *in;
23   FILE *out;
24   char outFn[20];
25   int useStdinStdout = 0;
26 
27   /* Declare our image pointer */
28   gdImagePtr im = 0;
29   int i;
30   /* We'll clear 'no' once we know the user has made a
31      reasonable request. */
32   int no = 1;
33   /* We'll set 'write' once we know the user's request
34      requires that the image be written back to disk. */
35   int write = 0;
36   /* C programs always get at least one argument; we want at
37      least one more (the image), more in practice. */
38   if (argc < 2 || !strcmp (argv[1], "--help"))
39     {
40       no = 1;
41       goto usage;
42     }
43 
44   /* The last argument should be the image. Open the file. */
45   if (strcmp ("-", argv[argc - 1]) == 0)
46     {				/* - is synonymous with STDIN */
47       useStdinStdout = 1;
48       in = stdin;
49     }
50   else
51     {
52       in = fopen (argv[argc - 1], "rb");
53     }
54   if (!in)
55     {
56       fprintf (stderr,
57 	       "Error: can't open file %s.\n", argv[argc - 1]);
58       exit (1);
59     }
60   /* Now load the image. */
61   im = gdImageCreateFromPng (in);
62   fclose (in);
63   /* If the load failed, it must not be a PNG file. */
64   if (!im)
65     {
66       fprintf (stderr,
67 	       "Error: %s is not a valid PNG file.\n", argv[argc - 1]);
68       exit (1);
69     }
70   /* Consider each argument in turn. */
71   for (i = 1; (i < (argc - 1)); i++)
72     {
73       /* -i turns on and off interlacing. */
74       if (!strcmp (argv[i], "--help"))
75 	{
76 	  /* Every program should use this for help! :) */
77 	  no = 1;
78 	  goto usage;
79 	}
80       else if (!strcmp (argv[i], "-i"))
81 	{
82 	  if (i == (argc - 2))
83 	    {
84 	      fprintf (stderr,
85 		       "Error: -i specified without y or n.\n");
86 	      no = 1;
87 	      goto usage;
88 	    }
89 	  if (!strcmp (argv[i + 1], "y"))
90 	    {
91 	      /* Set interlace. */
92 	      gdImageInterlace (im, 1);
93 	    }
94 	  else if (!strcmp (argv[i + 1], "n"))
95 	    {
96 	      /* Clear interlace. */
97 	      gdImageInterlace (im, 0);
98 	    }
99 	  else
100 	    {
101 	      fprintf (stderr,
102 		       "Error: -i specified without y or n.\n");
103 	      no = 1;
104 	      goto usage;
105 	    }
106 	  i++;
107 	  no = 0;
108 	  write = 1;
109 	}
110       else if (!strcmp (argv[i], "-t"))
111 	{
112 	  /* Set transparent index (or none). */
113 	  int index;
114 	  if (i == (argc - 2))
115 	    {
116 	      fprintf (stderr,
117 		       "Error: -t specified without a color table index.\n");
118 	      no = 1;
119 	      goto usage;
120 	    }
121 	  if (!strcmp (argv[i + 1], "none"))
122 	    {
123 	      /* -1 means not transparent. */
124 	      gdImageColorTransparent (im, -1);
125 	    }
126 	  else
127 	    {
128 	      /* OK, get an integer and set the index. */
129 	      index = atoi (argv[i + 1]);
130 	      gdImageColorTransparent (im, index);
131 	    }
132 	  i++;
133 	  write = 1;
134 	  no = 0;
135 	}
136       else if (!strcmp (argv[i], "-l"))
137 	{
138 	  /* List the colors in the color table. */
139 	  int j;
140 	  if (!im->trueColor)
141 	    {
142 	      /* Tabs used below. */
143 	      printf ("Index	Red	Green	Blue Alpha\n");
144 	      for (j = 0; (j < gdImageColorsTotal (im)); j++)
145 		{
146 		  /* Use access macros to learn colors. */
147 		  printf ("%d	%d	%d	%d	%d\n",
148 			  j,
149 			  gdImageRed (im, j),
150 			  gdImageGreen (im, j),
151 			  gdImageBlue (im, j),
152 			  gdImageAlpha (im, j));
153 		}
154 	    }
155 	  else
156 	    {
157 	      printf ("Truecolor image, no palette entries to list.\n");
158 	    }
159 	  no = 0;
160 	}
161       else if (!strcmp (argv[i], "-d"))
162 	{
163 	  /* Output dimensions, etc. */
164 	  int t;
165 	  printf ("Width: %d Height: %d Colors: %d\n",
166 		  gdImageSX (im), gdImageSY (im),
167 		  gdImageColorsTotal (im));
168 	  t = gdImageGetTransparent (im);
169 	  if (t != (-1))
170 	    {
171 				printf ("First 100%% transparent index: %d\n", t);
172 	    }
173 	  else
174 	    {
175 	      /* -1 means the image is not transparent. */
176 				printf ("First 100%% transparent index: none\n");
177 	    }
178 	  if (gdImageGetInterlaced (im))
179 	    {
180 	      printf ("Interlaced: yes\n");
181 	    }
182 	  else
183 	    {
184 	      printf ("Interlaced: no\n");
185 	    }
186 	  no = 0;
187 	}
188 		else if (!strcmp(argv[i], "-a"))
189 		{
190 			int maxx, maxy, x, y, alpha, pix, nalpha = 0;
191 
192 			maxx = gdImageSX(im);
193 			maxy = gdImageSY(im);
194 
195 			printf("alpha channel information:\n");
196 
197 			if (im->trueColor)	{
198 				for (y = 0; y < maxy; y++)	{
199 					for (x = 0; x < maxx; x++)	{
200 						pix = gdImageGetPixel(im, x, y);
201 						alpha = gdTrueColorGetAlpha(pix);
202 
203 						if (alpha > gdAlphaOpaque)	{
204 							/* Use access macros to learn colors. */
205 							printf ("%d	%d	%d	%d\n",
206 									gdTrueColorGetRed(pix),
207 									gdTrueColorGetGreen(pix),
208 									gdTrueColorGetBlue(pix),
209 									alpha);
210 							nalpha++;
211 						}
212 
213 					}
214 				}
215 			}
216 			else
217 				printf("NOT a true color image\n");
218 			no = 0;
219 			printf("%d alpha channels\n", nalpha);
220 
221 		}
222       else
223 	{
224 	  fprintf (stderr, "Unknown argument: %s\n", argv[i]);
225 	  break;
226 	}
227     }
228 usage:
229   if (no)
230     {
231       /* If the command failed, output an explanation. */
232       fprintf (stderr,
233 	  "Usage: webpng [-i y|n ] [-l] [-t index|none ] [-d] pngname.png\n"
234 
235 	       "  -i [y|n]   Turns on/off interlace\n"
236 	       "  -l         Prints the table of color indexes\n"
237 	       "  -t [index] Set the transparent color to the specified index (0-255 or \"none\")\n"
238 	       "  -d         Reports the dimensions and other characteristics of the image.\n"
239 				"  -a         Prints all alpha channels that are not 100%% opaque.\n"
240 	       "\n"
241 	       "If you specify '-' as the input file, stdin/stdout will be used input/output.\n"
242 	);
243     }
244   if (write)
245     {
246       if (useStdinStdout)
247 	{
248 	  out = stdout;
249 	}
250       else
251 	{
252 	  /* Open a temporary file. */
253 
254 	  /* "temp.tmp" is not good temporary filename. */
255 	  snprintf (outFn, sizeof(outFn), "webpng.tmp%d", getpid ());
256 	  out = fopen (outFn, "wb");
257 
258 	  if (!out)
259 	    {
260 	      fprintf (stderr,
261 		       "Unable to write to %s -- exiting\n", outFn);
262 	      exit (1);
263 	    }
264 	}
265 
266       /* Write the new PNG. */
267       gdImagePng (im, out);
268 
269       if (!useStdinStdout)
270 	{
271 	  fclose (out);
272 	  /* Erase the old PNG. */
273 	  unlink (argv[argc - 1]);
274 	  /* Rename the new to the old. */
275 	  if (rename (outFn, argv[argc - 1]) != 0)
276 	    {
277 	      perror ("rename");
278 	      exit (1);
279 	    }
280 	}
281     }
282   /* Delete the image from memory. */
283   if (im)
284     {
285       gdImageDestroy (im);
286     }
287   /* All's well that ends well. */
288   return 0;
289 }
290