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