[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