Permalink
Browse files

initial implementation of masking on wcs coverages

1 parent 2f4b50a commit 7581744e01061dc9cac8f05e202e348c299f0402 @tbonfort tbonfort committed Aug 23, 2012
Showing with 173 additions and 10 deletions.
  1. +2 −2 mapdraw.c
  2. +20 −0 mapdrawgdal.c
  3. +25 −8 mapresample.c
  4. +63 −0 mapwcs.c
  5. +63 −0 mapwcs20.c
View
@@ -776,8 +776,8 @@ int msDrawLayer(mapObj *map, layerObj *layer, imageObj *image)
renderer->startLayer(image_draw,map,layer);
} else if (MS_RENDERER_PLUGIN(image_draw->format)) {
rendererVTableObj *renderer = MS_IMAGE_RENDERER(image_draw);
- if (layer->mask || (layer->opacity > 0 && layer->opacity < 100)) {
- if (!renderer->supports_transparent_layers) {
+ if ((layer->mask && layer->connectiontype!=MS_WMS && layer->type != MS_LAYER_RASTER) || (layer->opacity > 0 && layer->opacity < 100)) {
+ if (layer->mask || !renderer->supports_transparent_layers) {
image_draw = msImageCreate(image->width, image->height,
image->format, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL);
if (!image_draw) {
View
@@ -39,6 +39,7 @@ extern int InvGeoTransform( double *gt_in, double *gt_out );
#define MAXCOLORS 256
#define GEO_TRANS(tr,x,y) ((tr)[0]+(tr)[1]*(x)+(tr)[2]*(y))
+#define SKIP_MASK(x,y) (mask_rb && !*(mask_rb->data.rgba.a+(y)*mask_rb->data.rgba.row_step+(x)*mask_rb->data.rgba.pixel_step))
#if defined(USE_GDAL)
@@ -129,12 +130,21 @@ int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image,
GDALRasterBandH hBand1=NULL, hBand2=NULL, hBand3=NULL, hBandAlpha=NULL;
int bHaveRGBNoData = FALSE;
int nNoData1=-1,nNoData2=-1,nNoData3=-1;
+ rasterBufferObj *mask_rb = NULL;
#ifdef USE_GD
int anColorCube[256];
int cmt=0;
/*make sure we don't have a truecolor gd image*/
assert(!rb || rb->type != MS_BUFFER_GD || !gdImageTrueColor(rb->data.gd_img));
#endif
+ if(layer->mask) {
+ int ret;
+ layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask));
+ mask_rb = msSmallCalloc(1,sizeof(rasterBufferObj));
+ ret = MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,mask_rb);
+ if(ret != MS_SUCCESS)
+ return -1;
+ }
/*only support rawdata and pluggable renderers*/
assert(MS_RENDERER_RAWDATA(image->format) || (MS_RENDERER_PLUGIN(image->format) && rb));
@@ -854,6 +864,10 @@ int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image,
for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) {
for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) {
int src_pixel, src_alpha, cmap_alpha, merged_alpha;
+ if(SKIP_MASK(j,i)) {
+ k++;
+ continue;
+ }
src_pixel = pabyRaw1[k];
src_alpha = pabyRawAlpha[k];
@@ -891,6 +905,9 @@ int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image,
for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) {
for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) {
int src_pixel = pabyRaw1[k++];
+ if(SKIP_MASK(j,i)) {
+ continue;
+ }
if( rb_cmap[3][src_pixel] > 253 ) {
RB_SET_PIXEL( rb, j, i,
@@ -918,6 +935,9 @@ int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image,
k = 0;
for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) {
for( j = dst_xoff; j < dst_xoff + dst_xsize; j++, k++ ) {
+ if(SKIP_MASK(j,i)) {
+ continue;
+ }
if( MS_VALID_COLOR( layer->offsite )
&& pabyRaw1[k] == layer->offsite.red
&& pabyRaw2[k] == layer->offsite.green
View
@@ -38,6 +38,8 @@
# define MAX(a,b) ((a>b) ? a : b)
#endif
+#define SKIP_MASK(x,y) (mask_rb && !*(mask_rb->data.rgba.a+(y)*mask_rb->data.rgba.row_step+(x)*mask_rb->data.rgba.pixel_step))
+
/************************************************************************/
/* InvGeoTransform() */
/* */
@@ -86,7 +88,7 @@ msNearestRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
imageObj *psDstImage, rasterBufferObj *dst_rb,
int *panCMap,
SimpleTransformer pfnTransform, void *pCBData,
- int debug )
+ int debug, rasterBufferObj *mask_rb )
{
double *x, *y;
@@ -116,6 +118,8 @@ msNearestRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) {
int nSrcX, nSrcY;
+ if(SKIP_MASK(nDstX,nDstY))
+ continue;
if( !panSuccess[nDstX] ) {
nFailedPoints++;
@@ -330,7 +334,7 @@ msBilinearRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
imageObj *psDstImage, rasterBufferObj *dst_rb,
int *panCMap,
SimpleTransformer pfnTransform, void *pCBData,
- int debug )
+ int debug, rasterBufferObj *mask_rb )
{
double *x, *y;
@@ -363,6 +367,7 @@ msBilinearRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) {
int nSrcX, nSrcY, nSrcX2, nSrcY2;
double dfRatioX2, dfRatioY2, dfWeightSum = 0.0;
+ if(SKIP_MASK(nDstX,nDstY)) continue;
if( !panSuccess[nDstX] ) {
nFailedPoints++;
@@ -569,7 +574,7 @@ msAverageRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
imageObj *psDstImage, rasterBufferObj *dst_rb,
int *panCMap,
SimpleTransformer pfnTransform, void *pCBData,
- int debug )
+ int debug, rasterBufferObj *mask_rb )
{
double *x1, *y1, *x2, *y2;
@@ -607,6 +612,7 @@ msAverageRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) {
double dfXMin, dfYMin, dfXMax, dfYMax;
double dfAlpha01;
+ if(SKIP_MASK(nDstX,nDstY)) continue;
/* Do not generate a pixel unless all four corners transformed */
if( !panSuccess1[nDstX] || !panSuccess1[nDstX+1]
@@ -1246,14 +1252,23 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
char **papszAlteredProcessing = NULL;
int nLoadImgXSize, nLoadImgYSize;
double dfOversampleRatio;
- rasterBufferObj src_rb, *psrc_rb = NULL;
+ rasterBufferObj src_rb, *psrc_rb = NULL, *mask_rb = NULL;
const char *resampleMode = CSLFetchNameValue( layer->processing,
"RESAMPLE" );
if( resampleMode == NULL )
resampleMode = "NEAREST";
+
+ if(layer->mask) {
+ int ret;
+ layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask));
+ mask_rb = msSmallCalloc(1,sizeof(rasterBufferObj));
+ ret = MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,mask_rb);
+ if(ret != MS_SUCCESS)
+ return -1;
+ }
/* -------------------------------------------------------------------- */
/* We will require source and destination to have a valid */
@@ -1490,13 +1505,15 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
/* -------------------------------------------------------------------- */
{
char **papszSavedProcessing = layer->processing;
-
+ char* origMask = layer->mask;
+ layer->mask = NULL;
layer->processing = papszAlteredProcessing;
result = msDrawRasterLayerGDAL( &sDummyMap, layer, srcImage,
psrc_rb, hDS );
layer->processing = papszSavedProcessing;
+ layer->mask = origMask;
CSLDestroy( papszAlteredProcessing );
if( result ) {
@@ -1563,17 +1580,17 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
result =
msAverageRasterResampler( srcImage, psrc_rb, image, rb,
anCMap, msApproxTransformer, pACBData,
- layer->debug );
+ layer->debug, mask_rb );
else if( EQUAL(resampleMode,"BILINEAR") )
result =
msBilinearRasterResampler( srcImage, psrc_rb, image, rb,
anCMap, msApproxTransformer, pACBData,
- layer->debug );
+ layer->debug, mask_rb );
else
result =
msNearestRasterResampler( srcImage, psrc_rb, image, rb,
anCMap, msApproxTransformer, pACBData,
- layer->debug );
+ layer->debug, mask_rb );
/* -------------------------------------------------------------------- */
/* cleanup */
View
@@ -1910,6 +1910,69 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage()", par
msSetError(MS_WCSERR, "Map outputformat not supported for WCS!", "msWCSGetCoverage()");
return msWCSException(map, NULL, NULL, params->version );
}
+
+ if(lp->mask) {
+ int maskLayerIdx = msGetLayerIndex(map,lp->mask);
+ layerObj *maskLayer;
+ outputFormatObj *altFormat;
+ if(maskLayerIdx == -1) {
+ msSetError(MS_MISCERR, "Layer (%s) references unknown mask layer (%s)", "msDrawLayer()",
+ lp->name,lp->mask);
+ return (MS_FAILURE);
+ }
+ maskLayer = GET_LAYER(map, maskLayerIdx);
+ if(!maskLayer->maskimage) {
+ int i,retcode;
+ int origstatus, origlabelcache;
+ char *origImageType = msStrdup(map->imagetype);
+ altFormat = msSelectOutputFormat(map, "png24");
+ msInitializeRendererVTable(altFormat);
+ /* TODO: check the png24 format hasn't been tampered with, i.e. it's agg */
+ maskLayer->maskimage= msImageCreate(image->width, image->height,altFormat,
+ image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL);
+ if (!maskLayer->maskimage) {
+ msSetError(MS_MISCERR, "Unable to initialize mask image.", "msDrawLayer()");
+ return (MS_FAILURE);
+ }
+
+ /*
+ * force the masked layer to status on, and turn off the labelcache so that
+ * eventual labels are added to the temporary image instead of being added
+ * to the labelcache
+ */
+ origstatus = maskLayer->status;
+ origlabelcache = maskLayer->labelcache;
+ maskLayer->status = MS_ON;
+ maskLayer->labelcache = MS_OFF;
+
+ /* draw the mask layer in the temporary image */
+ retcode = msDrawLayer(map, maskLayer, maskLayer->maskimage);
+ maskLayer->status = origstatus;
+ maskLayer->labelcache = origlabelcache;
+ if(retcode != MS_SUCCESS) {
+ return MS_FAILURE;
+ }
+ /*
+ * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain
+ * symbols that reference it. We want to remove those references before the altFormat is destroyed
+ * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking
+ * it's for him.
+ */
+ for(i=0; i<map->symbolset.numsymbols; i++) {
+ if (map->symbolset.symbol[i]!=NULL) {
+ symbolObj *s = map->symbolset.symbol[i];
+ if(s->renderer == MS_IMAGE_RENDERER(maskLayer->maskimage)) {
+ MS_IMAGE_RENDERER(maskLayer->maskimage)->freeSymbol(s);
+ s->renderer = NULL;
+ }
+ }
+ }
+ /* set the imagetype from the original outputformat back (it was removed by msSelectOutputFormat() */
+ msFree(map->imagetype);
+ map->imagetype = origImageType;
+
+ }
+ }
if( image == NULL )
return msWCSException(map, NULL, NULL, params->version );
View
@@ -3461,6 +3461,69 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p
return msWCSException(map, NULL, NULL, params->version);
}
+ if(layer->mask) {
+ int maskLayerIdx = msGetLayerIndex(map,layer->mask);
+ layerObj *maskLayer;
+ outputFormatObj *altFormat;
+ if(maskLayerIdx == -1) {
+ msSetError(MS_MISCERR, "Layer (%s) references unknown mask layer (%s)", "msDrawLayer()",
+ layer->name,layer->mask);
+ return (MS_FAILURE);
+ }
+ maskLayer = GET_LAYER(map, maskLayerIdx);
+ if(!maskLayer->maskimage) {
+ int i,retcode;
+ int origstatus, origlabelcache;
+ char *origImageType = msStrdup(map->imagetype);
+ altFormat = msSelectOutputFormat(map, "png24");
+ msInitializeRendererVTable(altFormat);
+ /* TODO: check the png24 format hasn't been tampered with, i.e. it's agg */
+ maskLayer->maskimage= msImageCreate(image->width, image->height,altFormat,
+ image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL);
+ if (!maskLayer->maskimage) {
+ msSetError(MS_MISCERR, "Unable to initialize mask image.", "msDrawLayer()");
+ return (MS_FAILURE);
+ }
+
+ /*
+ * force the masked layer to status on, and turn off the labelcache so that
+ * eventual labels are added to the temporary image instead of being added
+ * to the labelcache
+ */
+ origstatus = maskLayer->status;
+ origlabelcache = maskLayer->labelcache;
+ maskLayer->status = MS_ON;
+ maskLayer->labelcache = MS_OFF;
+
+ /* draw the mask layer in the temporary image */
+ retcode = msDrawLayer(map, maskLayer, maskLayer->maskimage);
+ maskLayer->status = origstatus;
+ maskLayer->labelcache = origlabelcache;
+ if(retcode != MS_SUCCESS) {
+ return MS_FAILURE;
+ }
+ /*
+ * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain
+ * symbols that reference it. We want to remove those references before the altFormat is destroyed
+ * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking
+ * it's for him.
+ */
+ for(i=0; i<map->symbolset.numsymbols; i++) {
+ if (map->symbolset.symbol[i]!=NULL) {
+ symbolObj *s = map->symbolset.symbol[i];
+ if(s->renderer == MS_IMAGE_RENDERER(maskLayer->maskimage)) {
+ MS_IMAGE_RENDERER(maskLayer->maskimage)->freeSymbol(s);
+ s->renderer = NULL;
+ }
+ }
+ }
+ /* set the imagetype from the original outputformat back (it was removed by msSelectOutputFormat() */
+ msFree(map->imagetype);
+ map->imagetype = origImageType;
+
+ }
+ }
+
/* Actually produce the "grid". */
if( MS_RENDERER_RAWDATA(map->outputformat) ) {
status = msDrawRasterLayerLow( map, layer, image, NULL );

0 comments on commit 7581744

Please sign in to comment.