[mapserver-commits] r12662 - trunk/mapserver/mapcache/src

svn at osgeo.org svn at osgeo.org
Fri Oct 14 09:06:57 EDT 2011


Author: tbonfort
Date: 2011-10-14 06:06:57 -0700 (Fri, 14 Oct 2011)
New Revision: 12662

Modified:
   trunk/mapserver/mapcache/src/cache_tiff.c
Log:
make the TIFF cache swap pixel order before encoding tile

create TIFF files with size that accounts for the number of tiles actually used at the current level


Modified: trunk/mapserver/mapcache/src/cache_tiff.c
===================================================================
--- trunk/mapserver/mapcache/src/cache_tiff.c	2011-10-14 12:43:43 UTC (rev 12661)
+++ trunk/mapserver/mapcache/src/cache_tiff.c	2011-10-14 13:06:57 UTC (rev 12662)
@@ -38,7 +38,17 @@
 #include <stdlib.h>
 #include <tiffio.h>
 
+#ifdef USE_GEOTIFF
+#include "xtiffio.h"
+#include "geovalues.h"
+#include "geotiff.h"
+#include "geo_normalize.h"
+#include "geo_tiffp.h"
+#include "geo_keyp.h"
+#include "xtiffio.h"
+#endif
 
+
 #ifdef USE_TIFF_WRITE
 #if APR_HAS_THREADS
 #include <apr_thread_mutex.h>
@@ -141,9 +151,9 @@
 #ifdef DEBUG
 static void check_tiff_format(mapcache_context *ctx, mapcache_tile *tile, TIFF *hTIFF, const char *filename) {
    mapcache_cache_tiff *dcache = (mapcache_cache_tiff*)tile->tileset->cache;
-   int imwidth,imheight,tilewidth,tileheight;
-   int planarconfig,orientation;
-   int compression;
+   uint32 imwidth,imheight,tilewidth,tileheight;
+   int16 planarconfig,orientation;
+   uint16 compression;
    int rv;
    TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &imwidth );
    TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &imheight );
@@ -173,15 +183,13 @@
    }
    
    /* is this test needed once we now we have JPEG ? */
-   /*
-   int photometric;
+   uint16 photometric;
    rv = TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &photometric );
    if(rv == 1 && (photometric != PHOTOMETRIC_RGB && photometric != PHOTOMETRIC_YCBCR)) {
-      ctx->set_error(ctx,500,"TIFF file \"%s\" is not RGB",
+      ctx->set_error(ctx,500,"TIFF file \"%s\" is not RGB: %d",
             filename);
       return;
    }
-   */
    
    /* the default is top-left, but check just in case */
    rv = TIFFGetField( hTIFF, TIFFTAG_ORIENTATION, &orientation );
@@ -196,14 +204,17 @@
     * - the number of tiles in each direction in the tiff must match what has been
     *   configured for the cache
     */
