[mapserver-commits] r12133 - in trunk/mapserver/mapcache: . include src

svn at osgeo.org svn at osgeo.org
Fri Aug 26 07:00:37 EDT 2011


Author: tbonfort
Date: 2011-08-26 04:00:36 -0700 (Fri, 26 Aug 2011)
New Revision: 12133

Modified:
   trunk/mapserver/mapcache/Makefile.in
   trunk/mapserver/mapcache/Makefile.inc.in
   trunk/mapserver/mapcache/configure
   trunk/mapserver/mapcache/configure.in
   trunk/mapserver/mapcache/geocache.xml
   trunk/mapserver/mapcache/include/geocache.h
   trunk/mapserver/mapcache/src/Makefile
   trunk/mapserver/mapcache/src/buffer.c
   trunk/mapserver/mapcache/src/configuration.c
   trunk/mapserver/mapcache/src/image.c
   trunk/mapserver/mapcache/src/imageio.c
   trunk/mapserver/mapcache/src/mod_geocache.c
   trunk/mapserver/mapcache/src/tileset.c
Log:
add support for Last-Modified and If-Modified-Since http headers

update issue 12
- returns 304 code if suitable if the client has added an If-Modified-Since header
- adds a Last-Modified header with a 200 OK response
thomas.bonfort | 2010-10-19 17:43:18 +0200 (Tue, 19 Oct 2010)

Modified: trunk/mapserver/mapcache/Makefile.in
===================================================================
--- trunk/mapserver/mapcache/Makefile.in	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/Makefile.in	2011-08-26 11:00:36 UTC (rev 12133)
@@ -16,7 +16,7 @@
 	true
 
 src/.libs/mod_geocache.so: src/mod_geocache.c $(SRCS) include/geocache.h
-	$(APXS) -Wc,"$(CFLAGS)" -Iinclude $(PNG_INC) $(CURL_CFLAGS) $(XML2_CFLAGS) $(XML2_LIBS) $(CURL_LIBS) $(PNG_LIB) -c src/mod_geocache.c $(SRCS)
+	$(APXS) -Wc,"$(CFLAGS)" -Iinclude $(JPEG_INC) $(PNG_INC) $(CURL_CFLAGS) $(XML2_CFLAGS) $(XML2_LIBS) $(CURL_LIBS) $(JPEG_LIB) $(PNG_LIB) -c src/mod_geocache.c $(SRCS)
 
 #install: src/.libs/mod_geocache.so
 	#$(APACHECTL) stop

Modified: trunk/mapserver/mapcache/Makefile.inc.in
===================================================================
--- trunk/mapserver/mapcache/Makefile.inc.in	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/Makefile.inc.in	2011-08-26 11:00:36 UTC (rev 12133)
@@ -13,7 +13,10 @@
 PNG_INC=@PNG_INC@
 PNG_LIB=@PNG_LIB@
 
+JPEG_INC=@JPEG_INC@
+JPEG_LIB=@JPEG_LIB@
 
 
+
 OBJS=$(shell find . -regex '^.*\.c$$' -print | grep -v mod_geocache.c | sed "s/^\(.*\)\.c$$/\1.o/") 
 LOBJS=$(shell find . -regex '^.*\.c$$' -print | grep -v mod_geocache.c | sed "s/^\(.*\)\.c$$/\1.lo/")

Modified: trunk/mapserver/mapcache/configure
===================================================================
--- trunk/mapserver/mapcache/configure	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/configure	2011-08-26 11:00:36 UTC (rev 12133)
@@ -601,6 +601,8 @@
 XML2_LIBS
 XML2_CFLAGS
 XML2CONFIG
+JPEG_LIB
+JPEG_INC
 PNG_LIB
 PNG_INC
 EGREP
@@ -664,6 +666,7 @@
 enable_debug
 with_apxs
 with_png
+with_jpeg
 with_xml2_config
 with_curl_config
 '
@@ -1293,6 +1296,7 @@
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
   --with-apxs=/path/to/apxs     Apache 2 apxs tool location
   --with-png=DIR          Specify where PNG is installed
+  --with-jpeg=DIR         Specify where JPEG is installed
   --with-xml2-config=/path/to/xml2-config     xml2-config tool location
   --with-curl-config      path to curl-config program
 
@@ -2843,6 +2847,8 @@
 
 
 
+
+
     # Check whether --enable-debug was given.
 if test "${enable_debug+set}" = set; then :
   enableval=$enable_debug;
@@ -3594,8 +3600,8 @@
 
 
       if test -n "$PNG_LIB" ; then
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result:         using libpng from system libs." >&5
-$as_echo "        using libpng from system libs." >&6; }
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: using libpng from system libs." >&5
+$as_echo "using libpng from system libs." >&6; }
       else
         as_fn_error "PNG (libpng) library cannot be found. install or reconfigure with --with-png=DIR" "$LINENO" 5
       fi
