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