+   mapcache_grid_level *level = tile->grid_link->grid->levels[tile->z];
+   int ntilesx = MAPCACHE_MIN(dcache->count_x, level->maxx);
+   int ntilesy = MAPCACHE_MIN(dcache->count_y, level->maxy);
    if( tilewidth != tile->grid_link->grid->tile_sx ||
          tileheight != tile->grid_link->grid->tile_sy ||
-         imwidth != tile->grid_link->grid->tile_sx * dcache->count_x ||
-         imheight != tile->grid_link->grid->tile_sy * dcache->count_y ) {
+         imwidth != tile->grid_link->grid->tile_sx * ntilesx ||
+         imheight != tile->grid_link->grid->tile_sy * ntilesy ) {
       ctx->set_error(ctx,500,"TIFF file %s imagesize (%d,%d) and tilesize (%d,%d).\
             Expected (%d,%d),(%d,%d)",filename,imwidth,imheight,tilewidth,tileheight,
-            tile->grid_link->grid->tile_sx * dcache->count_x,
-            tile->grid_link->grid->tile_sy * dcache->count_y,
+            tile->grid_link->grid->tile_sx * ntilesx,
+            tile->grid_link->grid->tile_sy * ntilesy,
             tile->grid_link->grid->tile_sx,
             tile->grid_link->grid->tile_sy);
       return;
@@ -326,15 +337,24 @@
          int tiff_offx, tiff_offy; /* the x and y offset of the tile inside the tiff image */
          int tiff_off; /* the index of the tile inside the list of tiles of the tiff image */
          
+         /* 
+          * compute the width and height of the full tiff file. This
+          * is not simply the tile size times the number of tiles per
+          * file for lower zoom levels
+          */
+         mapcache_grid_level *level = tile->grid_link->grid->levels[tile->z];
+         int ntilesx = MAPCACHE_MIN(dcache->count_x, level->maxx);
+         int ntilesy = MAPCACHE_MIN(dcache->count_y, level->maxy);
+         
          /* x offset of the tile along a row */
-         tiff_offx = tile->x % dcache->count_x;
+         tiff_offx = tile->x % ntilesx;
 
          /* 
           * y offset of the requested row. we inverse it as the rows are ordered
           * from top to bottom, whereas the tile y is bottom to top
           */
-         tiff_offy = dcache->count_y - (tile->y % dcache->count_y) -1;
-         tiff_off = tiff_offy * dcache->count_x + tiff_offx;
+         tiff_offy = ntilesy - (tile->y % ntilesy) -1;
+         tiff_off = tiff_offy * ntilesx + tiff_offx;
          
          toff_t  *offsets=NULL, *sizes=NULL;
          
@@ -490,6 +510,10 @@
          tile->x,tile->y,tile->z,filename);
 #endif
 
+   /*
+    * create the directory where the tiff file will be stored
+    */
+
    /* find the location of the last '/' in the string */
    char *hackptr1,*hackptr2;
    hackptr1 = filename;
@@ -513,6 +537,10 @@
    *hackptr2 = '/';
 
 #if APR_HAS_THREADS
+   /*
+    * aquire a thread lock for the filename. The filename is hashed to avoid all
+    * threads locking here if they are to access different files
+    */
    unsigned int threadkey;
    if(ctx->has_threads) {
       threadkey = _hash_key(filename);
@@ -524,6 +552,11 @@
    }
 #endif
 
+   /*
+    * aquire a lock on the tiff file. This lock does not work for multiple threads of
+    * a same process, but should work on network filesystems.
+    * we previously aquired a thread lock so we should be ok here
+    */
    apr_file_t *flock;
    rv = apr_file_open(&flock,filename,APR_FOPEN_READ|APR_FOPEN_CREATE,APR_OS_DEFAULT,ctx->pool);
    if(rv != APR_SUCCESS) {
@@ -531,10 +564,13 @@
       return; /* we could not delete the file */
    }
 
-   apr_file_lock(flock,APR_FLOCK_EXCLUSIVE);
+   apr_file_lock(flock,APR_FLOCK_EXCLUSIVE); /* aquire the lock (this call is blocking) */
    apr_finfo_t finfo;
    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, flock);
 
+   /*
+    * check if the file exists by looking at its size
+    */
    if(finfo.size) {
       hTIFF = TIFFOpen(filename,"r+");
       create = 0;
@@ -552,37 +588,96 @@
       return;
    }
 
-   int w,h;
-   w = tile->grid_link->grid->tile_sx;
-   h = tile->grid_link->grid->tile_sy;
+   int tilew = tile->grid_link->grid->tile_sx;
+   int tileh = tile->grid_link->grid->tile_sy;
+
+   /* 
+    * compute the width and height of the full tiff file. This
+    * is not simply the tile size times the number of tiles per
+    * file for lower zoom levels
+    */
+   mapcache_grid_level *level = tile->grid_link->grid->levels[tile->z];
+   int ntilesx = MAPCACHE_MIN(dcache->count_x, level->maxx);
+   int ntilesy = MAPCACHE_MIN(dcache->count_y, level->maxy);
    if(create) {
-      TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, dcache->count_x * w );
-      TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, dcache->count_y * h );
-      TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, 8 );
+      /* populate the TIFF tags if we are creating the file */
+
       TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT );
