[mapserver-commits] r11218 - trunk/mapserver
svn at osgeo.org
svn at osgeo.org
Fri Mar 18 09:41:33 EDT 2011
Author: warmerdam
Date: 2011-03-18 06:41:32 -0700 (Fri, 18 Mar 2011)
New Revision: 11218
Modified:
trunk/mapserver/mapgdal.c
trunk/mapserver/mapresample.c
trunk/mapserver/mapserver.h
trunk/mapserver/mapsymbol.h
trunk/mapserver/maputil.c
Log:
update raster alpha to account for buffer being pre-multiplied
Modified: trunk/mapserver/mapgdal.c
===================================================================
--- trunk/mapserver/mapgdal.c 2011-03-18 13:33:17 UTC (rev 11217)
+++ trunk/mapserver/mapgdal.c 2011-03-18 13:41:32 UTC (rev 11218)
@@ -344,9 +344,42 @@
"msSaveImageGDAL()" );
return MS_FAILURE;
}
+
pabyData = (GByte *)(pixptr + iLine*rb.data.rgba.row_step);
- GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
- pabyData, image->width, 1, GDT_Byte, rb.data.rgba.pixel_step, 0 );
+
+ if( rb.data.rgba.a == NULL || iBand == 3 )
+ {
+ GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
+ pabyData, image->width, 1, GDT_Byte,
+ rb.data.rgba.pixel_step, 0 );
+ }
+ else /* We need to un-pre-multiple RGB by alpha. */
+ {
+ GByte *pabyUPM = (GByte*) malloc(image->width);
+ GByte *pabyAlpha= (GByte *)(rb.data.rgba.a + iLine*rb.data.rgba.row_step);
+ int i;
+
+ for( i = 0; i < image->width; i++ )
+ {
+ int alpha = pabyAlpha[i*rb.data.rgba.pixel_step];
+
+ if( alpha == 0 )
+ pabyUPM[i] = 0;
+ else
+ {
+ int result = (pabyData[i*rb.data.rgba.pixel_step] * 255) / alpha;
+
+ if( result > 255 )
+ result = 255;
+
+ pabyUPM[i] = result;
+ }
+ }
+
+ GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
+ pabyUPM, image->width, 1, GDT_Byte, 1, 0 );
+ free( pabyUPM );
+ }
}
}
}
Modified: trunk/mapserver/mapresample.c
===================================================================
--- trunk/mapserver/mapresample.c 2011-03-18 13:33:17 UTC (rev 11217)
+++ trunk/mapserver/mapresample.c 2011-03-18 13:41:32 UTC (rev 11218)
@@ -185,14 +185,14 @@
nSetPoints++;
/* actual alpha blending is required */
- msAlphaBlend( src->r[src_rb_off],
- src->g[src_rb_off],
- src->b[src_rb_off],
- src->a[src_rb_off],
- dst->r + dst_rb_off,
- dst->g + dst_rb_off,
- dst->b + dst_rb_off,
- dst->a ? dst->a + dst_rb_off : NULL );
+ msAlphaBlendPM( src->r[src_rb_off],
+ src->g[src_rb_off],
+ src->b[src_rb_off],
+ src->a[src_rb_off],
+ dst->r + dst_rb_off,
+ dst->g + dst_rb_off,
+ dst->b + dst_rb_off,
+ dst->a ? dst->a + dst_rb_off : NULL );
}
}
@@ -475,13 +475,13 @@
red = (unsigned char) MAX(0,MIN(255,padfPixelSum[0]));
green = (unsigned char) MAX(0,MIN(255,padfPixelSum[1]));
blue = (unsigned char) MAX(0,MIN(255,padfPixelSum[2]));
- alpha = (unsigned char) MAX(0,MIN(255,255.5*dfWeightSum));
+ alpha = (unsigned char)MAX(0,MIN(255,255.5*dfWeightSum));
- msAlphaBlend( red, green, blue, alpha,
- dst_rb->data.rgba.r + dst_rb_off,
- dst_rb->data.rgba.g + dst_rb_off,
- dst_rb->data.rgba.b + dst_rb_off,
- (dst_rb->data.rgba.a == NULL) ? NULL : dst_rb->data.rgba.a + dst_rb_off );
+ msAlphaBlendPM( red, green, blue, alpha,
+ dst_rb->data.rgba.r + dst_rb_off,
+ dst_rb->data.rgba.g + dst_rb_off,
+ dst_rb->data.rgba.b + dst_rb_off,
+ (dst_rb->data.rgba.a == NULL) ? NULL : dst_rb->data.rgba.a + dst_rb_off );
}
}
}
Modified: trunk/mapserver/mapserver.h
===================================================================
--- trunk/mapserver/mapserver.h 2011-03-18 13:33:17 UTC (rev 11217)
+++ trunk/mapserver/mapserver.h 2011-03-18 13:41:32 UTC (rev 11218)
@@ -2289,6 +2289,11 @@
unsigned char blue_src, unsigned char alpha_src,
unsigned char *red_dst, unsigned char *green_dst,
unsigned char *blue_dst, unsigned char *alpha_dst );
+MS_DLL_EXPORT void msAlphaBlendPM(
+ unsigned char red_src, unsigned char green_src,
+ unsigned char blue_src, unsigned char alpha_src,
+ unsigned char *red_dst, unsigned char *green_dst,
+ unsigned char *blue_dst, unsigned char *alpha_dst );
MS_DLL_EXPORT int msCheckParentPointer(void* p, char* objname);
Modified: trunk/mapserver/mapsymbol.h
===================================================================
--- trunk/mapserver/mapsymbol.h 2011-03-18 13:33:17 UTC (rev 11217)
+++ trunk/mapserver/mapsymbol.h 2011-03-18 13:41:32 UTC (rev 11218)
@@ -84,6 +84,9 @@
} data;
} rasterBufferObj;
+/* NOTE: RB_SET_PIXEL() will premultiply by alpha, inputs should not be
+ premultiplied */
+
#define RB_SET_PIXEL(rb,x,y,red,green,blue,alpha) \
{ \
int _rb_off = (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step; \
@@ -100,6 +103,22 @@
} \
}
+/* This versions receives an input red/green/blue that is already
+ premultiplied with alpha */
+#define RB_SET_PIXEL_PM(rb,x,y,red,green,blue,alpha) \
+ { \
+ int _rb_off = (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step; \
+ (rb)->data.rgba.r[_rb_off] = red; \
+ (rb)->data.rgba.g[_rb_off] = green; \
+ (rb)->data.rgba.b[_rb_off] = blue; \
+ if( rb->data.rgba.a ) { \
+ (rb)->data.rgba.a[_rb_off] = alpha; \
+ } \
+ }
+
+/* NOTE: RB_MIX_PIXEL() will premultiply by alpha, inputs should not be
+ premultiplied */
+
#define RB_MIX_PIXEL(rb,x,y,red,green,blue,alpha) \
{ \
int _rb_off = (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step; \
Modified: trunk/mapserver/maputil.c
===================================================================
--- trunk/mapserver/maputil.c 2011-03-18 13:33:17 UTC (rev 11217)
+++ trunk/mapserver/maputil.c 2011-03-18 13:41:32 UTC (rev 11218)
@@ -1855,17 +1855,15 @@
msPluginFreeVirtualTableFactory();
}
-
-
/************************************************************************/
-/* msAlphaBlend() */
+/* msAlphaBlend() */
/* */
/* Function to overlay/blend an RGBA value into an existing */
/* RGBA value using the Porter-Duff "over" operator. */
/* Primarily intended for use with rasterBufferObj */
/* raster rendering. The "src" is the overlay value, and "dst" */
/* is the existing value being overlaid. dst is expected to be */
-/* premultiplied. */
+/* premultiplied, but the source should not be. */
/* */
/* NOTE: alpha_dst may be NULL. */
/************************************************************************/
@@ -1891,6 +1889,17 @@
return;
}
+/* -------------------------------------------------------------------- */
+/* Premultiple alpha for source values now. */
+/* -------------------------------------------------------------------- */
+ red_src = red_src * alpha_src / 255;
+ green_src = green_src * alpha_src / 255;
+ blue_src = blue_src * alpha_src / 255;
+
+/* -------------------------------------------------------------------- */
+/* Another pretty fast case if there is nothing in the */
+/* destination to mix with. */
+/* -------------------------------------------------------------------- */
if( alpha_dst && *alpha_dst == 0) {
*red_dst = red_src;
*green_dst = green_src;
@@ -1906,24 +1915,85 @@
{
int weight_dst = 255 - alpha_src;
- *red_dst = (red_src * alpha_src + *red_dst * weight_dst) / 255;
- *green_dst = (green_src * alpha_src + *green_dst * weight_dst) / 255;
- *blue_dst = (blue_src * alpha_src + *blue_dst * weight_dst) / 255;
+ *red_dst = (255 * red_src + *red_dst * weight_dst) / 255;
+ *green_dst = (255 * green_src + *green_dst * weight_dst) / 255;
+ *blue_dst = (255 * blue_src + *blue_dst * weight_dst) / 255;
}
else
{
- int weight_src = alpha_src;
- int weight_dst = (*alpha_dst * (255-alpha_src)) / 255;
- int weight_tot = weight_src + weight_dst;
+ int weight_dst = (255 - alpha_src);
- *red_dst = (red_src*weight_src + *red_dst*weight_dst) / weight_tot;
- *green_dst = (green_src*weight_src + *green_dst*weight_dst) /weight_tot;
- *blue_dst = (blue_src*weight_src + *blue_dst*weight_dst) / weight_tot;
+ *red_dst = (255 * red_src + *red_dst * weight_dst) / 255;
+ *green_dst = (255 * green_src + *green_dst * weight_dst) / 255;
+ *blue_dst = (255 * blue_src + *blue_dst * weight_dst) / 255;
- *alpha_dst = weight_tot;
+ *alpha_dst = (alpha_src * 255 + *alpha_dst * weight_dst) / 255;
}
}
+/************************************************************************/
+/* msAlphaBlendPM() */
+/* */
+/* Same as msAlphaBlend() except that the source RGBA is */
+/* assumed to already be premultiplied. */
+/************************************************************************/
+
+void msAlphaBlendPM( unsigned char red_src, unsigned char green_src,
+ unsigned char blue_src, unsigned char alpha_src,
+ unsigned char *red_dst, unsigned char *green_dst,
+ unsigned char *blue_dst, unsigned char *alpha_dst )
+{
+/* -------------------------------------------------------------------- */
+/* Simple cases we want to handle fast. */
+/* -------------------------------------------------------------------- */
+ if( alpha_src == 0 )
+ return;
+
+ if( alpha_src == 255 )
+ {
+ *red_dst = red_src;
+ *green_dst = green_src;
+ *blue_dst = blue_src;
+ if( alpha_dst )
+ *alpha_dst = 255;
+ return;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Another pretty fast case if there is nothing in the */
+/* destination to mix with. */
+/* -------------------------------------------------------------------- */
+ if( alpha_dst && *alpha_dst == 0) {
+ *red_dst = red_src;
+ *green_dst = green_src;
+ *blue_dst = blue_src;
+ *alpha_dst = alpha_src;
+ return;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Cases with actual blending. */
+/* -------------------------------------------------------------------- */
+ if(!alpha_dst || *alpha_dst == 255)
+ {
+ int weight_dst = 255 - alpha_src;
+
+ *red_dst = (255 * red_src + *red_dst * weight_dst) / 255;
+ *green_dst = (255 * green_src + *green_dst * weight_dst) / 255;
+ *blue_dst = (255 * blue_src + *blue_dst * weight_dst) / 255;
+ }
+ else
+ {
+ int weight_dst = (255 - alpha_src);
+
+ *red_dst = (255 * red_src + *red_dst * weight_dst) / 255;
+ *green_dst = (255 * green_src + *green_dst * weight_dst) / 255;
+ *blue_dst = (255 * blue_src + *blue_dst * weight_dst) / 255;
+
+ *alpha_dst = (alpha_src * 255 + *alpha_dst * weight_dst) / 255;
+ }
+}
+
/*
RFC 24: check if the parent pointer is NULL and raise an error otherwise
*/
More information about the mapserver-commits
mailing list