예제 #1
0
void progresslog(int x, int y, int z) {
   char msg[1024];
   if(quiet) return;
  
   
   sprintf(msg,"seeding tile %d %d %d",x,y,z);
   if(lastmsglen) {
      char erasestring[1024];
      int len = MAPCACHE_MIN(1023,lastmsglen);
      memset(erasestring,' ',len);
      erasestring[len+1]='\0';
      sprintf(erasestring,"\r%%%ds\r",lastmsglen);
      printf(erasestring," ");
   }
   lastmsglen = strlen(msg);
   printf("%s",msg);
   fflush(NULL);
   return;

   if(queuedtilestot>nthreads) {
      struct mctimeval now_t;
      float duration;
      float totalduration;
      seededtilestot = queuedtilestot - nthreads;

      mapcache_gettimeofday(&now_t,NULL);
      duration = ((now_t.tv_sec-lastlogtime.tv_sec)*1000000+(now_t.tv_usec-lastlogtime.tv_usec))/1000000.0;
      totalduration = ((now_t.tv_sec-starttime.tv_sec)*1000000+(now_t.tv_usec-starttime.tv_usec))/1000000.0;
      if(duration>=5) {
	int Nx, Ny, Ntot, Ncur, ntilessincelast;
         Nx = (grid_link->grid_limits[z][2]-grid_link->grid_limits[z][0])/tileset->metasize_x;
         Ny = (grid_link->grid_limits[z][3]-grid_link->grid_limits[z][1])/tileset->metasize_y;
         Ntot = Nx*Ny;
         Ncur = (y-grid_link->grid_limits[z][1])/tileset->metasize_y*Nx+(x-grid_link->grid_limits[z][0]+1)/tileset->metasize_x;
         ntilessincelast = seededtilestot-seededtiles;
         sprintf(msg,"seeding level %d [%d/%d]: %f metatiles/sec (avg since start: %f)",z,Ncur,Ntot,ntilessincelast/duration,
               seededtilestot/totalduration);
         lastlogtime=now_t;
         seededtiles=seededtilestot;
      } else {
         return;
      }
   } else {
      sprintf(msg,"seeding level %d",z);
   
   }
   if(lastmsglen) {
      char erasestring[1024];
      int len = MAPCACHE_MIN(1023,lastmsglen);
      memset(erasestring,' ',len);
      erasestring[len+1]='\0';
      sprintf(erasestring,"\r%%%ds\r",lastmsglen);
      printf(erasestring," ");
   }
   lastmsglen = strlen(msg);
   printf("%s",msg);
   fflush(NULL);
}
예제 #2
0
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;
   uint32 imwidth,imheight,tilewidth,tileheight;
   int16 planarconfig,orientation;
   uint16 compression;
   uint16 photometric;
   int rv;
   mapcache_grid_level *level;
   int ntilesx;
   int ntilesy;
   TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &imwidth );
   TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &imheight );
   TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &tilewidth );
   TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &tileheight );

   /* Test that the TIFF is tiled and not stripped */
   if(!TIFFIsTiled(hTIFF)) {
      ctx->set_error(ctx,500,"TIFF file \"%s\" is not tiled", filename);
      return;
   }
   
   /* check we have jpeg compression */
   rv = TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &compression );
   if(rv == 1 && compression != COMPRESSION_JPEG) {
      ctx->set_error(ctx,500,"TIFF file \"%s\" is not jpeg compressed",
            filename);
      return;
   }

   /* tiff must be pixel interleaved, not with a single image per band */
   rv = TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &planarconfig );
   if(rv == 1 && planarconfig != PLANARCONFIG_CONTIG) {
      ctx->set_error(ctx,500,"TIFF file \"%s\" is not pixel interleaved",
            filename);
      return;
   }
   
   /* is this test needed once we now we have JPEG ? */
   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: %d",
            filename);
      return;
   }
   
   /* the default is top-left, but check just in case */
   rv = TIFFGetField( hTIFF, TIFFTAG_ORIENTATION, &orientation );
   if(rv == 1 && orientation != ORIENTATION_TOPLEFT) {
      ctx->set_error(ctx,500,"TIFF file \"%s\" is not top-left oriented",
            filename);
      return;
   }

   /* check that the tiff internal tiling aligns with the mapcache_grid we are using:
    * - the tiff tile size must match the grid tile size
    * - the number of tiles in each direction in the tiff must match what has been
    *   configured for the cache
    */
   level = tile->grid_link->grid->levels[tile->z];
   ntilesx = MAPCACHE_MIN(dcache->count_x, level->maxx);
   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 * 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 * ntilesx,
            tile->grid_link->grid->tile_sy * ntilesy,
            tile->grid_link->grid->tile_sx,
            tile->grid_link->grid->tile_sy);
      return;
   }