-      TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL,4 );
       TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
       TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
+      TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, 8 );
       TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, COMPRESSION_JPEG );
-      TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, w );
-      TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, h );
+      TIFFSetField( hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB );
+      TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, tilew );
+      TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, tileh );
+      TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, ntilesx * tilew );
+      TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, ntilesy * tileh );
+      TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL,3 );
+
+#ifdef USE_GEOTIFF
+      double	adfPixelScale[3], adfTiePoints[6];
+#ifndef TIFFTAG_GEOPIXELSCALE
+ #define TIFFTAG_GEOPIXELSCALE 33550
+#endif
+#ifndef TIFFTAG_GEOTIEPOINTS
+ #define TIFFTAG_GEOTIEPOINTS 33922
+#endif
+      adfPixelScale[0] = adfPixelScale[1] = level->resolution;
+      adfPixelScale[2] = 0.0;
+      TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
+
+      adfTiePoints[0] = 0.0;
+      adfTiePoints[1] = 0.0;
+      adfTiePoints[2] = 0.0;
+      adfTiePoints[3] = -20000000;
+      adfTiePoints[4] = 20000000;
+      adfTiePoints[5] = 0.0;
+      TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
+
+      GTIF *psGTIF = GTIFNew( hTIFF );
+      GTIFSetFromProj4( psGTIF, apr_psprintf(ctx->pool,"+init=%s",tile->grid_link->grid->srs) );
+      GTIFWriteKeys( psGTIF );
+      GTIFFree( psGTIF );
+#endif
+
+            int cc = TIFFTileSize( hTIFF );
+            unsigned char *pabyZeros = (unsigned char *) calloc(cc,1);
+            TIFFWriteEncodedTile(hTIFF, 0, pabyZeros, cc);
+            free( pabyZeros );
+
    }
    int tiff_offx, tiff_offy; /* the x and y offset of the tile inside the tiff image */
    int tiff_off; /* the index of the tile inside the list of tiles of the tiff image */
 
    /* x offset of the tile along a row */
-   tiff_offx = tile->x % dcache->count_x;
+   tiff_offx = tile->x % ntilesx;
 
    /* 
     * y offset of the requested row. we inverse it as the rows are ordered
     * from top to bottom, whereas the tile y is bottom to top
     */
-   tiff_offy = dcache->count_y - (tile->y % dcache->count_y) -1;
-   tiff_off = tiff_offy * dcache->count_x + tiff_offx;
+   tiff_offy = ntilesy - (tile->y % ntilesy) -1;
+   tiff_off = tiff_offy * ntilesx + tiff_offx;
 
    mapcache_image *tileimg = mapcache_imageio_decode(ctx, tile->data);
 
-   TIFFWriteEncodedTile(hTIFF, tiff_off, tileimg->data, w*h*4);
+   /* remap xrgb to rgb */
+   unsigned char *rgb = (unsigned char*)malloc(tilew*tileh*3);
+   int r,c;
+   for(r=0;r<tileimg->h;r++) {
+      unsigned char *imptr = tileimg->data + r * tileimg->stride;
+      unsigned char *rgbptr = rgb + r * tilew * 3;
+      for(c=0;c<tileimg->w;c++) {
+         rgbptr[0] = imptr[2];
+         rgbptr[1] = imptr[1];
+         rgbptr[2] = imptr[0];
+         rgbptr += 3;
+         imptr += 4;
+      }
+   }
+
+   TIFFWriteEncodedTile(hTIFF, tiff_off, rgb, tilew*tileh*3);
+   free(rgb);
    TIFFWriteCheck( hTIFF, 1, "cache_set()");
 
    if(create)



More information about the mapserver-commits mailing list