Permalink
Browse files

implementation of masking on wcs coverages (#4469)

  • Loading branch information...
1 parent 27c1c75 commit 237c7a8d0f93e38e2f7aa9d0ad43db150126f592 @tbonfort tbonfort committed Aug 23, 2012
Showing with 221 additions and 16 deletions.
  1. +5 −2 mapdraw.c
  2. +62 −6 mapdrawgdal.c
  3. +28 −8 mapresample.c
  4. +63 −0 mapwcs.c
  5. +63 −0 mapwcs20.c
View
@@ -776,8 +776,11 @@ 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)) {
+ /* masking occurs at the pixel/layer level for raster images, so we don't need to create a temporary image
+ in these cases
+ */
+ 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));
@@ -808,6 +818,9 @@ int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image,
alpha = pabyRawAlpha[k];
result = cmap[pabyRaw1[k++]];
+ if(SKIP_MASK(j,i)) {
+ continue;
+ }
/*
** We don't do alpha blending in non-truecolor mode, just
@@ -834,6 +847,9 @@ int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image,
for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) {
result = cmap[pabyRaw1[k++]];
+ if(SKIP_MASK(j,i)) {
+ continue;
+ }
if( result != -1 ) {
rb->data.gd_img->pixels[i][j] = result;
}
@@ -854,6 +870,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 +911,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 +941,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
@@ -972,6 +998,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
@@ -1000,6 +1029,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++, k++ ) {
int cc_index;
+ if(SKIP_MASK(j,i)) {
+ continue;
+ }
if( MS_VALID_COLOR( layer->offsite )
&& pabyRaw1[k] == layer->offsite.red
@@ -1031,6 +1063,7 @@ int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image,
** Cleanup
*/
+ msFree( mask_rb );
free( pabyRaw1 );
if( hColorMap != NULL )
@@ -1879,6 +1912,15 @@ msDrawRasterLayerGDAL_RawMode(
unsigned char *b_nodatas = NULL;
GInt16 *i_nodatas = NULL;
int got_nodata=FALSE;
+ rasterBufferObj *mask_rb = NULL;
+ 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;
+ }
if( image->format->bands > 256 ) {
msSetError( MS_IMGERR, "Too many bands (more than 256).",
@@ -1998,8 +2040,8 @@ msDrawRasterLayerGDAL_RawMode(
+ band*image->width*image->height;
int off_mask = j + i * image->width;
- if( i_nodatas
- && ((GInt16 *) pBuffer)[k] == i_nodatas[band] ) {
+ if( ( i_nodatas && ((GInt16 *) pBuffer)[k] == i_nodatas[band] )
+ || SKIP_MASK(j,i)) {
k++;
continue;
}
@@ -2013,8 +2055,8 @@ msDrawRasterLayerGDAL_RawMode(
+ band*image->width*image->height;
int off_mask = j + i * image->width;
- if( f_nodatas
- && ((float *) pBuffer)[k] == f_nodatas[band] ) {
+ if( ( f_nodatas && ((float *) pBuffer)[k] == f_nodatas[band] )
+ || SKIP_MASK(j,i)) {
k++;
continue;
}
@@ -2028,8 +2070,8 @@ msDrawRasterLayerGDAL_RawMode(
+ band*image->width*image->height;
int off_mask = j + i * image->width;
- if( b_nodatas
- && ((unsigned char *) pBuffer)[k] == b_nodatas[band] ) {
+ if( ( b_nodatas && ((unsigned char *) pBuffer)[k] == b_nodatas[band] )
+ || SKIP_MASK(j,i)) {
k++;
continue;
}
@@ -2041,6 +2083,7 @@ msDrawRasterLayerGDAL_RawMode(
}
}
+ msFree( mask_rb );
free( pBuffer );
free( f_nodatas );
@@ -2077,6 +2120,15 @@ msDrawRasterLayerGDAL_16BitClassification(
int *cmap, c, j, k, bGotNoData = FALSE, bGotFirstValue;
unsigned char *rb_cmap[4];
CPLErr eErr;
+ rasterBufferObj *mask_rb = NULL;
+ 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;
+ }
assert( rb->type == MS_BUFFER_GD || rb->type == MS_BUFFER_BYTE_RGBA );
@@ -2283,6 +2335,9 @@ msDrawRasterLayerGDAL_16BitClassification(
continue;
}
+ if(SKIP_MASK(j,i))
+ continue;
+
/*
* The funny +1/-1 is to avoid odd rounding around zero.
* We could use floor() but sometimes it is expensive.
@@ -2322,6 +2377,7 @@ msDrawRasterLayerGDAL_16BitClassification(
free( rb_cmap[1] );
free( rb_cmap[2] );
free( rb_cmap[3] );
+ msFree( mask_rb );
assert( k == dst_xsize * dst_ysize );
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++;
@@ -229,6 +233,7 @@ msNearestRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
free( panSuccess );
free( x );
free( y );
+ msFree(mask_rb);
/* -------------------------------------------------------------------- */
/* Some debugging output. */
@@ -330,7 +335,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 +368,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++;
@@ -489,6 +495,7 @@ msBilinearRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
free( panSuccess );
free( x );
free( y );
+ msFree(mask_rb);
/* -------------------------------------------------------------------- */
/* Some debugging output. */
@@ -569,7 +576,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 +614,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]
@@ -708,6 +716,7 @@ msAverageRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
free( panSuccess2 );
free( x2 );
free( y2 );
+ msFree(mask_rb);
/* -------------------------------------------------------------------- */
/* Some debugging output. */
@@ -1246,14 +1255,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 +1508,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 +1583,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 */
Oops, something went wrong.

0 comments on commit 237c7a8

Please sign in to comment.