http://www.perlmonks.org?node_id=1047300

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

So I'm building a perl/dancer app and I want to serve an image at a url like this:

mysite.com/image.png (which will be generated at runtime)

I did this:

get '/image' => sub { # 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); # make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # 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); content_type 'image/png'; binmode STDOUT;#don't think this makes a diff. send_file($im->png); };
But, I end up getting a broken image and 400 BAD request in the network log. Any ideas? I tried putting it all in a eval, no errors there.

Replies are listed 'Best First'.
Re: serving an image with dancer and GD
by Corion (Patriarch) on Jul 31, 2013 at 18:20 UTC

    send_file wants to send a file, which must exist on disk, with a name, on the server. You maybe just want to return $im->png as the result of the request?

    Also, what is DISPLAY supposed to be/do? I recommend using lexical filehandles over using global filehandles.

Re: serving an image with dancer and GD
by dasgar (Priest) on Jul 31, 2013 at 22:35 UTC

    You're close to getting it right. The binmode line is not needed and the send_file should just be a return (as Corion had suggested). Below is a copy of your code with these changes.

    get '/image' => sub { # 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); # make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # 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); content_type 'image/png'; #binmode STDOUT;#don't think this makes a diff. #send_file($im->png); return $im->png; };