[Mapserver-users] sending image with mod_perl (conclusion)

Jason Thaxter thaxter at gomoos.org
Fri Mar 7 12:18:52 EST 2003


--QTprm0S8XgL7H0Dt
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

A quick re-summary of the issue: under mod_perl, stdout does not go to the
browser/client, it goes to wherever Apache thinks stdout is for itself.  So
	$img->saveImage(undef,
doesn't really work, though it may sometimes accidentally work, depending on
buffering issues.

So the solution is:

	1) extend mapserver code to add a "writeImage" function that takes a
	filehandle instead of a file name.

	2) extend the Perl interface through SWIG so perl can give the map object
	a filehandle to write the image on

	3) in perl code, get a filehandle to the browser/client and pass it to the
	writeImage function.

Attached you will find a patch against 3.6.4 for parts 1 and 2, and a very
minimal example in perl of how to accomplish part 3.  Maybe the execution
could be better, and GD-like behavior (e.g. "print $img->png"), would be more
elegant for the user, but this works now.

Hope this helps.  I'll copy this to the dev list later...

Cheers,
Jason

-- 
----------------------------------------------
Jason Thaxter
GoMOOS, P.O. Box 4919, Portland, ME 04112-4919
Office Location: 1 Canal Plaza, 7th Floor
Office: 207.773.0423
Fax:    207.773.8672
Email:  thaxter at gomoos.org
------------www.gomoos.org--------------------

--QTprm0S8XgL7H0Dt
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="mod_perl_example.cgi"

#!/usr/bin/perl

use strict;

# Map Server
use mapscript;
use XBase;

my $map = new mapscript::mapObj('/home/moxie/tmp/test.map');

my $img = $map->draw();
my $ref_img = $map->drawReferenceMap();


use Time::HiRes 'time';
my $start = time;

# these are for getting the filehandle
use Apache();
use IO::Handle;
my $fh; # this is the filehandle we'll pass to writeImage
if ($ENV{MOD_PERL}){
	$fh = IO::Handle->new_from_fd(Apache->request->connection->fileno(1),'w');
}
else {
	$fh = \*STDOUT;
}

use CGI ':cgi';
print $fh header(  # note the use of the filehandle here...
	-type => 'image/png',
);

$ref_img->writeImage($fh, $mapscript::MS_PNG, $map->{transparent}, $map->{interlace},0);

$img->free();
$ref_img->free();


--QTprm0S8XgL7H0Dt
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="mod_perl_fixes.diff"

Index: map.h
===================================================================
RCS file: /data2/cvsroot/mapserver/map.h,v
retrieving revision 1.150.2.12
diff -b -u -r1.150.2.12 map.h
--- map.h	8 Jan 2003 19:06:59 -0000	1.150.2.12
+++ map.h	7 Mar 2003 16:53:28 -0000
@@ -729,6 +729,7 @@
 
 // Function prototypes, wrapable
 int msSaveImage(gdImagePtr img, char *filename, int type, int transparent, int interlace, int quality);
+int msWriteImage(gdImagePtr img, FILE *stream, int type, int transparent, int interlace, int quality);
 void msFreeImage(gdImagePtr img);
 
 // Function prototypes, not wrapable
Index: maputil.c
===================================================================
RCS file: /data2/cvsroot/mapserver/maputil.c,v
retrieving revision 1.108
diff -b -u -r1.108 maputil.c
--- maputil.c	9 Apr 2002 04:55:13 -0000	1.108
+++ maputil.c	7 Mar 2003 16:53:29 -0000
@@ -1183,6 +1183,59 @@
   return(MS_SUCCESS);
 }
 
+/*
+** Write an image to a file handle
+*/
+int msWriteImage(gdImagePtr img, FILE *stream , int type, int transparent, int interlace, int quality)
+{
+
+  if(interlace)
+    gdImageInterlace(img, 1);
+
+  if(transparent)
+    gdImageColorTransparent(img, 0);
+
+  switch(type) {
+  case(MS_GIF):
+#ifdef USE_GD_GIF
+    gdImageGif(img, stream);
+#else
+    msSetError(MS_MISCERR, "GIF output is not available.", "msWriteImage()");
+    return(MS_FAILURE);
+#endif
+    break;
+  case(MS_PNG):
+#ifdef USE_GD_PNG
+    gdImagePng(img, stream);
+#else
+    msSetError(MS_MISCERR, "PNG output is not available.", "msWriteImage()");
+    return(MS_FAILURE);
+#endif
+    break;
+  case(MS_JPEG):
+#ifdef USE_GD_JPEG
+    gdImageJpeg(img, stream, quality);
+#else
+     msSetError(MS_MISCERR, "JPEG output is not available.", "msWriteImage()");
+     return(MS_FAILURE);
+#endif
+     break;
+  case(MS_WBMP):
+#ifdef USE_GD_WBMP
+    gdImageWBMP(img, 1, stream);
+#else
+    msSetError(MS_MISCERR, "WBMP output is not available.", "msWriteImage()");
+    return(MS_FAILURE);
+#endif
+    break;
+  default:
+    msSetError(MS_MISCERR, "Unknown output image type.", "msWriteImage()");
+    return(MS_FAILURE);
+  }
+
+  return(MS_SUCCESS);
+}
+
 void msFreeImage(gdImagePtr img)
 {
   gdImageDestroy(img);
Index: mapscript/mapscript.i
===================================================================
RCS file: /data2/cvsroot/mapserver/mapscript/mapscript.i,v
retrieving revision 1.66.2.1
diff -b -u -r1.66.2.1 mapscript.i
--- mapscript/mapscript.i	8 Jul 2002 17:28:16 -0000	1.66.2.1
+++ mapscript/mapscript.i	7 Mar 2003 16:53:30 -0000
@@ -989,6 +989,15 @@
     msSaveImage(self->bytes, filename, type, transparent, interlace, quality);
   }
 
+  /* Make FILE * work */
+  %typemap(perl5,in) FILE * {
+    /* $target = IoIFP(sv_2io($source)); older swig */
+    $1 = IoIFP(sv_2io($input));
+  }
+  void writeImage(FILE *stream, int type, int transparent, int interlace, int quality) {
+    msWriteImage(self->bytes, stream, type, transparent, interlace, quality);
+  }
+
   
 }
 

--QTprm0S8XgL7H0Dt--



More information about the mapserver-users mailing list