예제 #3
0
int main(int argc, const char **argv) {
    /* initialize apr_getopt_t */
    apr_getopt_t *opt;
    const char *configfile=NULL;
#ifndef USE_FORK
    apr_thread_t **threads;
    apr_threadattr_t *thread_attrs;
#endif
    const char *tileset_name=NULL;
    const char *tileset_transfer_name=NULL;
    const char *grid_name = NULL;
    int *zooms = NULL;//[2];
    double *extent = NULL;//[4];
    int optch;
    int rv,n;
    const char *old = NULL;
    const char *optarg;
    apr_table_t *argdimensions;
    char *dimkey=NULL, *dimvalue=NULL,*key, *last, *optargcpy=NULL;
    int keyidx;
    int *metasizes = NULL;//[2];
    int metax=-1,metay=-1;

#ifdef USE_CLIPPERS
    const char *ogr_where = NULL;
    const char *ogr_layer = NULL;
    const char *ogr_sql = NULL;
    const char *ogr_datasource = NULL;
#endif

    apr_initialize();
    (void) signal(SIGINT,handle_sig_int);
    apr_pool_create(&ctx.pool,NULL);
    mapcache_context_init(&ctx);
    ctx.process_pool = ctx.pool;
#ifndef USE_FORK
    apr_thread_mutex_create((apr_thread_mutex_t**)&ctx.threadlock,APR_THREAD_MUTEX_DEFAULT,ctx.pool);
#else
    ctx.threadlock = NULL;
#endif
    cfg = mapcache_configuration_create(ctx.pool);
    ctx.config = cfg;
    ctx.log= mapcache_context_seeding_log;
    apr_getopt_init(&opt, ctx.pool, argc, argv);

    seededtiles=seededtilestot=queuedtilestot=0;
    mapcache_gettimeofday(&starttime,NULL);
    lastlogtime=starttime;
    argdimensions = apr_table_make(ctx.pool,3);
    

    /* parse the all options based on opt_option[] */
    while ((rv = apr_getopt_long(opt, seed_options, &optch, &optarg)) == APR_SUCCESS) {
        switch (optch) {
            case 'h':
                return usage(argv[0],NULL);
                break;
            case 'f':
               force = 1;
               break;
            case 'q':
                quiet = 1;
                break;
            case 'v':
                verbose = 1;
                break;
            case 'c':
                configfile = optarg;
                break;
            case 'g':
                grid_name = optarg;
                break;
            case 't':
                tileset_name = optarg;
                break;
            case 'x':
                tileset_transfer_name = optarg;
                break;
            case 'm':
                if(!strcmp(optarg,"delete")) {
                   mode = MAPCACHE_CMD_DELETE;
                } else if(!strcmp(optarg,"transfer")){
  		   mode = MAPCACHE_CMD_TRANSFER;
                } else if(strcmp(optarg,"seed")){
                   return usage(argv[0],"invalid mode, expecting \"seed\", \"delete\" or \"transfer\"");
                } else {
                   mode = MAPCACHE_CMD_SEED;
                }
                break;
            case 'n':
                nthreads = (int)strtol(optarg, NULL, 10);
                break;
            case 'e':
                if ( MAPCACHE_SUCCESS != mapcache_util_extract_double_list(&ctx, (char*)optarg, ",", &extent, &n) ||
                        n != 4 || extent[0] >= extent[2] || extent[1] >= extent[3] ) {
                    return usage(argv[0], "failed to parse extent, expecting comma separated 4 doubles");
                }
                break;
            case 'z':
                if ( MAPCACHE_SUCCESS != mapcache_util_extract_int_list(&ctx, (char*)optarg, ",", &zooms, &n) ||
                        n != 2 || zooms[0] > zooms[1]) {
                    return usage(argv[0], "failed to parse zooms, expecting comma separated 2 ints");
                } else {
                   minzoom = zooms[0];
                   maxzoom = zooms[1];
                }
                break;
            case 'M':
                if ( MAPCACHE_SUCCESS != mapcache_util_extract_int_list(&ctx, (char*)optarg, ",", &metasizes, &n) ||
                        n != 2 || metasizes[0] <= 0 || metasizes[1] <=0) {
                    return usage(argv[0], "failed to parse metasize, expecting comma separated 2 positive ints (e.g. -M 8,8");
                } else {
                   metax = metasizes[0];
                   metay = metasizes[1];
                }
                break;
            case 'o':
                old = optarg;
                break;
            case 'D':
                optargcpy = apr_pstrdup(ctx.pool,optarg);
                keyidx = 0;
                for (key = apr_strtok(optargcpy, "=", &last); key != NULL;
                      key = apr_strtok(NULL, "=", &last)) {
                   if(keyidx == 0) {
                      dimkey = key;
                   } else {
                      dimvalue = key;
                   }
                   keyidx++;
                }
                if(keyidx!=2 || !dimkey || !dimvalue || !*dimkey || !*dimvalue) {
                   return usage(argv[0], "failed to parse dimension, expecting DIMNAME=DIMVALUE");
                }
                apr_table_set(argdimensions,dimkey,dimvalue);
                break;
#ifdef USE_CLIPPERS
            case 'd':
                ogr_datasource = optarg;
                break;
            case 's':
                ogr_sql = optarg;
                break;
            case 'l':
                ogr_layer = optarg;
                break;
            case 'w':
               ogr_where = optarg;
               break;
#endif

        }
    }
    if (rv != APR_EOF) {
        return usage(argv[0],"bad options");
    }

    if( ! configfile ) {
        return usage(argv[0],"config not specified");
    } else {
        mapcache_configuration_parse(&ctx,configfile,cfg,0);
        if(ctx.get_error(&ctx))
            return usage(argv[0],ctx.get_error_message(&ctx));
        mapcache_configuration_post_config(&ctx,cfg);
        if(ctx.get_error(&ctx))
            return usage(argv[0],ctx.get_error_message(&ctx));
    }

#ifdef USE_CLIPPERS
    if(extent && ogr_datasource) {
       return usage(argv[0], "cannot specify both extent and ogr-datasource");
    }

    if( ogr_sql && ( ogr_where || ogr_layer )) {
      return usage(argv[0], "ogr-where or ogr_layer cannot be used in conjunction with ogr-sql");
    }

    if(ogr_datasource) {
      OGRDataSourceH hDS = NULL;
       OGRLayerH layer = NULL;
       OGRRegisterAll();
       
       hDS = OGROpen( ogr_datasource, FALSE, NULL );
       if( hDS == NULL )
       {
          printf( "OGR Open failed\n" );
          exit( 1 );
       }

       if(ogr_sql) {
         layer = OGR_DS_ExecuteSQL( hDS, ogr_sql, NULL, NULL);
         if(!layer) {
            return usage(argv[0],"aborting");
         }
       } else {
         int nLayers = OGR_DS_GetLayerCount(hDS);
         if(nLayers>1 && !ogr_layer) {
            return usage(argv[0],"ogr datastore contains more than one layer. please specify which one to use with --ogr-layer");
         } else {
            if(ogr_layer) {
               layer = OGR_DS_GetLayerByName(hDS,ogr_layer);
            } else {
               layer = OGR_DS_GetLayer(hDS,0);
            }
            if(!layer) {
               return usage(argv[0],"aborting");
            }
            if(ogr_where) {
               if(OGRERR_NONE != OGR_L_SetAttributeFilter(layer, ogr_where)) {
                  return usage(argv[0],"aborting");
               }
            }

         }
       }
      if((nClippers=OGR_L_GetFeatureCount(layer, TRUE)) == 0) {
         return usage(argv[0],"no features in provided ogr parameters, cannot continue");
      }


      initGEOS(notice, log_and_exit);
      clippers = (const GEOSPreparedGeometry**)malloc(nClippers*sizeof(GEOSPreparedGeometry*));


      OGRFeatureH hFeature;
      GEOSWKTReader *geoswktreader = GEOSWKTReader_create();
      OGR_L_ResetReading(layer);
      extent = apr_pcalloc(ctx.pool,4*sizeof(double));
      int f=0;
      while( (hFeature = OGR_L_GetNextFeature(layer)) != NULL ) {
         OGRGeometryH geom = OGR_F_GetGeometryRef(hFeature);
         if(!geom ||  !OGR_G_IsValid(geom)) continue;
         char *wkt;
         OGR_G_ExportToWkt(geom,&wkt);
         GEOSGeometry *geosgeom = GEOSWKTReader_read(geoswktreader,wkt);
         free(wkt);
         clippers[f] = GEOSPrepare(geosgeom);
         //GEOSGeom_destroy(geosgeom);
         OGREnvelope ogr_extent;
         OGR_G_GetEnvelope	(geom, &ogr_extent);	
         if(f == 0) {
            extent[0] = ogr_extent.MinX;
            extent[1] = ogr_extent.MinY;
            extent[2] = ogr_extent.MaxX;
            extent[3] = ogr_extent.MaxY;
         } else {
            extent[0] = MAPCACHE_MIN(ogr_extent.MinX, extent[0]);
            extent[1] = MAPCACHE_MIN(ogr_extent.MinY, extent[1]);
            extent[2] = MAPCACHE_MAX(ogr_extent.MaxX, extent[2]);
            extent[3] = MAPCACHE_MAX(ogr_extent.MaxY, extent[3]);
         }

         OGR_F_Destroy( hFeature );
         f++;
      }
      nClippers = f;
      

    }
#endif

    if( ! tileset_name ) {
        return usage(argv[0],"tileset not specified");
    } else {
        tileset = mapcache_configuration_get_tileset(cfg,tileset_name);
        if(!tileset) {
            return usage(argv[0], "tileset not found in configuration");
        }
        if( ! grid_name ) {
           grid_link = APR_ARRAY_IDX(tileset->grid_links,0,mapcache_grid_link*);
        } else {
예제 #4
0
/**
 * Compute a palette for the given RGBA rasterBuffer using a median cut quantization.
 * - rb: the rasterBuffer to quantize
 * - reqcolors: the desired number of colors the palette should contain. will be set
 *   with the actual number of entries in the computed palette
 * - palette: preallocated array of palette entries that will be populated by the
 *   function
 * - maxval: max value of pixel intensity. In some cases, the input data has to
 *   be rescaled to compute the quantization. if the returned value of maxscale is
 *   less than 255, this means that the input pixels have been rescaled, and that
 *   the returned palette must be upscaled before being written to the png file
 * - forced_palette: entries that should appear in the computed palette
 * - num_forced_palette_entries: number of entries contained in "force_palette". if 0,
 *   "force_palette" can be NULL
 */
int _mapcache_imageio_quantize_image(mapcache_image *rb,
      unsigned int *reqcolors, rgbaPixel *palette,
      unsigned int *maxval,
      rgbaPixel *forced_palette, int num_forced_palette_entries) {

   rgbaPixel **apixels=NULL; /* pointer to the start rows of truecolor pixels */
   register rgbaPixel *pP;
   register int col;

   unsigned char newmaxval;
   acolorhist_vector achv, acolormap=NULL;

   int row;
   int colors;
   int newcolors = 0;

   int x;
   /*  int channels;  */


   *maxval = 255;

   apixels=(rgbaPixel**)malloc(rb->h*sizeof(rgbaPixel**));
   if(!apixels) return MAPCACHE_FAILURE;

   for(row=0;row<rb->h;row++) {
      apixels[row]=(rgbaPixel*)(&(rb->data[row * rb->stride]));
   }

   /*
    ** Step 2: attempt to make a histogram of the colors, unclustered.
    ** If at first we don't succeed, lower maxval to increase color
    ** coherence and try again.  This will eventually terminate, with
    ** maxval at worst 15, since 32^3 is approximately MAXCOLORS.
                  [GRR POSSIBLE BUG:  what about 32^4 ?]
    */
   for ( ; ; ) {
      achv = pam_computeacolorhist(
            apixels, rb->w, rb->h, MAXCOLORS, &colors );
      if ( achv != (acolorhist_vector) 0 )
         break;
      newmaxval = *maxval / 2;
      for ( row = 0; row < rb->h; ++row )
         for ( col = 0, pP = apixels[row]; col < rb->w; ++col, ++pP )
            PAM_DEPTH( *pP, *pP, *maxval, newmaxval );
      *maxval = newmaxval;
   }
   newcolors = MAPCACHE_MIN(colors, *reqcolors);
   acolormap = mediancut(achv, colors, rb->w*rb->h, *maxval, newcolors);
   pam_freeacolorhist(achv);


   *reqcolors = newcolors;


   for (x = 0; x < newcolors; ++x) {
      palette[x].r = acolormap[x].acolor.r;
      palette[x].g = acolormap[x].acolor.g;
      palette[x].b = acolormap[x].acolor.b;
      palette[x].a = acolormap[x].acolor.a;
   }

   free(acolormap);
   free(apixels);
   return MAPCACHE_SUCCESS;
}