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

Hello, I'm trying to return an image in a cgi script and the code works for jpgs, but not for pngs. Here's the code that works for jpgs:

use strict; print "Content-type: image/jpg\n\n"; my $file_name = "./images/picture.jpg"; binmode IMAGE; binmode STDOUT; open IMAGE, $file_name or die "ERROR $!"; while(read IMAGE, $buff, 1024) { print STDOUT $buff; } close IMAGE; 1;

This returns the image just as I hoped and expected. However, if I merely change the two occurrences of 'jpg' above to 'png', it returns nothing! Both picture.jpg and picture.png exist of course, in the proper place.

I've tried all combinations of with and w/o binmode, a full path to the file, buffering to a temporary variable before printing, etc. and always get the same result. Tested on IE and Chrome.

Any help is greatly appreciated. I've got a fair amount invested in keeping the images as pngs. Thank you.

Replies are listed 'Best First'.
Re: Returning jpg works, png NOT
by Corion (Patriarch) on Jul 06, 2011 at 08:23 UTC

    Note that this serves no purpose:

    binmode IMAGE; ... open IMAGE, $file_name or die "ERROR $!";

    You need to appüly binmode after opening a file (but before reading from it):

    open IMAGE, $file_name or die "ERROR $!"; binmode IMAGE;

      Good catch! That, in fact, could explain the symptoms, because the magic bytes of the PNG format ("\x89PNG\r\n\cz\n") is specifically designed such that it becomes corrupted if you mess up line endings, whereas a small jpg image might not contain "\r\n" anywhere at all so it may survive being read in text mode.

      Thank you, Corion! This solved it, and "good catch" indeed...

Re: Returning jpg works, png NOT
by davido (Cardinal) on Jul 06, 2011 at 07:47 UTC

    What do your server error logs say? It's not impossible for there to be a silent failure, but it's unlikely. You just need to look for it.


    Dave

Re: Returning jpg works, png NOT
by i5513 (Pilgrim) on Jul 06, 2011 at 08:01 UTC
    After adding my $buff, Your script work fine here (iceweasel (firefox in debian)) with both PNG and jpg I suppose you can capture network traffic with wireshark or similar and see what happens (or if it is a IE issue??) Regards
    #!/usr/bin/perl use strict; print "Content-type: image/jpg\n\n"; my $file_name = "/path/to/picture.jpg"; my $buff; binmode IMAGE; binmode STDOUT; open IMAGE, $file_name or die "ERROR $!"; while(read IMAGE, $buff, 1024) { print STDOUT $buff; } close IMAGE; 1;
Re: Returning jpg works, png NOT
by moritz (Cardinal) on Jul 06, 2011 at 07:48 UTC
    Is there anything in the error log or the access log of your web server?

    If you run the script on the command line, do you get the binary data of the png printed to your terminal? (you might need to type reset to restore it afterward).