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

I am trying to read information from a file and generate a graph. When I run it in the browser, the image section shows up as a bunch of symbols and trash. I can't seem to pin point the problem.
#!/usr/bin/perl -w # # Retrieve form selections & display the results # use strict; use File::Find; use CGI; my $q = new CGI; use GD::Graph::points; my $request = $ENV{"Query String"}; # Assign input to variables my $start_month= $q->param('month'); my $start_day= $q->param('day'); my $start_year= $q->param('year'); my $start_hour= $q->param('hour'); my $start_min= $q->param('min'); my $test_site= $q->param('center'); print $q->header("text/html\n\n"), $q->start_html(-title=>"Data Report"), "Report for $center from $start_hour:$start_min $start_month/$star +t_day/$start_year.\n"; #Find the file (yymmdd_site format) undef$/; find (sub { return if($_ =~ /^\./); return unless($_ =~ /\.txt/i); stat $Find::File::name; return if -d; return unless -r; open(FILE, "<$Find::file::name") or return; my $headercount = 1; my $discard = <FILE > for 1 .. headercount; While(<FILE>){ chomp; my ($timestamp, $out, $in) = (split m{"\t"}) [0, 3, 7]); my @data = (["timestamp", "$timestamp"), [$out, $in]); my $mygraph = GD::Graph::points->new(500,300); $mygraph->set( x_label => 'Time/Date', y_label => 'COunt', ) or warn $mygraph-> error; my $myimage = $mygraph->plot(\@data) or die $mygraph->error; print "Content-type: image/png\n\n"; print $myimage->png; close(FILE); }, '/(name of my directory tree)' $q->end_html;

Replies are listed 'Best First'.
Re: my image is not showing
by Corion (Patriarch) on Jul 08, 2008 at 15:52 UTC

    This is not how HTTP works.

    You're trying to output the data for two URLs at once. You need to handle the page HTML and the image data in two separate requests, because that's what your browser sends you. Your HTML never links to the image.

    Let me suggest that you start out with a static image (and possibly static HTML), then move towards dynamic HTML and the static image, and then move from a static image to creating a dynamic image. That way, you will have separated the steps into programs.

      You need to handle the page HTML and the image data in two separate requests

      There actually is a way to do this in one request, but it's not for the faint of heart, and it won't work in older browsers, or in some browsers if the encoded size is larger to than 4k.

      But, for those times when you really want to do it, use the data:// URL scheme. See the docs from mozilla for more info.

      I personally have never had a situation where the images I'm generating fit within the size limit, so have never had a chance to make use of this ... and I believe this is one of the tests that IE7 is still failing in Acid2

Re: my image is not showing
by oko1 (Deacon) on Jul 08, 2008 at 16:51 UTC

    There's actually a protocol (Sparkline) for doing this kind of thing - assuming that your graph is relatively simple. In general, though, the previous replies are correct - you can't mix two kinds of MIME data streams under one header.

    Example of a sparkline (pie chart) follows:

    #!/usr/bin/perl -w use strict; use GD::Graph; use GD::Graph::pie; use CGI qw/:standard/; use MIME::Base64; my @data = ( ["1st","2nd"], [ 1, 2], ); my $graph = new GD::Graph::pie( 120, 120 ); $graph->set( dclrs => [ split / /, "#FECECE #FEFECE #FFFFFF" ], start_angle => 90 ); my $gd = $graph->plot(\@data) or die $graph->error; print header, start_html, h1("Data graph"), p('<IMG SRC="data:image/png;base64,', encode_base64($gd->png), '" alt="sparkline"/>'), end_html;

    Also, take a look at GD::Graph::sparklines.

    
    -- 
    Human history becomes more and more a race between education and catastrophe. -- HG Wells
    
Re: my image is not showing
by thezip (Vicar) on Jul 08, 2008 at 15:56 UTC

    ITMajor,

    Your text/html header is incorrect. It must be something like 'image/gif' or 'image/png'.

    If you must embed the image in an HTML page, you'll need to do something like:

    <HTML> <BODY> Some text goes here...<br> Your image is displayed here:<br> <IMG SRC="/cgi-bin/showmetheimage.pl"> </BODY> </HTML>

    You can't the mix headers for HTML and the image.


    Your wish is my commandline.
Re: my image is not showing
by moritz (Cardinal) on Jul 08, 2008 at 15:56 UTC
    The browser doesn't know what to do with an inline image, and it doesn't expect another HTTP header.

    What you have to do is to separate the script the prints out the chart from the one that prints the HTML. In the HTML you generate a link to the script that returns the image, and just the image + header:

    # HTML generating script: use CGI; my $q = CGI->new(); print $q->header(), $q->start_html(), ... # Image generating script: use CGI; use GD::Graph::points; print "Content-Type: iamge/png\n\n"; # generate plot here ... binmode STDOUT; print $myimg->png;