1 /*******************************************************************************
2 **  fly:  On-the-fly image creation utility
3 **  Martin Gleeson, martin@gleeson.com
4 **  Copyright (c), Martin Gleeson and The University of Melbourne, 1994-2001
5 **  Created: 9 December 1994
6 **  Last Update: 28th February 2001
7 **
8 **  Uses the gd library by Thomas Boutell, boutell@boutell.com
9 **  gd: Copyright 1994-1999, Quest Protein Database Centre,
10 **     Cold Spring Harbour Labs
11 **
12 **  Contributions from:
13 **  Philip Warner
14 **     patches to gd to retain support for GIF images
15 **  Claus Hofmann <claush@ipfr.bau-verm.uni-karlsruhe.de>
16 **     addition of 'transparent' directive.
17 **     addtion of code to check if colour already allocated
18 **     addition of feature to copy whole image if all coords are -1
19 **  John Bowe <bowe@osf.org>
20 **     addition of better argument parsing
21 **  Ian Reid <ian@robots.ox.ac.uk>
22 **     addition of reading existing image file from external program output
23 **     fix for line number calculations
24 **  Shoji Mori <mori@moriken.com>
25 **     fix for win32 binmode weirdness
26 **  Anatoly A. Orehovsky <tolik@mpeks.tomsk.su>
27 **     fix for garbage input files
28 **
29 *******************************************************************************/
30 
31 /******************************************************************************
32 **  Defines
33 ******************************************************************************/
34 
35 /* Uncomment the following line if your operating system doesn't support fork */
36 /* #define NO_FORK 1 */
37 
38 #define NAMESIZE 1256
39 
40 /******************************************************************************
41 **  Included Header Files
42 ******************************************************************************/
43 
44 #include "gd.h"
45 #include "gdfonts.h"
46 #include "gdfontl.h"
47 #include "gdfontmb.h"
48 #include "gdfontt.h"
49 #include "gdfontg.h"
50 #include "fly.h"
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <errno.h>
54 #include <string.h>
55 #include <unistd.h>
56 
57 #ifdef WIN32
58 #include <fcntl.h>
59 #include <io.h>
60 #endif
61 
62 /******************************************************************************
63 **  Strings for usage and quick reference
64 ******************************************************************************/
65 
66 char *version = "2.0.1";
67 char *usage = "Usage : fly [-h] [-q] [-i inputfile] [-o outputfile]";
68 
69 char *help = "See <http://martin.gleeson.net/fly/> for documentation.\n\
70 \n\
71 Quick Reference to Directives: \n\
72 \n\
73 new\n\
74 size x,y\n\
75 name filename\n\
76 \n\
77 line    x1,y1,x2,y2,R,G,B             dline        x1,y1,x2,y2,R,G,B \n\
78 rect    x1,y1,x2,y2,R,G,B             frect        x1,y1,x2,y2,R,G,B \n\
79 square  x,y,s,R,G,B                   fsquare      x,y,s,R,G,B \n\
80 poly    R,G,B,x1,y1...,xn,yn          fpoly        R,G,B,x1,y1...,xn,yn \n\
81 fill    x,y,R,G,B                     filltoborder x,y,R1,G1,B1,R2,B2,G2 \n\
82 arc     x1,y1,w,h,start,finish,R,G,B  \n\
83 ellipse x1,y1,w,h,R,G,B  \n\
84 circle  x,y,d,R,G,B                   fcircle      x,y,d,R,G,B \n\
85 \n\
86 string   R,G,B,x,y,<size>,<string> \n\
87 stringup R,G,B,x,y,<size>,<string> \n\
88 (size = tiny, small, medium, large or giant) \n\
89 \n\
90 copy         x,y,x1,y1,x2,y2,filename \n\
91 copyresized  x1,y1,x2,y2,dx1,dy1,dx2,dy2,filename \n\
92 \n\
93 setpixel     x,y,R,G,B \n\
94 getpixel     x,y \n\
95 colourchange R1,G1,B1,R2,G2,B2 \n\
96 transparent  R,G,B \n\
97 interlace \n\
98 \n\
99 setbrush    filename                         killbrush \n\
100 settile     filename                         killtile \n\
101 setstyle    R1,G1,B1,R2,G2,B2,...,Rn,Bn,Gn       killstyle \n\n\
102 sizex \n\
103 sizey \n\
104 rotate      deg \n\
105 \n\
106 type        gif|png|jpeg\n\
107 quality     n (image quality when type = jpeg. Must be in the range 0-95)\n\
108 \n\
109 end\n";
110 
111 /******************************************************************************
112 **  Internal Functions
113 ******************************************************************************/
114 
115 int         process_args(int argc, char *argv[]);
116 int         get_token(FILE *infile);
117 int         get_number(FILE *infile);
118 char        *get_string(FILE *infile);
119 void        sync_input(FILE *infile);
120 int         get_colour(FILE *infile, gdImagePtr img);
121 void        copy_to_img(FILE *infile, gdImagePtr img, int resize);
122 gdImagePtr  get_image(int type, int argc, char *argv[]);
123 void       *my_newmem(size_t size);
124 FILE       *get_file(int *line_number, char **filename);
125 void        swap(int *a, int *b);
126 
127 /******************************************************************************
128 **  Global Variables
129 ******************************************************************************/
130 
131 int   finished = FALSE,
132           done = FALSE,
133          quiet = FALSE,
134    end_of_line = FALSE,
135    written_out = FALSE,
136           type = 0,
137        imgtype = PNG,
138    line_number = 1;
139 
140 char     *input_file = NULL,
141          *output_file = NULL;
142 
143 FILE	 *outfile;
144 FILE	 *infile;
145 FILE	 *brushfile;
146 FILE	 *tilefile;
147 FILE     *verbose_out;
148 
149 /******************************************************************************
150 ** Main Program
151 ******************************************************************************/
152 
main(int argc,char * argv[])153 int main(int argc, char *argv[]){
154 	int colour = 0, colour1 = 0, colour2 = 0, type;
155 	int status, size, side, jp_quality = 75;
156 	int brush_on = 0, tile_on = 0, style_on = 0;
157 	int num_entries, up = 0;
158 	int i, n, c, x, y;
159 	int size_x, size_y;
160 	int arg[4096], style[1024];
161 	char *s;
162 	gdPoint points[2048];
163 	gdImagePtr img = NULL, brush = NULL, tile = NULL, new_img = NULL;
164 	gdFontPtr gdFont = gdFontSmall; /* just a default font */
165 
166 	status = process_args(argc, argv);
167 	if (status == FALSE) exit(1);
168 
169 START:	type = get_token(infile);
170 	while(((type == COMMENT) || (type == EMPTY) || (type == (int)NULL))) {
171 		sync_input(infile);
172 		type = get_token(infile);
173 		if(finished == TRUE) goto FINISH;
174 	}
175 	if(finished == TRUE) goto FINISH;
176 	if( type != NEW	 && type != EXISTING) {
177 		fprintf(stderr,"Error: Must use 'new' or 'existing' directive first in input.\n");
178 		exit(1);
179 	}
180 	img=get_image(type, argc, argv);
181 
182 	/* while more lines to process */
183 	do{
184 		type = get_token(infile);
185 		switch(type){
186 
187 		case LINE:      /*      gdImageLine()           */
188 			for(i=1;i<=4;i++) {
189 				arg[i]=get_number(infile);
190 			}
191 			if (!quiet) fprintf(verbose_out,"## Line ## drawn from %d,%d to %d,%d. (",
192 			    arg[1],arg[2],arg[3],arg[4]);
193 			if( brush_on ) {
194 				sync_input(infile);
195 				gdImageLine(img,arg[1],arg[2],arg[3],arg[4],gdBrushed);
196 				if (!quiet) fprintf(verbose_out,"colour = current brush");
197 			} else if ( style_on ) {
198 				sync_input(infile);
199 				gdImageLine(img,arg[1],arg[2],arg[3],arg[4],gdStyled);
200 				if (!quiet) fprintf(verbose_out,"colour = current style");
201 			} else {
202 				colour=get_colour(infile,img);
203 				gdImageLine(img,arg[1],arg[2],arg[3],arg[4],colour);
204 			}
205 			if (!quiet) fprintf(verbose_out,")\n");
206 			break;
207 
208 
209 		case DLINE:     /*      gdImageDashedLine()     */
210 			for(i=1;i<=4;i++){
211 				arg[i]=get_number(infile);
212 			}
213 			if (!quiet)
214 				fprintf(verbose_out,"## Dashed Line ## drawn from %d,%d to %d,%d. (",
215 			    arg[1],arg[2],arg[3],arg[4]);
216 			if( brush_on ){
217 				sync_input(infile);
218 				gdImageDashedLine(img,arg[1],arg[2],arg[3],arg[4],gdBrushed);
219 				if (!quiet) fprintf(verbose_out,"colour = current brush");
220 			} else if ( style_on ) {
221 				sync_input(infile);
222 				gdImageDashedLine(img,arg[1],arg[2],arg[3],arg[4],gdStyled);
223 				if (!quiet) fprintf(verbose_out,"colour = current style");
224 			} else{
225 				colour=get_colour(infile,img);
226 				gdImageDashedLine(img,arg[1],arg[2],arg[3],arg[4],colour);
227 			}
228 			if (!quiet) fprintf(verbose_out,")\n");
229 			break;
230 
231 		case SQUARE:      /*      gdImageRectangle()      */
232 			for(i=1;i<=3;i++){
233 				arg[i]=get_number(infile);
234 			}
235 			side = arg[3];
236 			arg[3] = arg[1] + side; arg[4] = arg[2] + side;
237 			if (!quiet) fprintf(verbose_out,"## Square ## drawn at %d,%d, side %d (",
238 			    arg[1],arg[2],side);
239 			if( brush_on ){
240 				sync_input(infile);
241 				gdImageRectangle(img,arg[1],arg[2],arg[3],arg[4],gdBrushed);
242 				if (!quiet) fprintf(verbose_out,"colour = current brush");
243 			} else if ( style_on ) {
244 				sync_input(infile);
245 				gdImageRectangle(img,arg[1],arg[2],arg[3],arg[4],gdStyled);
246 				if (!quiet) fprintf(verbose_out,"colour = current style");
247 			} else{
248 				colour=get_colour(infile,img);
249 				gdImageRectangle(img,arg[1],arg[2],arg[3],arg[4],colour);
250 			}
251 			if (!quiet) fprintf(verbose_out,")\n");
252 			break;
253 
254 		case FSQUARE:     /*      gdImageFilledRectangle() */
255 			for(i=1;i<=3;i++){
256 				arg[i]=get_number(infile);
257 			}
258 			side = arg[3];
259 			arg[3] = arg[1] + side; arg[4] = arg[2] + side;
260 			if (!quiet)
261 				fprintf(verbose_out,"## Filled Square ## drawn from %d,%d, side %d. (",
262 			    arg[1],arg[2],side);
263 			if( tile_on ){
264 				sync_input(infile);
265 				gdImageFilledRectangle(img,arg[1],arg[2],arg[3],arg[4],gdTiled);
266 				if (!quiet) fprintf(verbose_out,"colour = current tile");
267 			} else{
268 				colour=get_colour(infile,img);
269 				gdImageFilledRectangle(img,arg[1],arg[2],arg[3],arg[4],colour);
270 			}
271 			if (!quiet) fprintf(verbose_out,")\n");
272 			break;
273 
274 		case RECT:      /*      gdImageRectangle()      */
275 			for(i=1;i<=4;i++){
276 				arg[i]=get_number(infile);
277 			}
278 			if (!quiet) fprintf(verbose_out,"## Rectangle ## drawn from %d,%d to %d,%d. (",
279 			    arg[1],arg[2],arg[3],arg[4]);
280 
281 			/* Check location of vertices given and swap if necessary */
282 			if((arg[1] > arg[3]) && (arg[4] > arg[2])) {
283 				swap(&arg[1],&arg[3]);
284 			} else if((arg[1] > arg[3]) && (arg[2] > arg[4])) {
285 				swap(&arg[1],&arg[3]);
286 				swap(&arg[2],&arg[4]);
287 			} else if((arg[3] > arg[1]) && (arg[2] > arg[4])) {
288 				swap(&arg[2],&arg[4]);
289 			}
290 
291 			if( brush_on ){
292 				sync_input(infile);
293 				gdImageRectangle(img,arg[1],arg[2],arg[3],arg[4],gdBrushed);
294 				if (!quiet) fprintf(verbose_out,"colour = current brush");
295 			} else if ( style_on ) {
296 				sync_input(infile);
297 				gdImageRectangle(img,arg[1],arg[2],arg[3],arg[4],gdStyled);
298 				if (!quiet) fprintf(verbose_out,"colour = current style");
299 			} else{
300 				colour=get_colour(infile,img);
301 				gdImageRectangle(img,arg[1],arg[2],arg[3],arg[4],colour);
302 			}
303 			if (!quiet) fprintf(verbose_out,")\n");
304 			break;
305 
306 		case FRECT:     /*      gdImageFilledRectangle() */
307 			for(i=1;i<=4;i++){
308 				arg[i]=get_number(infile);
309 			}
310 			if (!quiet) fprintf(verbose_out,"## Filled Rectangle ## drawn from %d,%d to %d,%d. (",
311 			    arg[1],arg[2],arg[3],arg[4]);
312 
313 			/* Check location of vertices given and swap if necessary */
314 			if((arg[1] > arg[3]) && (arg[4] > arg[2])) {
315 				swap(&arg[1],&arg[3]);
316 			} else if((arg[1] > arg[3]) && (arg[2] > arg[4])) {
317 				swap(&arg[1],&arg[3]);
318 				swap(&arg[2],&arg[4]);
319 			} else if((arg[3] > arg[1]) && (arg[2] > arg[4])) {
320 				swap(&arg[2],&arg[4]);
321 			}
322 
323 			if( tile_on ){
324 				sync_input(infile);
325 				gdImageFilledRectangle(img,arg[1],arg[2],arg[3],arg[4],gdTiled);
326 				if (!quiet) fprintf(verbose_out,"colour = current tile");
327 			} else{
328 				colour=get_colour(infile,img);
329 				gdImageFilledRectangle(img,arg[1],arg[2],arg[3],arg[4],colour);
330 			}
331 			if (!quiet) fprintf(verbose_out,")\n");
332 			break;
333 
334 		case POLY:      /* gdImagePolygon() */
335 			done = FALSE; i=0;
336 
337 			if (!quiet) fprintf(verbose_out,"## Polygon ## (");
338 			colour=get_colour(infile,img);
339 			if (!quiet) fprintf(verbose_out,") ");
340 
341 			arg[i++] = get_number(infile); /* get first point */
342 			arg[i++] = get_number(infile);
343 
344 			while( ! done ){     /* get next point until EOL*/
345 				for(c=0; c<=1 ;c++){
346 					arg[i++]=get_number(infile);
347 				}
348 				if (!quiet) fprintf(verbose_out,"%d,%d to %d,%d; ",
349 					arg[i-4],arg[i-3],arg[i-2],arg[i -1]);
350 			}
351 
352 			num_entries = i / 2;  i=0;
353 			for(n=0; n<num_entries; n++)
354 			{
355 				points[n].x = arg[i++];
356 				points[n].y = arg[i++];
357 			}
358 			if( brush_on ) {
359 				gdImagePolygon(img, points, num_entries, gdBrushed);
360 			} else if ( style_on ) {
361 				gdImagePolygon(img, points, num_entries, gdStyled);
362 			} else {
363 				gdImagePolygon(img, points, num_entries, colour);
364 			}
365 
366 			done = FALSE;
367 			if (!quiet) fprintf(verbose_out,"\n");
368 			break;
369 
370 		case FPOLY:      /* gdImageFilledPolygon() */
371 			done = FALSE; i=0;
372 
373 			if (!quiet) fprintf(verbose_out,"## Filled Polygon ## (");
374 			colour=get_colour(infile,img);
375 			if (!quiet) fprintf(verbose_out,") ");
376 
377 			arg[i++] = get_number(infile); /* get first point */
378 			arg[i++] = get_number(infile);
379 
380 			while( ! done ){     /* get next point until EOL*/
381 				for(c=0; c<=1 ;c++){
382 					arg[i++]=get_number(infile);
383 				}
384 				if (!quiet) fprintf(verbose_out,"%d,%d to %d,%d; ",
385 					arg[i-4],arg[i-3],arg[i-2],arg[i -1]);
386 			}
387 
388 			num_entries = i / 2;  i=0;
389 			for(n=0; n<num_entries; n++)
390 			{
391 				points[n].x = arg[i++];
392 				points[n].y = arg[i++];
393 			}
394 
395 			if( tile_on )
396 			{
397 				gdImageFilledPolygon(img, points, num_entries, gdTiled);
398 			}
399 			else
400 			{
401 				gdImageFilledPolygon(img, points, num_entries, colour);
402 			}
403 			done = FALSE;
404 			if (!quiet) fprintf(verbose_out,"\n");
405 			break;
406 
407 		case ARC:       /*      gdImageArc()            */
408 			for(i=1;i<7;i++){
409 				arg[i]=get_number(infile);
410 			}
411 			if (!quiet) {
412 				fprintf(verbose_out,"## Arc ## Centred at %d,%d, width %d, height %d,\n",
413 				    arg[1],arg[2],arg[3],arg[4]);
414 				fprintf(verbose_out,"          starting at %d deg, ending at %d deg. (",
415 				    arg[5],arg[6]);
416 			}
417 			if( brush_on ){
418 			sync_input(infile);
419 			gdImageArc(img,arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],gdBrushed);
420 			if(!quiet) fprintf(verbose_out,"colour = current brush");
421 			} else if ( style_on ) {
422 			sync_input(infile);
423 			gdImageArc(img,arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],gdStyled);
424 			if(!quiet) fprintf(verbose_out,"colour = current style");
425 			} else{
426 			colour=get_colour(infile,img);
427 			gdImageArc(img,arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],colour);
428 			}
429 			if (!quiet) fprintf(verbose_out,")\n");
430 			break;
431 
432 		case ELLIPSE:       /*      gdImageArc()            */
433 			for(i=1;i<5;i++){
434 				arg[i]=get_number(infile);
435 			}
436 			if (!quiet) {
437 				fprintf(verbose_out,"## Ellipse ## Centred at %d,%d, width %d, height %d. (",
438 				    arg[1],arg[2],arg[3],arg[4]);
439 			}
440 			if( brush_on ){
441 			sync_input(infile);
442 			gdImageArc(img,arg[1],arg[2],arg[3],arg[4],0,360,gdBrushed);
443 			if(!quiet) fprintf(verbose_out,"colour = current brush");
444 			} else if ( style_on ) {
445 			sync_input(infile);
446 			gdImageArc(img,arg[1],arg[2],arg[3],arg[4],0,360,gdStyled);
447 			if(!quiet) fprintf(verbose_out,"colour = current style");
448 			} else{
449 			colour=get_colour(infile,img);
450 			gdImageArc(img,arg[1],arg[2],arg[3],arg[4],0,360,colour);
451 			}
452 			if (!quiet) fprintf(verbose_out,")\n");
453 			break;
454 
455 		case CIRCLE:
456 		case FCIRCLE:
457 			for(i=1;i<4;i++){
458 				arg[i]=get_number(infile);
459 			}
460 			if (!quiet) {
461 				if (type == CIRCLE) {
462 					fprintf(verbose_out,"## Circle ## Centred at %d,%d, diameter %d (",
463 						arg[1],arg[2],arg[3]);
464 				}
465 				else {
466 					fprintf(verbose_out,"## Filled Circle ## Centred at %d,%d, diameter %d (",
467 						arg[1],arg[2],arg[3]);
468 				}
469 			}
470 			if( brush_on ){
471 			sync_input(infile);
472 			gdImageArc(img,arg[1],arg[2],arg[3],arg[3],0,360,gdBrushed);
473 			if(!quiet) fprintf(verbose_out,"colour = current brush");
474 			} else if ( style_on ) {
475 			sync_input(infile);
476 			gdImageArc(img,arg[1],arg[2],arg[3],arg[3],0,360,gdStyled);
477 			if(!quiet) fprintf(verbose_out,"colour = current style");
478 			} else{
479 			colour=get_colour(infile,img);
480 			gdImageArc(img,arg[1],arg[2],arg[3],arg[3],0,360,colour);
481 			}
482 			if (type == FCIRCLE) gdImageFillToBorder(img,arg[1],arg[2],colour,colour);
483 			if (!quiet) fprintf(verbose_out,")\n");
484 			break;
485 
486 
487 		case SETPIXEL:      /*	gdImageSetPixel  */
488 			for(i=1;i<=2;i++){
489 				arg[i]=get_number(infile);
490 			}
491 			if (!quiet) fprintf(verbose_out,"## Set Pixel ## at %d,%d to ",arg[1],arg[2]);
492 			colour=get_colour(infile,img);
493 			gdImageSetPixel(img,arg[1],arg[2],colour);
494 			if (!quiet) fprintf(verbose_out,".\n");
495 			break;
496 
497 		case GETPIXEL:      /*	gdImageGetPixel  */
498 			for(i=1;i<=2;i++){
499 				arg[i]=get_number(infile);
500 			}
501 			if (!quiet) fprintf(verbose_out,"## Get Pixel ## at %d,%d:",arg[1],arg[2]);
502 			colour = gdImageGetPixel(img,arg[1],arg[2]);
503 			arg[3] = gdImageRed(img,colour);
504 			arg[4] = gdImageGreen(img,colour);
505 			arg[5] = gdImageBlue(img,colour);
506 			if (!quiet) fprintf(verbose_out," %d, %d, %d = %d.\n",
507 				arg[3],arg[4],arg[5],colour);
508 			break;
509 
510 		case COLOURCHANGE:
511 			for(i=1;i<=6;i++){
512 				arg[i]=get_number(infile);
513 			}
514 			/* colour is new colour */
515 			colour = gdImageColorExact(img,arg[4],arg[5],arg[6]);
516 			if (colour == -1) {
517 				colour = gdImageColorAllocate(img,arg[4],arg[5],arg[6]);
518 			}
519 			/* colour1 is old colour */
520 			colour1 = gdImageColorExact(img,arg[1],arg[2],arg[3]);
521 			if (colour1 == -1) {
522 				colour1 = gdImageColorAllocate(img,arg[1],arg[2],arg[3]);
523 			}
524 			size_x = gdImageSX(img);
525 			size_y = gdImageSY(img);
526 			for(x=0; x < size_x; x++) {
527 				for(y=0; y < size_y; y++) {
528 					colour2 = gdImageGetPixel(img,x,y);
529 					if(colour2 == colour1) {
530 						gdImageSetPixel(img,x,y,colour);
531 					}
532 				}
533 			}
534 			if (!quiet) fprintf(verbose_out,"## Colour Change ## %d,%d,%d (%d) changed to %d,%d,%d (%d).\n",
535 				arg[1],arg[2],arg[3],colour1,arg[4],arg[5],arg[6],colour);
536 
537 			break;
538 		case ROTATE:
539 			i=get_number(infile);
540 			if(! ((i == 90) || (i == 180) || (i == 270))) {
541 				fprintf(verbose_out,"Error: line %d. Rotation must be 90, 180 or 270.\n", line_number);
542 				break;
543 			}
544 			if (!quiet) fprintf(verbose_out,"## Rotate ## by %d degrees.\n",i);
545 			size_x = gdImageSX(img);
546 			size_y = gdImageSY(img);
547 			switch(i) {
548 				case 180:
549 					new_img = gdImageCreate(size_x,size_y);
550 					break;
551 				case 90:
552 				case 270:
553 					new_img = gdImageCreate(size_y,size_x);
554 					break;
555 			}
556 			for(x=0; x < size_x; x++) {
557 				for(y=0; y < size_y; y++) {
558 					int r, g, b;
559 					colour = gdImageGetPixel(img,x,y);
560 					r = gdImageRed(img,colour);
561 					g = gdImageGreen(img,colour);
562 					b = gdImageBlue(img,colour);
563 					colour1 = gdImageColorExact(new_img,r,g,b);
564 					if (colour1 == -1) { colour1 = gdImageColorAllocate(new_img,r,g,b); }
565 					switch(i) {
566 						case 90:
567 							gdImageSetPixel(new_img,(size_y - y - 1),x,colour1);
568 							break;
569 						case 180:
570 							gdImageSetPixel(new_img,(size_x - x - 1),(size_y - y - 1),colour1);
571 							break;
572 						case 270:
573 							gdImageSetPixel(new_img,y,(size_x - x - 1),colour1);
574 							break;
575 					}
576 				}
577 			}
578 			gdImageDestroy(img);
579 			img = new_img;
580 			break;
581 
582 		case FILL:      /*      gdImageFill() */
583 			for(i=1;i<=2;i++){
584 				arg[i]=get_number(infile);
585 			}
586 			if (!quiet) fprintf(verbose_out,"## Fill ## from %d,%d. (", arg[1],arg[2]);
587 			if( tile_on ){
588 				sync_input(infile);
589 				gdImageFill(img,arg[1],arg[2],gdTiled);
590 			} else {
591 				colour=get_colour(infile,img);
592 				gdImageFill(img,arg[1],arg[2],colour);
593 			}
594 			if (!quiet) fprintf(verbose_out,")\n");
595 			break;
596 
597 		case FILLTOBORDER:      /*	gdImageFillToBorder()	*/
598 			for(i=1;i<=2;i++){
599 				arg[i]=get_number(infile);
600 			}
601 			if (!quiet) fprintf(verbose_out,"## Fill ## from %d,%d. (", arg[1],arg[2]);
602 			colour=get_colour(infile,img);
603 			if (!quiet) fprintf(verbose_out,") to Border of ");
604 			if( tile_on ){
605 				if (!quiet)
606 					fprintf(verbose_out,"Line %d skipped: Cannot use tile with filltoborder.\n",line_number);
607 				sync_input(infile);
608 			} else {
609 				colour2=get_colour(infile,img);
610 				gdImageFillToBorder(img,arg[1],arg[2],colour,colour2);
611 			}
612 			if (!quiet) fprintf(verbose_out,".\n");
613 			break;
614 
615 		case STRINGUP:
616 			up = TRUE;
617 		case STRING:
618 			if (!quiet && up) fprintf(verbose_out,"## String (Up) ## (");
619 			if (!quiet && !up) fprintf(verbose_out,"## String ## (");
620 			colour=get_colour(infile,img);
621 			if (!quiet) fprintf(verbose_out,") at location ");
622 			for(i=1;i<=2;i++){
623 				arg[i]=get_number(infile);
624 			}
625 			if (!quiet) fprintf(verbose_out," %d,%d, ",arg[1],arg[2]);
626 			i = get_token(infile);
627 			s = get_string(infile);
628 			switch(i) {
629 				case TINY:
630 					gdFont = gdFontTiny;
631 					if (!quiet) fprintf(verbose_out,"[size: tiny] contents: %s\n",s);
632 					break;
633 				case SMALL:
634 					gdFont = gdFontSmall;
635 					if (!quiet) fprintf(verbose_out,"[size: small] contents: %s\n",s);
636 					break;
637 				case MEDIUM:
638 					gdFont = gdFontMediumBold;
639 					if (!quiet) fprintf(verbose_out,"[size: medium-bold] contents: %s\n",s);
640 					break;
641 				case LARGE:
642 					gdFont = gdFontLarge;
643 					if (!quiet) fprintf(verbose_out,"[size: large] contents: %s\n",s);
644 					break;
645 				case GIANT:
646 					gdFont = gdFontGiant;
647 					if (!quiet) fprintf(verbose_out,"[size: giant] contents: %s\n",s);
648 					break;
649 				default:
650 					if (!quiet) fprintf(verbose_out,"Error: line %d. Incorrect font size specifier.\n",
651 						line_number);
652 					break;
653 			}
654 			if( !up ) {
655 				gdImageString(img, gdFont, arg[1],arg[2], (unsigned char *) s, colour);
656 			} else {
657 				gdImageStringUp(img, gdFont, arg[1],arg[2], (unsigned char *) s, colour);
658 			}
659 			up = FALSE;
660 			break;
661 
662 		case SETBRUSH:
663 			s = get_string(infile);
664 			if ( (brushfile = fopen(s,"rb")) == NULL )
665 			{
666 				fprintf(stderr, "Failed to open brush file, %s\n",
667 					output_file);
668 				exit(1);
669 			}
670 			else
671 			{
672 				brush = gdImageCreateFromPng(brushfile);
673 				gdImageSetBrush(img,brush);
674 				brush_on = 1;
675 				if (!quiet) fprintf(verbose_out,"## Brush Set ## to: %s\n",s);
676 			}
677 			break;
678 
679 		case KILLBRUSH:
680 			brush_on = 0;
681 			if (!quiet) fprintf(verbose_out,"## Brush Killed ##\n");
682 			break;
683 
684 		case SETSTYLE:
685 			i=0;
686 			end_of_line = FALSE;
687 			if (!quiet) fprintf(verbose_out,"## Style Set ## Colours: (");
688 			while( ! end_of_line ){
689 				colour=get_colour(infile,img);
690 				if (!quiet && !end_of_line) fprintf(verbose_out,"), (");
691 				style[i++] = colour;
692 			}
693 			if (!quiet) fprintf(verbose_out,")\n");
694 			gdImageSetStyle(img, style, i-1);
695 			style_on = TRUE;
696 			end_of_line = FALSE;
697 			break;
698 
699 		case KILLSTYLE:
700 			style_on = 0;
701 			if (!quiet) fprintf(verbose_out,"## Style Killed ##\n");
702 			break;
703 
704 		case SETTILE:
705 			s = get_string(infile);
706 			if ( (tilefile = fopen(s,"rb")) == NULL )
707 			{
708 				fprintf(stderr, "Failed to open tile file, %s\n",
709 					output_file);
710 				exit(1);
711 			}
712 			else
713 			{
714 				tile = gdImageCreateFromPng(tilefile);
715 				gdImageSetTile(img,tile);
716 				tile_on = TRUE;
717 				if (!quiet) fprintf(verbose_out,"## Tile Set ## to: %s\n",s);
718 			}
719 			break;
720 
721 		case KILLTILE:
722 			tile_on = 0;
723 			if (!quiet) fprintf(verbose_out,"## Tile Killed ##\n");
724 			break;
725 
726 		case COPY:
727 			copy_to_img(infile, img, 0);
728 			break;
729 
730 		case COPYRESIZED:
731 			copy_to_img(infile, img, 1);
732 			break;
733 
734 		case TRANSPARENT:
735 			if (!quiet) fprintf(verbose_out,"## Make transparent ## [");
736 			colour=get_colour(infile,img);
737 			gdImageColorTransparent(img,colour);
738 			if (!quiet) fprintf(verbose_out,"]\n");
739 			break;
740 
741 		case INTERLACE:
742 			gdImageInterlace(img,1);
743 			if (!quiet) fprintf(verbose_out,"## Image is interlaced ##\n");
744 			break;
745 
746 		case SIZEX:
747 			size = gdImageSX(img);
748 			if (!quiet) fprintf(verbose_out,"## Size - X ## is %d\n",size);
749 			break;
750 
751 		case SIZEY:
752 			size = gdImageSY(img);
753 			if (!quiet) fprintf(verbose_out,"## Size - Y ## is %d\n",size);
754 			break;
755 
756 		case NAME:
757 			s = get_string(infile);
758 			if ( (outfile = fopen(s,"wb")) == NULL )
759 			{
760 				fprintf(stderr, "Failed to open output file, %s\n",
761 					output_file);
762 				exit(1);
763 			}
764 			else
765 			{
766 				if (!quiet) fprintf(verbose_out,"## Output to file %s ##\n",s);
767 			}
768 			break;
769 
770 		case TYPE:
771 			imgtype = get_token(infile);
772 			if(imgtype != JPEG && imgtype != PNG && imgtype != GIF){
773 				fprintf(verbose_out,"Error: line %d: Image type must be jpeg, gif or png.\n",line_number);
774 				exit(1);
775 			}
776 			break;
777 
778 		case QUALITY:
779 			i=get_number(infile);
780 			jp_quality = i;
781 			if(imgtype != JPEG){
782 				fprintf(verbose_out,"Error: line %d: Cannot use quality directive unless type is set to jpeg first.\n",line_number);
783 				exit(1);
784 			}
785 			if(i < 0 || i > 95){
786 				fprintf(verbose_out,"Line %d skipped: Image quality must be within the range 0-95. %d is not an acceptable value.\n",line_number, i);
787 				exit(1);
788 			}
789 
790 			break;
791 
792 		case COMMENT:
793 			sync_input(infile);
794 			break;
795 
796 		case EMPTY:
797 			break;
798 
799 		case END:
800 			gdImagePng(img,outfile);
801 			fclose(outfile);
802 			gdImageDestroy(img);
803 			written_out = TRUE;
804 			if (!quiet) fprintf(verbose_out,"End of image directives.\n");
805 			if(!finished) { goto START; } else { goto FINISH; }
806 
807 		default:
808 			if( ! finished ) {
809 				if (!quiet) fprintf(verbose_out,
810 					"Line %d skipped: bad directive or syntax error.\n",line_number);
811 			} else {
812 				if (!quiet) fprintf(verbose_out,"EOF: fly finished.\n");
813 			}
814 			sync_input(infile);
815 			break;
816 		}
817 	}	while( ! finished );
818 
819 	/*  Write the gd to the image output file and exit */
820 FINISH:	if(!written_out && img) {
821 		if(imgtype == JPEG) {
822 			gdImageJpeg(img,outfile,jp_quality);
823 		} else if(imgtype == GIF) {
824 			gdImageGif(img,outfile);
825 		} else {
826 			gdImagePng(img,outfile);
827 		}
828 		fclose(outfile);
829 		gdImageDestroy(img);
830 	}
831 	exit(0);
832 }
833 
834 /******************************************************************************
835 **
836 **  get_string
837 **
838 **  returns a string from the current input line: from the current point
839 **  to the end of line.
840 **
841 **  Used by:
842 **  string,stringup,chr,chrup,setbrush,settile
843 **
844 ******************************************************************************/
get_string(FILE * infile)845 char *get_string(FILE *infile){
846 	int     c,i=0;
847 	char    temp[1024], *string, *p;
848 
849 	while(( (c=getc(infile)) != EOF ) && ( c != '\n') ){
850 		temp[i++]=c;
851 	}
852 
853 	if( c == '\n' ) { line_number++; }
854 	if( c == EOF ) {
855 		finished = TRUE;
856 	}
857 	temp[i]='\0';
858 	p=temp;
859 	string=(char *)my_newmem(strlen(p));
860 	sprintf(string,"%s",temp);
861 
862 	return string;
863 }
864 
865 /******************************************************************************
866 **
867 **  get_token
868 **
869 **  Gets the next "token" from the input line.
870 **
871 **  Used by:
872 **  all
873 **
874 ******************************************************************************/
get_token(FILE * infile)875 int get_token(FILE *infile){
876 	int     c,i=0;
877 	char    temp[80], *input_type, *p;
878 	char    *line="line",
879 		*poly="poly",
880 		*fpoly="fpoly",
881 		*rect="rect",
882 		*frect="frect",
883 		*square="square",
884 		*fsquare="fsquare",
885 		*dline="dline",
886 		*arc="arc",
887 		*size="size",
888 		*new="new",
889 		*existing="existing",
890 		*setpixel="setpixel",
891 		*getpixel="getpixel",
892 		*filltoborder="filltoborder",
893 		*fill="fill",
894 		*string="string",
895 		*stringup="stringup",
896 		*copy="copy",
897 		*copyresized="copyresized",
898 		*transparent="transparent",
899 		*interlace="interlace",
900 		*sizex="sizex",
901 		*sizey="sizey",
902 		*setbrush="setbrush",
903 		*killbrush="killbrush",
904 		*settile="settile",
905 		*killtile="killtile",
906 		*setstyle="setstyle",
907 		*killstyle="killstyle",
908 		*tiny="tiny",
909 		*small="small",
910 		*medium="medium",
911 		*large="large",
912 		*giant="giant",
913 		*zero="0",
914 		*one="1",
915 		*circle="circle",
916 		*fcircle="fcircle",
917 		*comment="#",
918 		*name="name",
919 		*end="end",
920 		*ellipse="ellipse",
921 		*colourchange="colourchange",
922 		*rotate="rotate",
923 		*type="type",
924 		*quality="quality",
925 		*gif="gif",
926 		*png="png",
927 		*jpeg="jpeg";
928 
929 	while(((c=getc(infile))!=EOF)&&(c!=' ')&&(c!='\n')&&(c!=',')&&(c!='=')&&(c!='\r'))
930 	{
931 		temp[i++]=c;
932 		if(temp[0] == '#') break;
933 	}
934 	if (c == EOF) finished = TRUE;
935 
936 	if (c == '\n' || c == '\r') {
937 		line_number++;
938 		if (i == 0) { return EMPTY; }
939 	} else if (c == EOF) {
940 		return (int)NULL;
941 	}
942 
943 	temp[i]='\0';
944 	p=temp;
945 	input_type=(char*)my_newmem(strlen(p));
946 	sprintf(input_type,"%s",temp);
947 
948 	if( strcmp(input_type, line) == 0 ){
949 		free(input_type);
950 		return LINE;
951 	}
952 	if( strcmp(input_type, rect) == 0 ){
953 		free(input_type);
954 		return RECT;
955 	}
956 	if( strcmp(input_type, square) == 0 ){
957 		free(input_type);
958 		return SQUARE;
959 	}
960 	if( strcmp(input_type, fsquare) == 0 ){
961 		free(input_type);
962 		return FSQUARE;
963 	}
964 	if( strcmp(input_type, dline) == 0 ){
965 		free(input_type);
966 		return DLINE;
967 	}
968 	if( strcmp(input_type, frect) == 0 ){
969 		free(input_type);
970 		return FRECT;
971 	}
972 	if( strcmp(input_type, fcircle) == 0 ){
973 		free(input_type);
974 		return FCIRCLE;
975 	}
976 	if( strcmp(input_type, circle) == 0 ){
977 		free(input_type);
978 		return CIRCLE;
979 	}
980 	if( strcmp(input_type, arc) == 0 ){
981 		free(input_type);
982 		return ARC;
983 	}
984 	if( strcmp(input_type, poly) == 0 ){
985 		free(input_type);
986 		return POLY;
987 	}
988 	if( strcmp(input_type, fpoly) == 0 ){
989 		free(input_type);
990 		return FPOLY;
991 	}
992 	if( strcmp(input_type, size) == 0 ){
993 		free(input_type);
994 		return SIZE;
995 	}
996 	if( strcmp(input_type, new) == 0 ){
997 		free(input_type);
998 		return NEW;
999 	}
1000 	if( strcmp(input_type, existing) == 0 ){
1001 		free(input_type);
1002 		return EXISTING;
1003 	}
1004 	if( strcmp(input_type, copyresized) == 0 ){
1005 		free(input_type);
1006 		return COPYRESIZED;
1007 	}
1008 	if( strcmp(input_type, copy) == 0 ){
1009 		free(input_type);
1010 		return COPY;
1011 	}
1012 	if( strcmp(input_type, fill) == 0 ){
1013 		free(input_type);
1014 		return FILL;
1015 	}
1016 	if( strcmp(input_type, filltoborder) == 0 ){
1017 		free(input_type);
1018 		return FILLTOBORDER;
1019 	}
1020 	if( strcmp(input_type, setpixel) == 0 ){
1021 		free(input_type);
1022 		return SETPIXEL;
1023 	}
1024 	if( strcmp(input_type, getpixel) == 0 ){
1025 		free(input_type);
1026 		return GETPIXEL;
1027 	}
1028 	if( strcmp(input_type, string) == 0 ){
1029 		free(input_type);
1030 		return STRING;
1031 	}
1032 	if( strcmp(input_type, stringup) == 0 ){
1033 		free(input_type);
1034 		return STRINGUP;
1035 	}
1036 	if( strcmp(input_type, sizex) == 0 ){
1037 		free(input_type);
1038 		return SIZEX;
1039 	}
1040 	if( strcmp(input_type, sizey) == 0 ){
1041 		free(input_type);
1042 		return SIZEY;
1043 	}
1044 	if( strcmp(input_type, setbrush) == 0 ){
1045 		free(input_type);
1046 		return SETBRUSH;
1047 	}
1048 	if( strcmp(input_type, killbrush) == 0 ){
1049 		free(input_type);
1050 		return KILLBRUSH;
1051 	}
1052 	if( strcmp(input_type, settile) == 0 ){
1053 		free(input_type);
1054 		return SETTILE;
1055 	}
1056 	if( strcmp(input_type, killtile) == 0 ){
1057 		free(input_type);
1058 		return KILLTILE;
1059 	}
1060 	if( strcmp(input_type, setstyle) == 0 ){
1061 		free(input_type);
1062 		return SETSTYLE;
1063 	}
1064 	if( strcmp(input_type, killstyle) == 0 ){
1065 		free(input_type);
1066 		return KILLSTYLE;
1067 	}
1068 	if( strcmp(input_type, interlace) == 0 ){
1069 		free(input_type);
1070 		return INTERLACE;
1071 	}
1072 	if( strcmp(input_type, transparent) == 0 ){
1073 		free(input_type);
1074 		return TRANSPARENT;
1075 	}
1076 	if( strcmp(input_type, tiny) == 0 ){
1077 		free(input_type);
1078 		return TINY;
1079 	}
1080 	if( strcmp(input_type, zero) == 0 ){
1081 		free(input_type);
1082 		return SMALL;
1083 	}
1084 	if( strcmp(input_type, small) == 0 ){
1085 		free(input_type);
1086 		return SMALL;
1087 	}
1088 	if( strcmp(input_type, medium) == 0 ){
1089 		free(input_type);
1090 		return MEDIUM;
1091 	}
1092 	if( strcmp(input_type, one) == 0 ){
1093 		free(input_type);
1094 		return LARGE;
1095 	}
1096 	if( strcmp(input_type, large) == 0 ){
1097 		free(input_type);
1098 		return LARGE;
1099 	}
1100 	if( strcmp(input_type, giant) == 0 ){
1101 		free(input_type);
1102 		return GIANT;
1103 	}
1104 	if( strcmp(input_type, name) == 0){
1105 		free(input_type);
1106 		return NAME;
1107 	}
1108 	if( strcmp(input_type, comment) == 0){
1109 		free(input_type);
1110 		return COMMENT;
1111 	}
1112 	if( strcmp(input_type, end) == 0){
1113 		free(input_type);
1114 		return END;
1115 	}
1116 	if( strcmp(input_type, ellipse) == 0){
1117 		free(input_type);
1118 		return ELLIPSE;
1119 	}
1120 	if( strcmp(input_type, colourchange) == 0){
1121 		free(input_type);
1122 		return COLOURCHANGE;
1123 	}
1124 	if( strcmp(input_type, rotate) == 0){
1125 		free(input_type);
1126 		return ROTATE;
1127 	}
1128 	if( strcmp(input_type, type) == 0){
1129 		free(input_type);
1130 		return TYPE;
1131 	}
1132 	if( strcmp(input_type, quality) == 0){
1133 		free(input_type);
1134 		return QUALITY;
1135 	}
1136 	if( strcmp(input_type, gif) == 0){
1137 		free(input_type);
1138 		return GIF;
1139 	}
1140 	if( strcmp(input_type, png) == 0){
1141 		free(input_type);
1142 		return PNG;
1143 	}
1144 	if( strcmp(input_type, jpeg) == 0){
1145 		free(input_type);
1146 		return JPEG;
1147 	}
1148 	free(input_type);
1149 	ungetc(c,infile);
1150 	return (int)NULL;
1151 }
1152 
1153 /******************************************************************************
1154 **
1155 **  get_number
1156 **
1157 **  grabs a number from the current input line. Reads up to a comma or newline.
1158 **
1159 **  Used by:
1160 **  line, dline, rect, frect, poly, fpoly, arc, setpixel, fill, filltoborder,
1161 **  string, stringup, chr, chrup.
1162 **
1163 ******************************************************************************/
get_number(FILE * infile)1164 int get_number(FILE *infile){
1165 	int     c,i=0;
1166 	char    tmp[80];
1167 
1168 	while(( (c=getc(infile)) != EOF ) && ( c != ',') && (c != '\n')){
1169 		tmp[i++]=c;
1170 	}
1171 	if( c == '\n' ) { line_number++; }
1172 	if( c != EOF ) {
1173 		tmp[i]='\0';
1174 		if( c == '\n') {
1175 			done = TRUE;
1176 		}
1177 		return atoi(tmp);
1178 	} else {
1179 		tmp[i]='\0';
1180 		finished = TRUE;
1181 		return atoi(tmp);
1182 	}
1183 }
1184 
1185 /******************************************************************************
1186 **
1187 **  get_colour
1188 **
1189 **  Gets a R,G,B colour value from the current input line.
1190 **  Returns the integer colour index.
1191 **
1192 **  Used by:
1193 **  line, dline, rect, frect, poly, fpoly, arc, setpixel, fill, filltoborder,
1194 **  string, stringup, chr, chrup, setstyle, transparent.
1195 **
1196 ******************************************************************************/
get_colour(FILE * infile,gdImagePtr img)1197 int get_colour(FILE *infile, gdImagePtr img){
1198 	int     c,i,count,colourIndex, colour[3];
1199 	char    temp[5];
1200 
1201 	for(count=0;count<3;count++){
1202 		i=0;
1203 		while(( (c=getc(infile)) != EOF )&&( c !=',')&&(c !='\n')){
1204 			temp[i++]=c;
1205 		}
1206 		if( c == '\n' ) { line_number++; }
1207 		temp[i]='\0';
1208 		if( c == '\n') end_of_line = TRUE;
1209 		if( c == EOF ) finished = TRUE;
1210 		colour[count]=atoi(temp);
1211 	}
1212 	if( (c=getc(infile)) != EOF )  {
1213 		ungetc(c,infile);
1214 	} else {
1215 		finished = TRUE;
1216 	}
1217 	/* Original comments from Claus Hofmann. I don't have any idea what they
1218          * mean, but I'll put 'em here anyhow.
1219 	 */
1220 	/* zuerst nachschauen, ob es die gewuenschte Farbe schon in der
1221 	 * colortable gibt. Erst wenn es die Farbe nicht gibt einen neuen
1222 	 * Index in der Tabelle allocieren.
1223 	 */
1224 	colourIndex=gdImageColorExact(img,colour[0],colour[1],colour[2]);
1225 	if (colourIndex == -1) {
1226 		colourIndex=gdImageColorAllocate(img,colour[0],colour[1],colour[2]);
1227 	}
1228 	if (!quiet)
1229 		fprintf(verbose_out,"colour: %d, %d, %d = %d",
1230 			colour[0],colour[1],colour[2], colourIndex);
1231 	return colourIndex;
1232 
1233 }
1234 
1235 /******************************************************************************
1236 **
1237 **  copy_to_img
1238 **
1239 **  Copies a img to the current image. Location of img and coordinates are
1240 **  specified on the input line.
1241 **
1242 **  Used by:
1243 **  copy, copyresized.
1244 **
1245 ******************************************************************************/
copy_to_img(FILE * infile,gdImagePtr img,int resize)1246 void copy_to_img(FILE *infile, gdImagePtr img, int resize){
1247 	int     i=0,arg[8];
1248 	char    *filename;
1249 	FILE	*img_to_copy;
1250 	gdImagePtr	img_file;
1251 
1252 	/*	Get the coordinates	*/
1253 	for(i=0;i<=5;i++){
1254 		arg[i]=get_number(infile);
1255 	}
1256 	if( resize == 1 ){
1257 		arg[i]=get_number(infile);
1258 		i++;
1259 		arg[i]=get_number(infile);
1260 	}
1261 	if((img_to_copy = get_file(&line_number, &filename)) == NULL) {
1262 		fprintf(stderr,"Error: Cannot read existing image file \"%s\"\n",
1263 			filename);
1264 		exit(1);
1265 	}
1266 	if(imgtype == JPEG) {
1267 		img_file = gdImageCreateFromJpeg(img_to_copy);
1268 	} else if(imgtype == GIF) {
1269 		img_file = gdImageCreateFromGif(img_to_copy);
1270 	} else {
1271 		img_file = gdImageCreateFromPng(img_to_copy);
1272 	}
1273 	if (img_file == NULL) {
1274 		fprintf(stderr, "Error: Cannot read image file \"%s\" of type \"%s\"\n",
1275 			filename, imgtype == GIF ? "gif" : (imgtype == JPEG ? "jpeg" : "png"));
1276 		exit(1);
1277 	}
1278 	fclose(img_to_copy);
1279 
1280 	if( resize == 1 )
1281 	{
1282 		if((arg[0] == -1)&&(arg[1] == -1) &(arg[2] == -1)&&(arg[3] == -1)){
1283 			if(!quiet) fprintf(verbose_out,"Copying %s (entire area) to area %d,%d - %d,%d.\n",
1284 				filename,arg[4],arg[5],arg[6], arg[7]);
1285 			gdImageCopyResized(img, img_file, arg[4], arg[5], 0, 0,
1286 				(arg[6] - arg[4]), (arg[7] - arg[5]), img_file->sx, img_file->sy);
1287 		}
1288 		else {
1289 			if(!quiet) fprintf(verbose_out,"Copying %s (area %d,%d - %d,%d) to area %d,%d - %d,%d.\n",
1290 				filename,arg[4],arg[5],arg[6], arg[7],arg[0],arg[1],arg[2],arg[3]);
1291 			gdImageCopyResized(img, img_file, arg[4], arg[5], arg[0], arg[1],
1292 				(arg[6] - arg[4] + 1), (arg[7] - arg[5] + 1), (arg[2] - arg[0] + 1),
1293 				(arg[3] - arg[1] + 1));
1294 		}
1295 	}
1296 	else
1297 	{
1298 		if ((arg[2] == -1)&&(arg[3] == -1) &(arg[4] == -1)&&(arg[5] == -1)) {
1299 			/* another comment from Claus Hofmann. I'm getting curious now. */
1300 			/* gesamtes Bild
1301 			*/
1302 			arg[2] = arg[3] = 0;
1303 			arg[4] = img_file->sx;
1304 			arg[5] = img_file->sy;
1305 		}
1306 		if(!quiet) fprintf(verbose_out,"Copying %s to coordinates %d,%d\n",filename,arg[0],arg[1]);
1307 		gdImageCopy(img, img_file, arg[0], arg[1], arg[2], arg[3],
1308 					arg[4] - arg[2], arg[5] - arg[3]);
1309 	}
1310 	gdImageDestroy(img_file);
1311 
1312 	return;
1313 }
1314 
1315 /******************************************************************************
1316 **
1317 **  sync_input
1318 **
1319 **  synchronises input line - reads to end of line, leaving file pointer
1320 **  at first character of next line.
1321 **
1322 **  Used by:
1323 **  main program - error handling.
1324 **
1325 ******************************************************************************/
1326 void
sync_input(FILE * infile)1327 sync_input(FILE *infile)
1328 {
1329 	int c = 0;
1330 
1331 	if( c == '\n' ) return;
1332 	while( ( (c=getc(infile)) != EOF ) && (c != '\n') && (c != '\r')) ;
1333 	if( c == EOF ) finished = TRUE;
1334 	if( c == '\n' || c == '\r') line_number++;
1335 	return;
1336 }
1337 
1338 /******************************************************************************
1339 **
1340 **  process_args
1341 **
1342 **  processes the command line arguments
1343 **
1344 **  Used by:
1345 **  main program.
1346 **
1347 ******************************************************************************/
1348 int
process_args(int argc,char * argv[])1349 process_args(int argc, char *argv[])
1350 {
1351 	int c = 0, errflag=0;
1352 	extern char *optarg;
1353 	extern int optind;
1354 
1355 	while ((c=getopt(argc, argv, "qhvi:o:")) != EOF) {
1356 		switch (c) {
1357 			case 'q': quiet = TRUE;
1358 			        break;
1359 			case 'v':
1360 			case 'h': fprintf(stdout,"fly, version %s\n\n%s\n", version, help);
1361 			          exit(0);
1362 			        break;
1363 			case 'o': output_file=(char *)my_newmem(strlen(optarg)*sizeof(char));
1364 			          sprintf(output_file,"%s",optarg);
1365 			        break;
1366 			case 'i': input_file=(char *)my_newmem(strlen(optarg)*sizeof(char));
1367 			          sprintf(input_file,"%s",optarg);
1368 			        break;
1369 			case '?': errflag = 1;
1370 			        break;
1371 		}
1372 		if (errflag) {
1373 			fprintf(stderr,"%s\n", usage);
1374 			exit(1);
1375 		}
1376 	}
1377 	if( input_file ) {
1378 		if ( (infile = fopen(input_file,"r")) == NULL ) {
1379 			fprintf(stderr, "Failed to open input file, %s.\n",
1380 				input_file);
1381 			return FALSE;
1382 		}
1383 	} else {
1384 		infile = stdin;
1385 	}
1386 	if( output_file ) {
1387 		if ( (outfile = fopen(output_file,"wb")) == NULL ) {
1388 			fprintf(stderr, "Failed to open output file, %s.\n",
1389 				output_file);
1390 			return FALSE;
1391 		}
1392 		verbose_out = stdout;
1393 	} else {
1394 #ifdef WIN32
1395 		_setmode( _fileno( stdout ), _O_BINARY ) ;
1396 #endif
1397 		outfile = stdout;
1398 		verbose_out = stderr;
1399 	}
1400 	return TRUE;
1401 }
1402 
1403 /******************************************************************************
1404 **
1405 **  get_image
1406 **
1407 **  creates a new image or uses an existing one as a template.
1408 **
1409 **  Used by:
1410 **  main program
1411 **
1412 ******************************************************************************/
get_image(int type,int argc,char * argv[])1413 gdImagePtr get_image(int type, int argc, char *argv[]){
1414 
1415 
1416 	FILE *in;
1417 	int n=0, num[10];
1418 	char *filename;
1419 	gdImagePtr image = NULL;
1420 	int newtype;
1421 
1422 	if( type == EXISTING ) {
1423 		/*  fprintf(stderr,"Creating image from existing file:"); */
1424 		if ((in = get_file(&line_number, &filename)) == NULL ) {
1425 			fprintf(stderr,"Error: Cannot read existing image file \"%s\"\n",
1426 				filename);
1427 			exit(1);
1428 		}
1429 		else {
1430 			if(!quiet) fprintf(verbose_out,"Creating image from existing image <%s>\n",
1431 			    filename);
1432 			image = gdImageCreateFromPng(in);
1433 			fclose(in);
1434 		}
1435 	}
1436 	else if( type == NEW ){
1437 		newtype = get_token(infile);
1438 		while( (newtype == COMMENT) || (newtype == EMPTY) || (newtype != SIZE) ) {
1439 			if(newtype != EMPTY) sync_input(infile);
1440 			newtype = get_token(infile);
1441 		}
1442 		if( newtype != SIZE ) {
1443 			if( argc == 2){
1444 				fprintf(stderr,"Error: <stdin> second line ");
1445 				fprintf(stderr,"must have a 'size' command\n");
1446 			}
1447 			else{
1448 				fprintf(stderr,"Error: %s second line must ", argv[1]);
1449 				fprintf(stderr,"have a 'size' command\n");
1450 			}
1451 			exit(1);
1452 		}
1453 		for( n=1; n<=2; n++ ){
1454 			num[n]=get_number(infile);
1455 		}
1456 		if (!quiet)
1457 		{
1458 			if( output_file )
1459 			{
1460 				fprintf(verbose_out,"Creating new %d by %d image, <%s>\n",
1461 					num[1],num[2],output_file);
1462 			}
1463 			else
1464 			{
1465 				fprintf(verbose_out,"Creating new %d by %d image\n",
1466 					num[1],num[2]);
1467 			}
1468 		}
1469 		image = gdImageCreate(num[1],num[2]);
1470 	}
1471 	written_out = FALSE;
1472 	return image;
1473 }
1474 
1475 /******************************************************************************
1476 **
1477 **  my_newmem: grab some memory.
1478 **
1479 **  -  Concentrates memory error handling in one place.
1480 **
1481 **
1482 **  Used by:
1483 **  string,stringup,chr,chrup,setbrush,settile
1484 **
1485 ******************************************************************************/
1486 void *
my_newmem(size_t size)1487 my_newmem(size_t size)
1488 {
1489 	void	*p;
1490 
1491 	if ((p = malloc(size +1)) == NULL)
1492 	{
1493 		fprintf(stderr, "fly: ran out of memory\n");
1494 		exit(1);
1495 	}
1496 
1497 	return p;
1498 }
1499 
1500 /******************************************************************************
1501 **
1502 **  get_file
1503 **
1504 **  reads a file name and opens a file corresponding to the
1505 **  name read.  if the name is back-quoted `...` then it is
1506 **  interpreted as a shell command.
1507 **
1508 **  Contributed by Ian Reid <ian@robots.ox.ac.uk>
1509 **
1510 **  Bug fix to type of ch by John Mitchell <johnm@magnet.com>
1511 **
1512 **  Used by:
1513 **  get_image
1514 **  copy_to_img
1515 **
1516 ******************************************************************************/
1517 
get_file(int * line_number,char ** filename)1518 FILE *get_file(int *line_number, char **filename)
1519 {
1520 	FILE *in;
1521 	int ch;
1522 	char fname[NAMESIZE];
1523 	int n=0;
1524 
1525 	if ((fname[n++]=getc(infile)) == '`') {
1526 		while (( (ch=getc(infile)) != EOF ) && ( ch != '`' ) && n<NAMESIZE) {
1527 			fname[n++]=ch;
1528 		}
1529 	} else {
1530 		while(( (ch=getc(infile)) != EOF ) && ( ch != ' ') && ( ch != '\n') && n<NAMESIZE){
1531 			fname[n++]=ch;
1532 		}
1533 	}
1534 	if (ch == '\n') { (*line_number)++; }
1535 	if (ch==EOF || n==NAMESIZE) {
1536 		fprintf(stderr, "Error: EOF or out space while reading filename (perhaps missing \"`\"?)\n");
1537 		return NULL;
1538 	}
1539 	fname[n]='\0';
1540 	if (fname[0]=='`') {
1541 #ifndef NO_FORK
1542 		/* open a pipe to get data from a shell command */
1543 		int pid, p[2];
1544 
1545 		*filename = (char *) my_newmem( n );
1546 		strncpy(*filename, fname+1, n);
1547 
1548 		if (pipe(p) < 0) {
1549 			fprintf(stderr, "Error: pipe creation failed\n");
1550 			return NULL;
1551 		}
1552 		if ((pid=fork()) < 0) {
1553 			fprintf(stderr, "Error: fork failed\n");
1554 			return NULL;
1555 		} else if (pid>0) {
1556 			/* child */
1557 			close(p[0]); close(1); dup(p[1]); close(p[1]);
1558 			exit( system (*filename) );
1559 		}
1560 		/* parent */
1561 		close(p[1]);
1562 		in = fdopen(p[0], "rb");
1563 #else
1564 	fprintf(stderr,"Error: Reading image from external command not supported on this Operating System\n");
1565 	exit(1);
1566 #endif
1567 	} else {
1568 		/* open an ordinary file */
1569 		*filename = (char *) my_newmem( n+1 );
1570 		sprintf(*filename,"%s",fname);
1571 		in = fopen(*filename, "rb");
1572 	}
1573 
1574 	return in;
1575 }
1576 /******************************************************************************/
swap(int * a,int * b)1577 void swap(int *a, int *b) {
1578 	int temp;
1579 
1580 	temp = *b;
1581 	*b = *a;
1582 	*a = temp;
1583 }
1584 /******************************************************************************/
1585