"Fossies" - the Fresh Open Source Software Archive

Member "fly-2.0.1/fly.c" (17 Jun 2009, 42143 Bytes) of package /linux/www/old/fly-2.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    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 
  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 ******************************************************************************/
  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 ******************************************************************************/
  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 ******************************************************************************/
 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 ******************************************************************************/
 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 ******************************************************************************/
 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     fclose(img_to_copy);
 1274 
 1275     if( resize == 1 )
 1276     {
 1277         if((arg[0] == -1)&&(arg[1] == -1) &(arg[2] == -1)&&(arg[3] == -1)){
 1278             if(!quiet) fprintf(verbose_out,"Copying %s (entire area) to area %d,%d - %d,%d.\n",
 1279                 filename,arg[4],arg[5],arg[6], arg[7]);
 1280             gdImageCopyResized(img, img_file, arg[4], arg[5], 0, 0,
 1281                 (arg[6] - arg[4]), (arg[7] - arg[5]), img_file->sx, img_file->sy);
 1282         }
 1283         else {
 1284             if(!quiet) fprintf(verbose_out,"Copying %s (area %d,%d - %d,%d) to area %d,%d - %d,%d.\n",
 1285                 filename,arg[4],arg[5],arg[6], arg[7],arg[0],arg[1],arg[2],arg[3]);
 1286             gdImageCopyResized(img, img_file, arg[4], arg[5], arg[0], arg[1],
 1287                 (arg[6] - arg[4] + 1), (arg[7] - arg[5] + 1), (arg[2] - arg[0] + 1),
 1288                 (arg[3] - arg[1] + 1));
 1289         }
 1290     }
 1291     else
 1292     {
 1293         if ((arg[2] == -1)&&(arg[3] == -1) &(arg[4] == -1)&&(arg[5] == -1)) {
 1294             /* another comment from Claus Hofmann. I'm getting curious now. */
 1295             /* gesamtes Bild 
 1296             */
 1297             arg[2] = arg[3] = 0;
 1298             arg[4] = img_file->sx;
 1299             arg[5] = img_file->sy;
 1300         }
 1301         if(!quiet) fprintf(verbose_out,"Copying %s to coordinates %d,%d\n",filename,arg[0],arg[1]);
 1302         gdImageCopy(img, img_file, arg[0], arg[1], arg[2], arg[3],
 1303                     arg[4] - arg[2], arg[5] - arg[3]);
 1304     }
 1305     gdImageDestroy(img_file);
 1306 
 1307     return;
 1308 }
 1309 
 1310 /******************************************************************************
 1311 **
 1312 **  sync_input
 1313 **
 1314 **  synchronises input line - reads to end of line, leaving file pointer
 1315 **  at first character of next line.
 1316 **
 1317 **  Used by:
 1318 **  main program - error handling.
 1319 **
 1320 ******************************************************************************/
 1321 void
 1322 sync_input(FILE *infile)
 1323 {
 1324     int c = 0;
 1325 
 1326     if( c == '\n' ) return;
 1327     while( ( (c=getc(infile)) != EOF ) && (c != '\n') && (c != '\r')) ;
 1328     if( c == EOF ) finished = TRUE;
 1329     if( c == '\n' || c == '\r') line_number++;
 1330     return;
 1331 }
 1332 
 1333 /******************************************************************************
 1334 **
 1335 **  process_args
 1336 **
 1337 **  processes the command line arguments
 1338 **
 1339 **  Used by:
 1340 **  main program.
 1341 **
 1342 ******************************************************************************/
 1343 int
 1344 process_args(int argc, char *argv[])
 1345 {
 1346     int c = 0, errflag=0;
 1347     extern char *optarg;
 1348     extern int optind;
 1349 
 1350     while ((c=getopt(argc, argv, "qhvi:o:")) != EOF) {
 1351         switch (c) {
 1352             case 'q': quiet = TRUE;
 1353                     break;
 1354             case 'v':
 1355             case 'h': fprintf(stdout,"fly, version %s\n\n%s\n", version, help);
 1356                       exit(0);
 1357                     break;
 1358             case 'o': output_file=(char *)my_newmem(strlen(optarg)*sizeof(char));
 1359                       sprintf(output_file,"%s",optarg);
 1360                     break;
 1361             case 'i': input_file=(char *)my_newmem(strlen(optarg)*sizeof(char));
 1362                       sprintf(input_file,"%s",optarg);
 1363                     break;
 1364             case '?': errflag = 1;
 1365                     break;
 1366         }
 1367         if (errflag) {
 1368             fprintf(stderr,"%s\n", usage);
 1369             exit(1);
 1370         }
 1371     }
 1372     if( input_file ) {
 1373         if ( (infile = fopen(input_file,"r")) == NULL ) {
 1374             fprintf(stderr, "Failed to open input file, %s.\n",
 1375                 input_file);
 1376             return FALSE;
 1377         }
 1378     } else {
 1379         infile = stdin;
 1380     }
 1381     if( output_file ) {
 1382         if ( (outfile = fopen(output_file,"wb")) == NULL ) {
 1383             fprintf(stderr, "Failed to open output file, %s.\n",
 1384                 output_file);
 1385             return FALSE;
 1386         }
 1387         verbose_out = stdout;
 1388     } else {
 1389 #ifdef WIN32
 1390         _setmode( _fileno( stdout ), _O_BINARY ) ;
 1391 #endif
 1392         outfile = stdout;
 1393         verbose_out = stderr;
 1394     }
 1395     return TRUE;
 1396 }
 1397 
 1398 /******************************************************************************
 1399 **
 1400 **  get_image
 1401 **
 1402 **  creates a new image or uses an existing one as a template.
 1403 **
 1404 **  Used by:
 1405 **  main program
 1406 **
 1407 ******************************************************************************/
 1408 gdImagePtr get_image(int type, int argc, char *argv[]){
 1409 
 1410 
 1411     FILE *in;
 1412     int n=0, num[10];
 1413     char *filename;
 1414     gdImagePtr image = NULL;
 1415     int newtype;
 1416 
 1417     if( type == EXISTING ) {
 1418         /*  fprintf(stderr,"Creating image from existing file:"); */
 1419         if ((in = get_file(&line_number, &filename)) == NULL ) {
 1420             fprintf(stderr,"Error: Cannot read existing image file \"%s\"\n",
 1421                 filename);
 1422             exit(1);
 1423         }
 1424         else {
 1425             if(!quiet) fprintf(verbose_out,"Creating image from existing image <%s>\n",
 1426                 filename);
 1427             image = gdImageCreateFromPng(in);
 1428             fclose(in);
 1429         }
 1430     }
 1431     else if( type == NEW ){
 1432         newtype = get_token(infile);
 1433         while( (newtype == COMMENT) || (newtype == EMPTY) || (newtype != SIZE) ) {
 1434             if(newtype != EMPTY) sync_input(infile);
 1435             newtype = get_token(infile);
 1436         }
 1437         if( newtype != SIZE ) {
 1438             if( argc == 2){
 1439                 fprintf(stderr,"Error: <stdin> second line ");
 1440                 fprintf(stderr,"must have a 'size' command\n");
 1441             }
 1442             else{
 1443                 fprintf(stderr,"Error: %s second line must ", argv[1]);
 1444                 fprintf(stderr,"have a 'size' command\n");
 1445             }
 1446             exit(1);
 1447         }
 1448         for( n=1; n<=2; n++ ){
 1449             num[n]=get_number(infile);
 1450         }
 1451         if (!quiet)
 1452         {
 1453             if( output_file )
 1454             {
 1455                 fprintf(verbose_out,"Creating new %d by %d image, <%s>\n",
 1456                     num[1],num[2],output_file);
 1457             }
 1458             else
 1459             {
 1460                 fprintf(verbose_out,"Creating new %d by %d image\n",
 1461                     num[1],num[2]);
 1462             }
 1463         }
 1464         image = gdImageCreate(num[1],num[2]);
 1465     }
 1466     written_out = FALSE;
 1467     return image;
 1468 }
 1469 
 1470 /******************************************************************************
 1471 **
 1472 **  my_newmem: grab some memory.
 1473 **
 1474 **  -  Concentrates memory error handling in one place.
 1475 **
 1476 **
 1477 **  Used by:
 1478 **  string,stringup,chr,chrup,setbrush,settile
 1479 **
 1480 ******************************************************************************/
 1481 void *
 1482 my_newmem(size_t size)
 1483 {
 1484     void    *p;
 1485 
 1486     if ((p = malloc(size +1)) == NULL)
 1487     {
 1488         fprintf(stderr, "fly: ran out of memory\n");
 1489         exit(1);
 1490     }
 1491 
 1492     return p;
 1493 }
 1494 
 1495 /******************************************************************************
 1496 **
 1497 **  get_file
 1498 **
 1499 **  reads a file name and opens a file corresponding to the
 1500 **  name read.  if the name is back-quoted `...` then it is
 1501 **  interpreted as a shell command.
 1502 **
 1503 **  Contributed by Ian Reid <ian@robots.ox.ac.uk>
 1504 **
 1505 **  Bug fix to type of ch by John Mitchell <johnm@magnet.com>
 1506 **
 1507 **  Used by:
 1508 **  get_image
 1509 **  copy_to_img
 1510 **
 1511 ******************************************************************************/
 1512 
 1513 FILE *get_file(int *line_number, char **filename)
 1514 {
 1515     FILE *in;
 1516     int ch;
 1517     char fname[NAMESIZE];
 1518     int n=0;
 1519 
 1520     if ((fname[n++]=getc(infile)) == '`') {
 1521         while (( (ch=getc(infile)) != EOF ) && ( ch != '`' ) && n<NAMESIZE) {
 1522             fname[n++]=ch;
 1523         }
 1524     } else {
 1525         while(( (ch=getc(infile)) != EOF ) && ( ch != ' ') && ( ch != '\n') && n<NAMESIZE){
 1526             fname[n++]=ch;
 1527         }
 1528     }
 1529     if (ch == '\n') { (*line_number)++; }
 1530     if (ch==EOF || n==NAMESIZE) {
 1531         fprintf(stderr, "Error: EOF or out space while reading filename (perhaps missing \"`\"?)\n");
 1532         return NULL;
 1533     }
 1534     fname[n]='\0';
 1535     if (fname[0]=='`') {
 1536 #ifndef NO_FORK
 1537         /* open a pipe to get data from a shell command */
 1538         int pid, p[2];
 1539 
 1540         *filename = (char *) my_newmem( n );
 1541         strncpy(*filename, fname+1, n);
 1542 
 1543         if (pipe(p) < 0) {
 1544             fprintf(stderr, "Error: pipe creation failed\n");
 1545             return NULL;
 1546         }
 1547         if ((pid=fork()) < 0) {
 1548             fprintf(stderr, "Error: fork failed\n");
 1549             return NULL;
 1550         } else if (pid>0) {
 1551             /* child */
 1552             close(p[0]); close(1); dup(p[1]); close(p[1]);
 1553             exit( system (*filename) );
 1554         }
 1555         /* parent */
 1556         close(p[1]);
 1557         in = fdopen(p[0], "rb");
 1558 #else
 1559     fprintf(stderr,"Error: Reading image from external command not supported on this Operating System\n");
 1560     exit(1);
 1561 #endif
 1562     } else {
 1563         /* open an ordinary file */
 1564         *filename = (char *) my_newmem( n+1 );
 1565         sprintf(*filename,"%s",fname);
 1566         in = fopen(*filename, "rb");
 1567     }
 1568 
 1569     return in;
 1570 }
 1571 /******************************************************************************/
 1572 void swap(int *a, int *b) {
 1573     int temp;
 1574 
 1575     temp = *b;
 1576     *b = *a;
 1577     *a = temp;
 1578 }
 1579 /******************************************************************************/