Skip to content

Commit

Permalink
initial implementation of masking on wcs coverages
Browse files Browse the repository at this point in the history
  • Loading branch information
tbonfort committed Aug 23, 2012
1 parent 2f4b50a commit 7581744
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 10 deletions.
4 changes: 2 additions & 2 deletions mapdraw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
20 changes: 20 additions & 0 deletions mapdrawgdal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
33 changes: 25 additions & 8 deletions mapresample.c
Original file line number Diff line number Diff line change
Expand Up @@ -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() */
/* */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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++;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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++;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 ) {
Expand Down Expand Up @@ -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 */
Expand Down
63 changes: 63 additions & 0 deletions mapwcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down
63 changes: 63 additions & 0 deletions mapwcs20.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down

0 comments on commit 7581744

Please sign in to comment.