@@ -3616,6 +3622,125 @@
 
 
 
+
+
+# Check whether --with-jpeg was given.
+if test "${with_jpeg+set}" = set; then :
+  withval=$with_jpeg; JPEG_DIR=$withval
+else
+  JPEG_DIR=''
+fi
+
+
+
+  if test -z "$JPEG_DIR" || echo "$JPEG_DIR" | grep '^/' >/dev/null ; then
+    JPEG_DIR="$JPEG_DIR"
+  else
+    JPEG_DIR="`pwd`/$JPEG_DIR"
+  fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking where JPEG is installed..." >&5
+$as_echo "$as_me: checking where JPEG is installed..." >&6;}
+    JPEG_LIB=''
+    JPEG_INC=''
+    JPEG_FOUND='no'
+
+    if test -n "$JPEG_DIR" ; then
+        test -f $JPEG_DIR/lib/libjpeg.a -o -f $JPEG_DIR/lib/libjpeg.so -o -f $JPEG_DIR/lib/libjpeg.sl -o -f $JPEG_DIR/lib/libjpeg.dylib && JPEG_LIBDIR="$JPEG_DIR/lib"
+        test -f $JPEG_DIR/lib64/libjpeg.a -o -f $JPEG_DIR/lib64/libjpeg.so -o -f $JPEG_DIR/lib64/libjpeg.sl -o -f $JPEG_DIR/libjpeg.dylib && JPEG_LIBDIR="$JPEG_DIR/lib64"
+        test -f $JPEG_DIR/libjpeg.a -o -f $JPEG_DIR/libjpeg.so -o -f $JPEG_DIR/libjpeg.sl -o -f $JPEG_DIR/libjpeg.dylib && JPEG_LIBDIR="$JPEG_DIR"
+        test -f $JPEG_DIR/include/jpeglib.h && JPEG_INCLUDE="$JPEG_DIR/include"
+        test -f $JPEG_DIR/include/jpeg/jpeglib.h && JPEG_INCLUDE="$JPEG_DIR/include/jpeg"
+        test -f $JPEG_DIR/lib/jpeglib.h && JPEG_INCLUDE="$JPEG_DIR/lib"
+        test -f $JPEG_DIR/jpeglib.h && JPEG_INCLUDE="$JPEG_DIR"
+
+        if test -n "$JPEG_LIBDIR" ; then
+          JPEG_LIB="-L$JPEG_LIBDIR -ljpeg"
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: using libjpeg from $JPEG_LIB" >&5
+$as_echo "using libjpeg from $JPEG_LIB" >&6; }
+        else
+          as_fn_error "cannot find jpeg lib in $JPEG_DIR" "$LINENO" 5
+        fi
+
+        if test -n "$JPEG_INCLUDE" ; then
+          as_ac_Header=`$as_echo "ac_cv_header_$JPEG_INCLUDE/jpeglib.h" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$JPEG_INCLUDE/jpeglib.h" "$as_ac_Header" "$ac_includes_default"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  JPEG_INC=-I$JPEG_INCLUDE
+else
+  as_fn_error "cannot find jpeg headers" "$LINENO" 5
+fi
+
+
+        else
+            as_fn_error "cannot find jpeg headers in $JPEG_DIR" "$LINENO" 5
+        fi
+    else
+
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jpeg_read_header in -ljpeg" >&5
+$as_echo_n "checking for jpeg_read_header in -ljpeg... " >&6; }
+if test "${ac_cv_lib_jpeg_jpeg_read_header+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ljpeg  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char jpeg_read_header ();
+int
+main ()
+{
+return jpeg_read_header ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_jpeg_jpeg_read_header=yes
+else
+  ac_cv_lib_jpeg_jpeg_read_header=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_jpeg_read_header" >&5
+$as_echo "$ac_cv_lib_jpeg_jpeg_read_header" >&6; }
+if test "x$ac_cv_lib_jpeg_jpeg_read_header" = x""yes; then :
+  JPEG_LIB="-ljpeg"
+fi
+
+      ac_fn_c_check_header_mongrel "$LINENO" "jpeglib.h" "ac_cv_header_jpeglib_h" "$ac_includes_default"
+if test "x$ac_cv_header_jpeglib_h" = x""yes; then :
+
+else
+  as_fn_error "cannot find jpeg headers in system path" "$LINENO" 5
+fi
+
+
+      if test -n "$JPEG_LIB" ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: using libjpeg from system libs." >&5
+$as_echo "using libjpeg from system libs." >&6; }
+      else
+        as_fn_error "JPEG (libjpeg) library cannot be found. install or reconfigure with --with-jpeg=DIR" "$LINENO" 5
+      fi
+    fi
+
+    JPEG_INC=$JPEG_INC
+
+    JPEG_LIB=$JPEG_LIB
+
+
+
 #PKGCONFIG_CHECK
 
 #CAIRO_CHECK

Modified: trunk/mapserver/mapcache/configure.in
===================================================================
--- trunk/mapserver/mapcache/configure.in	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/configure.in	2011-08-26 11:00:36 UTC (rev 12133)
@@ -278,7 +278,7 @@
       AC_CHECK_HEADER([png.h],,
             [AC_MSG_ERROR([cannot find png headers in system path])])
       if test -n "$PNG_LIB" ; then
-        AC_MSG_RESULT([        using libpng from system libs.])
+        AC_MSG_RESULT([using libpng from system libs.])
       else
         AC_MSG_ERROR([PNG (libpng) library cannot be found. install or reconfigure with --with-png=DIR])
       fi
@@ -290,12 +290,65 @@
     AC_SUBST(PNG_LIB,$PNG_LIB)
 ])
 
+AC_DEFUN(JPEG_CHECK,[
+    AC_ARG_WITH(jpeg,
+        AC_HELP_STRING([--with-jpeg=DIR],[Specify where JPEG is installed]),
+        JPEG_DIR=$withval,JPEG_DIR='')
+    
+    AC_EXPAND_PATH($JPEG_DIR, JPEG_DIR)
+    AC_CHECKING(where JPEG is installed)
+    JPEG_LIB=''
+    JPEG_INC=''  
+    JPEG_FOUND='no'  
+    
+    if test -n "$JPEG_DIR" ; then
+        test -f $JPEG_DIR/lib/libjpeg.a -o -f $JPEG_DIR/lib/libjpeg.so -o -f $JPEG_DIR/lib/libjpeg.sl -o -f $JPEG_DIR/lib/libjpeg.dylib && JPEG_LIBDIR="$JPEG_DIR/lib"
+        test -f $JPEG_DIR/lib64/libjpeg.a -o -f $JPEG_DIR/lib64/libjpeg.so -o -f $JPEG_DIR/lib64/libjpeg.sl -o -f $JPEG_DIR/libjpeg.dylib && JPEG_LIBDIR="$JPEG_DIR/lib64"
+        test -f $JPEG_DIR/libjpeg.a -o -f $JPEG_DIR/libjpeg.so -o -f $JPEG_DIR/libjpeg.sl -o -f $JPEG_DIR/libjpeg.dylib && JPEG_LIBDIR="$JPEG_DIR"
+        test -f $JPEG_DIR/include/jpeglib.h && JPEG_INCLUDE="$JPEG_DIR/include"
+        test -f $JPEG_DIR/include/jpeg/jpeglib.h && JPEG_INCLUDE="$JPEG_DIR/include/jpeg"
+        test -f $JPEG_DIR/lib/jpeglib.h && JPEG_INCLUDE="$JPEG_DIR/lib"
+        test -f $JPEG_DIR/jpeglib.h && JPEG_INCLUDE="$JPEG_DIR"
+        
+        if test -n "$JPEG_LIBDIR" ; then   
+          JPEG_LIB="-L$JPEG_LIBDIR -ljpeg"
+          AC_MSG_RESULT([using libjpeg from $JPEG_LIB])
+        else
+          AC_MSG_ERROR([cannot find jpeg lib in $JPEG_DIR])
+        fi
+        
+        if test -n "$JPEG_INCLUDE" ; then
+          AC_CHECK_HEADER([$JPEG_INCLUDE/jpeglib.h],JPEG_INC=-I$JPEG_INCLUDE,
+            [AC_MSG_ERROR([cannot find jpeg headers])])
+        else
+            AC_MSG_ERROR([cannot find jpeg headers in $JPEG_DIR])
+        fi
+    else
+    
+      dnl check for jpeg in system locations
+    
+      AC_CHECK_LIB(jpeg, jpeg_read_header, JPEG_LIB="-ljpeg",,)
+      AC_CHECK_HEADER([jpeglib.h],,
+            [AC_MSG_ERROR([cannot find jpeg headers in system path])])
+      if test -n "$JPEG_LIB" ; then
+        AC_MSG_RESULT([using libjpeg from system libs.])
+      else
+        AC_MSG_ERROR([JPEG (libjpeg) library cannot be found. install or reconfigure with --with-jpeg=DIR])
+      fi
+    fi
+    
+    AC_SUBST(JPEG_INC,$JPEG_INC)
+    AC_SUBST(JPEG_LIB,$JPEG_LIB)
+])
+
 DEBUG_CHECK
 
 APXS_CHECK
 
 PNG_CHECK
 
+JPEG_CHECK
+
 #PKGCONFIG_CHECK
 
 #CAIRO_CHECK

Modified: trunk/mapserver/mapcache/geocache.xml
===================================================================
--- trunk/mapserver/mapcache/geocache.xml	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/geocache.xml	2011-08-26 11:00:36 UTC (rev 12133)
@@ -36,7 +36,9 @@
         <size>256 256</size>
         <resolutions>1.40625 0.703125 0.3515625 0.17578125 0.087890625 0.0439453125 0.02197265625 0.010986328125 0.0054931640625 0.00274658203125 0.001373291015625 0.0006866455078125 0.00034332275390625 0.000171661376953125 0.0000858306884765625 0.00004291534423828125</resolutions>
         <extent>-180 -90 180 90</extent>
-        
+        <metatile>5 5</metatile>
+        <metabuffer>30</metabuffer>
+        <format>JPG</format>
     </tileset>
     <tileset name="test2">
         <source>nexrad</source>

Modified: trunk/mapserver/mapcache/include/geocache.h
===================================================================
--- trunk/mapserver/mapcache/include/geocache.h	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/include/geocache.h	2011-08-26 11:00:36 UTC (rev 12133)
@@ -51,7 +51,7 @@
 extern module AP_MODULE_DECLARE_DATA geocache_module;
 
 typedef struct {
-   char* buf ;     /* buffer */
+   unsigned char* buf ;     /* buffer */
    size_t size ; /* bytes used */
    size_t avail ;  /* bytes allocated */
    apr_pool_t* pool; /*apache pool to allocate from */
@@ -144,6 +144,7 @@
    double *resolutions;
    int metasize_x, metasize_y;
    int metabuffer;
+   geocache_image_format_type format;
    geocache_cache *cache;
    geocache_source *source;
    apr_table_t *forwarded_params;
@@ -223,7 +224,7 @@
 
 typedef struct {
    geocache_buffer *buffer;
-   char *ptr;
+   unsigned char *ptr;
 } _geocache_buffer_closure;
 
 /* in image.c */
@@ -231,8 +232,8 @@
 int geocache_image_metatile_split(geocache_metatile *mt, request_rec *r);
 
 /* in imageio.c */
-geocache_buffer* geocache_imageio_png_encode(request_rec *r, geocache_image *img);
-geocache_image* geocache_imageio_png_decode(request_rec *r, geocache_buffer *buffer);
+geocache_buffer* geocache_imageio_encode(request_rec *r, geocache_image *img, geocache_image_format_type format);
 geocache_image_format_type geocache_imageio_header_sniff(request_rec *r, geocache_buffer *buffer);
 geocache_image* geocache_imageio_decode(request_rec *r, geocache_buffer *buffer);
+
 #endif /* GEOCACHE_H_ */

Modified: trunk/mapserver/mapcache/src/Makefile
===================================================================
--- trunk/mapserver/mapcache/src/Makefile	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/src/Makefile	2011-08-26 11:00:36 UTC (rev 12133)
@@ -9,7 +9,7 @@
 	$(APXS) -Wc,"$(CFLAGS)" -I../include $(PNG_INC) $(CURL_CFLAGS) $(XML2_CFLAGS) -c $<
 	
 mod_geocache.o:  mod_geocache.c $(OBJS)
-	$(APXS) -Wc,"$(CFLAGS)" -I../include $(PNG_INC) $(CURL_CFLAGS) $(XML2_CFLAGS) $(XML2_LIBS) $(CURL_LIBS) $(PNG_LIB) -c mod_geocache.c $(LOBJS)
+	$(APXS) -Wc,"$(CFLAGS)" -I../include $(JPEG_INC) $(PNG_INC) $(CURL_CFLAGS) $(XML2_CFLAGS) $(XML2_LIBS) $(CURL_LIBS) $(JPEG_LIB) $(PNG_LIB) -c mod_geocache.c $(LOBJS)
 	
 .libs/mod_geocache.so: mod_geocache.o $(OBJS)
 

Modified: trunk/mapserver/mapcache/src/buffer.c
===================================================================
--- trunk/mapserver/mapcache/src/buffer.c	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/src/buffer.c	2011-08-26 11:00:36 UTC (rev 12133)
@@ -19,7 +19,7 @@
 #define INITIAL_BUFFER_SIZE 100
 
 static void _geocache_buffer_realloc(geocache_buffer *buffer, size_t len) {
-   char* newbuf ;
+   unsigned char* newbuf ;
    while ( len > buffer->avail ) {
       buffer->avail += buffer->avail;
    }

Modified: trunk/mapserver/mapcache/src/configuration.c
===================================================================
--- trunk/mapserver/mapcache/src/configuration.c	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/src/configuration.c	2011-08-26 11:00:36 UTC (rev 12133)
@@ -264,6 +264,19 @@
 
 
          xmlFree(value);
+      } else if(!xmlStrcmp(cur_node->name, BAD_CAST "format")) {
+         value = (char*)xmlNodeGetContent(cur_node);
+         if(!strcasecmp("PNG", value)) {
+            tileset->format = GEOCACHE_IMAGE_FORMAT_PNG;
+         } else if(!strcasecmp("JPEG", value) || !strcasecmp("JPG", value)) {
+            tileset->format = GEOCACHE_IMAGE_FORMAT_JPEG;
+         } else {
+            return apr_psprintf(pool,"failed to parse format %s."
+                              "(expecting PNG or JPEG, "
+                              "eg <format>PNG</format>",
+                              value);
+         }
+         xmlFree(value);
       }
    }
    /* check we have all we want */

Modified: trunk/mapserver/mapcache/src/image.c
===================================================================
--- trunk/mapserver/mapcache/src/image.c	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/src/image.c	2011-08-26 11:00:36 UTC (rev 12133)
@@ -73,7 +73,7 @@
       _geocache_image_merge(r, base, overlay);
    }
    tile = apr_pcalloc(r->pool,sizeof(geocache_tile));
-   tile->data = geocache_imageio_png_encode(r,base);
+   tile->data = geocache_imageio_encode(r,base, GEOCACHE_IMAGE_FORMAT_PNG);
    tile->sx = base->w;
    tile->sy = base->h;
    tile->tileset = tiles[0]->tileset;
@@ -82,23 +82,21 @@
 
 int geocache_image_metatile_split(geocache_metatile *mt, request_rec *r) {
    geocache_image *metatile;
-   geocache_image tile;
+   geocache_image tileimg;
    
    int i,j;
    int sx,sy;
-   tile.w = mt->tile.tileset->tile_sx;
-   tile.h = mt->tile.tileset->tile_sy;
+   tileimg.w = mt->tile.tileset->tile_sx;
+   tileimg.h = mt->tile.tileset->tile_sy;
    metatile = geocache_imageio_decode(r, mt->tile.data);
-   tile.stride = metatile->stride;
+   tileimg.stride = metatile->stride;
    if(!metatile) return GEOCACHE_FAILURE;
    for(i=0;i<mt->tile.tileset->metasize_x;i++) {
       for(j=0;j<mt->tile.tileset->metasize_y;j++) {
-         
-
-         sx = mt->tile.tileset->metabuffer + i * tile.w;
-         sy = mt->tile.sy - (mt->tile.tileset->metabuffer + (j+1) * tile.w);
-         tile.data = &(metatile->data[sy*metatile->stride + 4 * sx]);
-         mt->tiles[i*mt->tile.tileset->metasize_x+j].data = geocache_imageio_png_encode(r,&tile);
+         sx = mt->tile.tileset->metabuffer + i * tileimg.w;
+         sy = mt->tile.sy - (mt->tile.tileset->metabuffer + (j+1) * tileimg.w);
+         tileimg.data = &(metatile->data[sy*metatile->stride + 4 * sx]);
+         mt->tiles[i*mt->tile.tileset->metasize_x+j].data = geocache_imageio_encode(r,&tileimg, mt->tile.tileset->format);
       }
    }
    return GEOCACHE_SUCCESS;

Modified: trunk/mapserver/mapcache/src/imageio.c
===================================================================
--- trunk/mapserver/mapcache/src/imageio.c	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/src/imageio.c	2011-08-26 11:00:36 UTC (rev 12133)
@@ -17,6 +17,7 @@
 #include "geocache.h"
 #include <http_log.h>
 #include <png.h>
+#include <jpeglib.h>
 
 int _geocache_imageio_image_has_alpha(geocache_image *img) {
    int i,j;
@@ -46,20 +47,254 @@
    // do nothing
 }
 
+typedef struct {
+   struct jpeg_destination_mgr pub;
+   unsigned char *data;
+   geocache_buffer *buffer;
+} geocache_jpeg_destination_mgr;
+
+
+#define OUTPUT_BUF_SIZE 4096
+
+static void _geocache_imageio_jpeg_init_source(j_decompress_ptr cinfo)
+{
+   /* nothing to do */
+}
+
+static int _geocache_imageio_jpeg_fill_input_buffer(j_decompress_ptr cinfo)
+{
+   static JOCTET mybuffer[4];
+
+   /* The whole JPEG data is expected to reside in the supplied memory
+    * buffer, so any request for more data beyond the given buffer size
+    * is treated as an error.
+    */
+   /* Insert a fake EOI marker */
+   mybuffer[0] = (JOCTET) 0xFF;
+   mybuffer[1] = (JOCTET) JPEG_EOI;
+
+   cinfo->src->next_input_byte = mybuffer;
+   cinfo->src->bytes_in_buffer = 2;
+
+   return TRUE;
+}
+
+static void _geocache_imageio_jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+{
+   struct jpeg_source_mgr * src = cinfo->src;
+
+   /* Just a dumb implementation for now.  Could use fseek() except
+    * it doesn't work on pipes.  Not clear that being smart is worth
+    * any trouble anyway --- large skips are infrequent.
+    */
+   if (num_bytes > 0) {
+      while (num_bytes > (long) src->bytes_in_buffer) {
+         num_bytes -= (long) src->bytes_in_buffer;
+         (void) (*src->fill_input_buffer) (cinfo);
+         /* note we assume that fill_input_buffer will never return FALSE,
+          * so suspension need not be handled.
+          */
+      }
+      src->next_input_byte += (size_t) num_bytes;
+      src->bytes_in_buffer -= (size_t) num_bytes;
+   }
+}
+
+static void _geocache_imageio_jpeg_term_source(j_decompress_ptr cinfo)
+{
+}
+
+
+
+int _geocache_imageio_jpeg_mem_src (j_decompress_ptr cinfo, unsigned char * inbuffer, unsigned long insize)
+{
+   struct jpeg_source_mgr * src;
+
+   if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */
+      return GEOCACHE_FAILURE;
+
+   /* The source object is made permanent so that a series of JPEG images
+    * can be read from the same buffer by calling jpeg_mem_src only before
+    * the first one.
+    */
+   if (cinfo->src == NULL) {   /* first time for this JPEG object? */
+      cinfo->src = (struct jpeg_source_mgr *)
+                        (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+                              sizeof(struct jpeg_source_mgr));
+   }
+
+   src = cinfo->src;
+   src->init_source = _geocache_imageio_jpeg_init_source;
+   src->fill_input_buffer = _geocache_imageio_jpeg_fill_input_buffer;
+   src->skip_input_data = _geocache_imageio_jpeg_skip_input_data;
+   src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
+   src->term_source = _geocache_imageio_jpeg_term_source;
+   src->bytes_in_buffer = (size_t) insize;
+   src->next_input_byte = (JOCTET *) inbuffer;
+   return GEOCACHE_SUCCESS;
+}
+
+
+
+void _geocache_imageio_jpeg_init_destination (j_compress_ptr cinfo) {
+   geocache_jpeg_destination_mgr *dest = (geocache_jpeg_destination_mgr*) cinfo->dest;
+
+   /* Allocate the output buffer --- it will be released when done with image */
+   dest->data = (unsigned char *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
+         JPOOL_IMAGE,OUTPUT_BUF_SIZE * sizeof (unsigned char));
+
+   dest->pub.next_output_byte = dest->data;
+   dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+void _geocache_imageio_jpeg_buffer_term_destination (j_compress_ptr cinfo) {
+   geocache_jpeg_destination_mgr *dest = (geocache_jpeg_destination_mgr*) cinfo->dest;
+   geocache_buffer_append(dest->buffer,OUTPUT_BUF_SIZE-dest->pub.free_in_buffer, dest->data);
+   dest->pub.next_output_byte = dest->data;
+   dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+
+int _geocache_imageio_jpeg_buffer_empty_output_buffer (j_compress_ptr cinfo) {
+   geocache_jpeg_destination_mgr *dest = (geocache_jpeg_destination_mgr*) cinfo->dest;
+   geocache_buffer_append(dest->buffer,OUTPUT_BUF_SIZE, dest->data);
+   dest->pub.next_output_byte = dest->data;
+   dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+   return TRUE;
+}
+
+geocache_buffer* _geocache_imageio_jpeg_encode(request_rec *r, geocache_image *img) {
+   struct jpeg_compress_struct cinfo;
+   struct jpeg_error_mgr jerr;
+   int quality = 85;
+   geocache_jpeg_destination_mgr *dest;
+   JSAMPLE *rowdata; 
+   unsigned int row;
+   geocache_buffer *buffer = geocache_buffer_create(5000,r->pool);
+   cinfo.err = jpeg_std_error(&jerr);
+   jpeg_create_compress(&cinfo);
+
+   cinfo.dest = (struct jpeg_destination_mgr *)
+                                                                (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
+                                                                      sizeof (geocache_jpeg_destination_mgr));
+   ((geocache_jpeg_destination_mgr*)cinfo.dest)->pub.empty_output_buffer = _geocache_imageio_jpeg_buffer_empty_output_buffer;
+   ((geocache_jpeg_destination_mgr*)cinfo.dest)->pub.term_destination = _geocache_imageio_jpeg_buffer_term_destination;
+   ((geocache_jpeg_destination_mgr*)cinfo.dest)->buffer = buffer;
+
+   dest = (geocache_jpeg_destination_mgr*) cinfo.dest;
+   dest->pub.init_destination = _geocache_imageio_jpeg_init_destination;
+
+   cinfo.image_width = img->w;
+   cinfo.image_height = img->h;
+   cinfo.input_components = 3;
+   cinfo.in_color_space = JCS_RGB;
+   jpeg_set_defaults(&cinfo);
+   jpeg_set_quality(&cinfo, quality, TRUE);
+   jpeg_start_compress(&cinfo, TRUE);
+
+   rowdata = (JSAMPLE*)malloc(img->w*cinfo.input_components*sizeof(JSAMPLE));
+   for(row=0;row<img->h;row++) {
+      JSAMPLE *pixptr = rowdata;
+      int col;
+      unsigned char *r,*g,*b;
+      r=&(img->data[0])+row*img->stride;
+      g=&(img->data[1])+row*img->stride;
+      b=&(img->data[2])+row*img->stride;
+      for(col=0;col<img->w;col++) {
+         *(pixptr++) = *r;
+         *(pixptr++) = *g;
+         *(pixptr++) = *b;
+         r+=4;
+         g+=4;
+         b+=4;
+      }
+      (void) jpeg_write_scanlines(&cinfo, &rowdata, 1);
+   }
+
+   /* Step 6: Finish compression */
+
+   jpeg_finish_compress(&cinfo);
+   jpeg_destroy_compress(&cinfo);
+   free(rowdata);
+   return buffer;
+}
+
+
 geocache_image_format_type geocache_imageio_header_sniff(request_rec *r, geocache_buffer *buffer) {
-   if(!buffer || buffer->size < 8) {
+   if(!buffer) {
       return GEOCACHE_IMAGE_FORMAT_UNKNOWN;
    }
-   if(png_sig_cmp((png_bytep)buffer->buf, 0, 8) == 0) {
+   if(buffer->size >= 8 && png_sig_cmp((png_bytep)buffer->buf, 0, 8) == 0) {
       return GEOCACHE_IMAGE_FORMAT_PNG;
-      /*   } else if(png_sig_cmp(buffer->buf, 0, 8) == 0) {
-      return GEOCACHE_IMAGE_FORMAT_JPEG;*/
+   } else if(buffer->size >= 2 && buffer->buf[0] == 0xFF && buffer->buf[1] == 0xD8) {
+      return GEOCACHE_IMAGE_FORMAT_JPEG;
    } else {
       return GEOCACHE_IMAGE_FORMAT_UNKNOWN;
    }
 }
 
-geocache_image* geocache_imageio_png_decode(request_rec *r, geocache_buffer *buffer) {
+
+
+geocache_image* _geocache_imageio_jpeg_decode(request_rec *r, geocache_buffer *buffer) {
+   struct jpeg_decompress_struct cinfo = {NULL};
+   struct jpeg_error_mgr jerr;
+   jpeg_create_decompress(&cinfo);
+   cinfo.err = jpeg_std_error(&jerr);
+   geocache_image *img = apr_pcalloc(r->pool,sizeof(geocache_image));
+   if (_geocache_imageio_jpeg_mem_src(&cinfo,buffer->buf, buffer->size) != GEOCACHE_SUCCESS){
+      return NULL;
+   }
+
+   jpeg_read_header(&cinfo, TRUE);
+   jpeg_start_decompress(&cinfo);
+   img->w = cinfo.output_width;
+   img->h = cinfo.output_height;
+   int s = cinfo.output_components;
+   img->data = apr_pcalloc(r->pool,img->w*img->h*4*sizeof(unsigned char));
+   img->stride = img->w * 4;
+
+   unsigned char *temp = apr_pcalloc(r->pool,img->w*s);
+   while ((int)cinfo.output_scanline < img->h)
+   {
+      int i;
+      unsigned char *rowptr = &img->data[cinfo.output_scanline * img->stride];
+      unsigned char *tempptr = temp;
+      jpeg_read_scanlines(&cinfo, &tempptr, 1);
+      if (s == 1)
+      {
+         for (i = 0; i < img->w; i++)
+         {
+            *rowptr++ = *tempptr;
+            *rowptr++ = *tempptr;
+            *rowptr++ = *tempptr;
+            *rowptr++ = 255;
+            tempptr++;
+         }
+      }
+      else if (s == 3)
+      {
+         for (i = 0; i < img->w; i++)
+         {
+            *rowptr++ = *tempptr++;
+            *rowptr++ = *tempptr++;
+            *rowptr++ = *tempptr++;
+            *rowptr++ = 255;
+         }
+      }
+      else
+      {
+         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unsupported jpeg format");
+         jpeg_destroy_decompress(&cinfo);
+         return NULL;
+      }
+   }
+   jpeg_finish_decompress(&cinfo);
+   jpeg_destroy_decompress(&cinfo);
+   return img;
+
+}
+
+geocache_image* _geocache_imageio_png_decode(request_rec *r, geocache_buffer *buffer) {
    geocache_image *img;
    png_uint_32 row_bytes;
    int bit_depth,color_type,i;
@@ -70,7 +305,7 @@
    b.buffer = buffer;
    b.ptr = buffer->buf;
 
-   
+
    /* could pass pointers to user-defined error handlers instead of NULLs: */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
@@ -93,14 +328,14 @@
       return NULL;
    }
    png_set_read_fn(png_ptr,&b,_geocache_imageio_png_read_func);
-   
+
    png_read_info(png_ptr,info_ptr);
    img = apr_pcalloc(r->pool,sizeof(geocache_image));
    if(!png_get_IHDR(png_ptr, info_ptr, &img->w, &img->h,&bit_depth, &color_type,NULL,NULL,NULL)) {
       ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "failed to read png header");
       return NULL;
    }
-   
+
    img->data = apr_pcalloc(r->pool,img->w*img->h*4*sizeof(unsigned char));
    img->stride = img->w * 4;
    row_pointers = apr_pcalloc(r->pool,img->h * sizeof(unsigned char*));
@@ -143,8 +378,7 @@
    return img;
 }
 
-
-geocache_buffer* geocache_imageio_png_encode(request_rec *r, geocache_image *img) {
+geocache_buffer* _geocache_imageio_png_encode(request_rec *r, geocache_image *img) {
    png_infop info_ptr; 
    int color_type;
    size_t row;
@@ -198,9 +432,24 @@
    return buffer;
 }
 
+geocache_buffer* geocache_imageio_encode(request_rec *r, geocache_image *image, geocache_image_format_type format) {
+   if(format == GEOCACHE_IMAGE_FORMAT_PNG) {
+      return _geocache_imageio_png_encode(r,image);
+   } else if(format == GEOCACHE_IMAGE_FORMAT_JPEG) {
+      return _geocache_imageio_jpeg_encode(r,image);
+   } else {
+      return NULL;
+   }
+}
+
 geocache_image* geocache_imageio_decode(request_rec *r, geocache_buffer *buffer) {
-   if(geocache_imageio_header_sniff(r,buffer) != GEOCACHE_IMAGE_FORMAT_PNG) {
+   geocache_image_format_type type = geocache_imageio_header_sniff(r,buffer);
+   if(type == GEOCACHE_IMAGE_FORMAT_PNG) {
+      return _geocache_imageio_png_decode(r,buffer);
+   } else if(type == GEOCACHE_IMAGE_FORMAT_JPEG) {
+      return _geocache_imageio_jpeg_decode(r,buffer);
+   } else {
+      ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "geocache_imageio_decode: unrecognized image format");
       return NULL;
    }
-   return geocache_imageio_png_decode(r,buffer);
 }

Modified: trunk/mapserver/mapcache/src/mod_geocache.c
===================================================================
--- trunk/mapserver/mapcache/src/mod_geocache.c	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/src/mod_geocache.c	2011-08-26 11:00:36 UTC (rev 12133)
@@ -97,6 +97,10 @@
       /* TODO: individual check on tiles if merging is allowed */
 
       tile = (geocache_tile*)geocache_image_merge_tiles(r,request->tiles,request->ntiles);
+      if(!tile) {
+         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "tile merging failed to return data");
+         return HTTP_INTERNAL_SERVER_ERROR;
+      }
       tile->tileset = request->tiles[0]->tileset;
    }
    return geocache_write_tile(r,tile);

Modified: trunk/mapserver/mapcache/src/tileset.c
===================================================================
--- trunk/mapserver/mapcache/src/tileset.c	2011-08-26 11:00:27 UTC (rev 12132)
+++ trunk/mapserver/mapcache/src/tileset.c	2011-08-26 11:00:36 UTC (rev 12133)
@@ -164,6 +164,7 @@
    tileset->tile_sx = tileset->tile_sy = 256;
    tileset->extent[0]=tileset->extent[1]=tileset->extent[2]=tileset->extent[3]=0;
    tileset->forwarded_params = apr_table_make(pool,1);
+   tileset->format = GEOCACHE_IMAGE_FORMAT_PNG;
    return tileset;
 }
 



More information about the mapserver-commits mailing list