chrono86 has asked for the wisdom of the Perl Monks concerning the following question:

Hi, i know there is a much easier way to doing this, but i've been trying to make FLY (Martin Gleeson) send STDOUT and recieve input automatically through perl using a WindowsNT system and the IIS webserver. I know the problem lies with binmode, but i am not sure why it isn't working correctly. Just have a look:
#!D:\perl\bin $flyprog = "D:\\fly\\fly.exe"; print "Content-type: image/png\n\n"; binmode(STDOUT); open(FLY,"| $flyprog -q "); print FLY "new\n"; print FLY "size 256,256\n"; print FLY "type png\n"; print FLY "fill 1,1,255,255,255\n"; print FLY "circle 128,128,180,0,0,0\n"; print FLY "fill 128,128,255,255,0\n"; print FLY "arc 128,128,120,120,0,180,0,0,0\n"; print FLY "circle 96,96,10,0,0,0\n"; print FLY "circle 160,96,10,0,0,0\n"; print FLY "fill 96,96,0,0,0\n"; print FLY "fill 160,96,0,0,0\n"; close(FLY);
If you know how fly works, if you don't specify an input file it takes its input from STDIN. If you don't specify an output file it sends its output to STDOUT. If you specify the -q option it works quietly. When it sends the image information to STDOUT, it doesn't send it in binary mode as i specified. If anyone could help me in understanding why, i would really appreciate it. Thanks!

Replies are listed 'Best First'.
Re: Using FLY to print to STDOUT
by dws (Chancellor) on Oct 04, 2002 at 01:55 UTC
    You can open() a program to write to it, or open() a program to read from it, but to do both you'll need to take extra steps. You're trying to do both, so you'll need to look for alternatives. One possibility (untested) is to try something like:
    open(ARGS, ">args$$") or die "args$$: $!"; print ARGS <<ENDARGS; new size 256,256 ... etc ENDARGS close(ARGS); open(FLY, "$flyprog -f args$$ |") or die "$flyprog: $!"; binmode(STDOUT); print "Content-type: image/png\n\n"; print <FLY>; close(FLY); unlink("args$$");
    In this approach, you write the commands to fly out to a temporary file, then feed that file back to fly via the "command line" that you're opening. (I'm assuming that there's way to pass a filename to fly.)

    The output, which you read from the command, is the PNG.

    Depending on your server configuration, you might need to put the temporary "args" file somewhere else, like /tmp

Re: Using FLY to print to STDOUT
by vek (Prior) on Oct 04, 2002 at 02:57 UTC
    Take a peek at IPC::Open2. It lets you write to a program via STDIN and read from the same program via STDOUT. I've used it with great success.

    -- vek --
      I tried it using the open2 function, but for some reason the readhandle is empty. maybe i'm using it wrong, since the readhandle is empty perl hangs when i try to read from it.
      #!D:\perl\bin\ use IPC::Open2; $flyprog = "d:\\perl\\fly\\fly.exe"; open2 (*BOY, *FLY, "$flyprog -q"); print FLY "new\n"; print FLY "size 256,256\n"; print FLY "fill 1,1,255,255,255\n"; print FLY "arc 128,128,180,180,0,360,0,0,0\n"; print FLY "fill 128,128,255,255,0\n"; print FLY "arc 128,128,120,120,0,180,0,0,0\n"; print FLY "arc 96,96,10,10,0,360,0,0,0\n"; print FLY "arc 160,96,10,10,0,360,0,0,0\n"; print FLY "fill 96,96,0,0,0\n"; print FLY "fill 160,96,0,0,0\n"; print FLY "string 0,0,0,10,240,giant,Hello, World!\n"; print FLY "string 0,0,0,100,10,medium,Don't worry, be Happy!\n"; close(FLY); $output = <BOY>; close(BOY); print "Content-type: image/gif\n\n"; binmode(STDOUT); print $output;
      It SHOULD work, but it doesn't for some reason. I must be doing something wrong.
        Make sure you use warnings and strict. Make sure you check to see if the call to open2 failed.
        open2 (*BOY, *FLY, "$flyprog -q") || die "open2 $flyprog - $!\n';
        Does fly.exe stream the data back to you via STDOUT? If so you might want to loop over the STDOUT filehandle:
        while (<BOY>) { $output .= $_; } close (BOY);
        -- vek --
Re: Using FLY to print to STDOUT
by helgi (Hermit) on Oct 04, 2002 at 09:59 UTC
    Instead of using an external program, I would like to take this chance to recommend the GD module. Here is a simple example that can be modified to easily do what you want and is a bit more Perlish than piping to fly.

    #!perl use warnings; use strict; use GD; # create a new image my $im = new GD::Image(100,100); # allocate some colors my $white = $im->colorAllocate(255,255,255); my $black = $im->colorAllocate(0,0,0); my $red = $im->colorAllocate(255,0,0); my $blue = $im->colorAllocate(0,0,255); # Put a black frame around the picture $im->rectangle(0,0,99,99,$black); # Draw a blue oval $im->arc(50,50,95,75,0,360,$blue); # And fill it with red $im->fill(50,50,$red); # draw a line (x1,y1,x2,y2,color) $im->line(30,20,40,50,$black); # open an output file my $png_file = "/full/path/test.png"; open OUT, ">$png_file" or die "Cannot open $png_file:$!\n"; # make sure we are writing to a binary stream (Win only) binmode OUT; # Convert the image to PNG and print it on standard output print OUT $im->png; close OUT or die "Cannot close $png_file:$!\n";
    Disclaimer: I took this sample from the documentation somewhere and take no credit for it, although it is slightly modified.

    -- Regards,
    Helgi Briem
    helgi AT decode DOT is