[mapserver-commits] r12640 - trunk/mapserver/mapcache/src

svn at osgeo.org svn at osgeo.org
Fri Oct 7 13:05:55 EDT 2011


Author: tbonfort
Date: 2011-10-07 10:05:55 -0700 (Fri, 07 Oct 2011)
New Revision: 12640

Modified:
   trunk/mapserver/mapcache/src/image.c
   trunk/mapserver/mapcache/src/imageio_jpeg.c
   trunk/mapserver/mapcache/src/imageio_png.c
Log:
switch internal image representation to premultiplied pixels, with argb ordering. This allows us to directly use the image buffers created by mapserver without having to go through an image compression/decompression


Modified: trunk/mapserver/mapcache/src/image.c
===================================================================
--- trunk/mapserver/mapcache/src/image.c	2011-10-07 15:59:01 UTC (rev 12639)
+++ trunk/mapserver/mapcache/src/image.c	2011-10-07 17:05:55 UTC (rev 12640)
@@ -95,7 +95,7 @@
                bptr[1]=optr[1];
                bptr[2]=optr[2];
                bptr[3]=optr[3];
-            } else {
+            } else if(optr[3] != 0) {
                unsigned int br = bptr[0];
                unsigned int bg = bptr[1];
                unsigned int bb = bptr[2];
@@ -104,10 +104,11 @@
                unsigned int og = optr[1];
                unsigned int ob = optr[2];
                unsigned int oa = optr[3];
-               bptr[0] += (unsigned char)(((or - br)*oa) >> 8);
-               bptr[1] += (unsigned char)(((og - bg)*oa) >> 8);
-               bptr[2] += (unsigned char)(((ob - bb)*oa) >> 8);
-               bptr[3] = (ba==255)?255:(unsigned char)((oa + ba) - ((oa * ba + 255) >> 8));                        
+               bptr[0] = (unsigned char)(or + (((255-oa)*br)>>8));
+               bptr[1] = (unsigned char)(og + (((255-oa)*bg)>>8));
+               bptr[2] = (unsigned char)(ob + (((255-oa)*bb)>>8));
+
+               bptr[3] = oa+((ba*(255-oa))>>8);                    
             }
          }
          bptr+=4;optr+=4;

Modified: trunk/mapserver/mapcache/src/imageio_jpeg.c
===================================================================
--- trunk/mapserver/mapcache/src/imageio_jpeg.c	2011-10-07 15:59:01 UTC (rev 12639)
+++ trunk/mapserver/mapcache/src/imageio_jpeg.c	2011-10-07 17:05:55 UTC (rev 12640)
@@ -183,9 +183,9 @@
       JSAMPLE *pixptr = rowdata;
       int col;
       unsigned char *r,*g,*b;
-      r=&(img->data[0])+row*img->stride;
+      r=&(img->data[2])+row*img->stride;
       g=&(img->data[1])+row*img->stride;
-      b=&(img->data[2])+row*img->stride;
+      b=&(img->data[0])+row*img->stride;
       for(col=0;col<img->w;col++) {
          *(pixptr++) = *r;
          *(pixptr++) = *g;
@@ -249,10 +249,12 @@
       {
          for (i = 0; i < img->w; i++)
          {
-            *rowptr++ = *tempptr++;
-            *rowptr++ = *tempptr++;
-            *rowptr++ = *tempptr++;
-            *rowptr++ = 255;
+            rowptr[0] = tempptr[2];
+            rowptr[1] = tempptr[1];
+            rowptr[2] = tempptr[0];
+            rowptr[3] = 255;
+            rowptr+=4;
+            tempptr+=3;
          }
       }
       else

Modified: trunk/mapserver/mapcache/src/imageio_png.c
===================================================================
--- trunk/mapserver/mapcache/src/imageio_png.c	2011-10-07 15:59:01 UTC (rev 12639)
+++ trunk/mapserver/mapcache/src/imageio_png.c	2011-10-07 17:05:55 UTC (rev 12640)
@@ -55,6 +55,14 @@
    // do nothing
 }
 
+static inline int
+premultiply (int color,int alpha)
+{
+    int temp = (alpha * color) + 0x80;
+    return ((temp + (temp >> 8)) >> 8);
+}
+
+
 void _mapcache_imageio_png_decode_to_image(mapcache_context *ctx, mapcache_buffer *buffer,
       mapcache_image *img) {
    int bit_depth,color_type,i;
@@ -123,6 +131,32 @@
    
    png_read_end(png_ptr,NULL);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+
+   /* switch buffer from rgba to premultiplied argb */
+   for(i=0;i<img->h;i++) {
+      unsigned int j;
+      unsigned char *pixptr = row_pointers[i];
+      for(j=0;j<img->w;j++) {
+         unsigned char pixel[4];
+         memcpy (pixel, pixptr, sizeof (uint32_t));
+         uint8_t  alpha = pixel[3];
+         if(alpha == 255) {
+            pixptr[0] = pixel[2];
+            pixptr[1] = pixel[1];
+            pixptr[2] = pixel[0];
+         } else if (alpha == 0) {
+            pixptr[0] = 0;
+            pixptr[1] = 0;
+            pixptr[2] = 0;
+         } else {
+            pixptr[0] = premultiply(pixel[2],alpha);
+            pixptr[1] = premultiply(pixel[1],alpha);
+            pixptr[2] = premultiply(pixel[0],alpha);
+         }
+         pixptr += 4;
+      }
+   }
+
 }
 
    
@@ -134,6 +168,51 @@
    return img;
 }
 
+/* png transform function to switch from premultiplied argb to png expected rgba */
+static void
+argb_to_rgba (png_structp png, png_row_infop row_info, png_bytep data)
+{
+   unsigned int i;
+
+   for (i = 0; i < row_info->rowbytes; i += 4) {
+      uint8_t *b = &data[i];
+      uint32_t pixel;
+      uint8_t  alpha;
+
+      memcpy (&pixel, b, sizeof (uint32_t));
+      alpha = (pixel & 0xff000000) >> 24;
+      if (alpha == 0) {
+         b[0] = b[1] = b[2] = b[3] = 0;
+      } else {
+         b[0] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
+         b[1] = (((pixel & 0x00ff00) >>  8) * 255 + alpha / 2) / alpha;
+         b[2] = (((pixel & 0x0000ff) >>  0) * 255 + alpha / 2) / alpha;
+         b[3] = alpha;
+      }
+   }
+}
+
+
+/* png transform function to switch from xrgb to rgbx (x is ignored)*/
+static void
+xrgb_to_rgbx (png_structp png, png_row_infop row_info, png_bytep data)
+{
+   unsigned int i;
+
+   for (i = 0; i < row_info->rowbytes; i += 4) {
+      uint8_t *b = &data[i];
+      uint32_t pixel;
+
+      memcpy (&pixel, b, sizeof (uint32_t));
+
+      b[0] = (pixel & 0xff0000) >> 16;
+      b[1] = (pixel & 0x00ff00) >>  8;
+      b[2] = (pixel & 0x0000ff) >>  0;
+   }
+}
+
+
+
 /**
  * \brief encode an image to RGB(A) PNG format
  * \private \memberof mapcache_image_format_png
@@ -186,8 +265,12 @@
          PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
 
    png_write_info(png_ptr, info_ptr);
-   if(color_type == PNG_COLOR_TYPE_RGB)
-       png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);
+   if(color_type == PNG_COLOR_TYPE_RGB) {
+      png_set_write_user_transform_fn (png_ptr, xrgb_to_rgbx);
+      png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);
+   } else {
+      png_set_write_user_transform_fn (png_ptr, argb_to_rgba);
+   }
 
    png_bytep rowptr = img->data;
    for(row=0;row<img->h;row++) {
@@ -219,7 +302,7 @@
  */
 
 typedef struct {
-   unsigned char r,g,b,a;
+   unsigned char b,g,r,a;
 } rgbaPixel;
 
 typedef struct {
@@ -993,14 +1076,35 @@
    for (x = 0; x < numPaletteEntries; ++x) {
       if(maxval == 255) {
          a[remap[x]] = palette[x].a;
-         rgb[remap[x]].r = palette[x].r;
-         rgb[remap[x]].g = palette[x].g;
-         rgb[remap[x]].b = palette[x].b;
+         if(palette[x].a == 255) {
+            rgb[remap[x]].r = palette[x].r;
+            rgb[remap[x]].g = palette[x].g;
+            rgb[remap[x]].b = palette[x].b;
+         } else if(palette[x].a == 0) {
+            rgb[remap[x]].r = 0;
+            rgb[remap[x]].g = 0;
+            rgb[remap[x]].b = 0;
+         } else {
+            /* un-premultiply the palette entries */
+            rgb[remap[x]].r = (palette[x].r * 255 + palette[x].a / 2) / palette[x].a ;
+            rgb[remap[x]].g = (palette[x].g * 255 + palette[x].a / 2) / palette[x].a ;
+            rgb[remap[x]].b = (palette[x].b * 255 + palette[x].a / 2) / palette[x].a ;
+         }
       } else {
-         rgb[remap[x]].r = (palette[x].r * 255 + (maxval >> 1)) / maxval;
-         rgb[remap[x]].g = (palette[x].g * 255 + (maxval >> 1)) / maxval;
-         rgb[remap[x]].b = (palette[x].b * 255 + (maxval >> 1)) / maxval;
-         a[remap[x]] = (palette[x].a * 255 + (maxval >> 1)) / maxval;
+         /* un-scale and un-premultiply the palette entries */
+         unsigned char al = a[remap[x]] = (palette[x].a * 255 + (maxval >> 1)) / maxval;
+         if(al == 255) {
+            rgb[remap[x]].r = (palette[x].r * 255 + (maxval >> 1)) / maxval;
+            rgb[remap[x]].g = (palette[x].g * 255 + (maxval >> 1)) / maxval;
+            rgb[remap[x]].b = (palette[x].b * 255 + (maxval >> 1)) / maxval;
+         } else if(al == 0) {
+            rgb[remap[x]].r = rgb[remap[x]].g = rgb[remap[x]].b = 0;
+
+         } else {
+            rgb[remap[x]].r = (((palette[x].r * 255 + (maxval >> 1)) / maxval) * 255 + al / 2) / al;
+            rgb[remap[x]].g = (((palette[x].g * 255 + (maxval >> 1)) / maxval) * 255 + al / 2) / al;
+            rgb[remap[x]].b = (((palette[x].b * 255 + (maxval >> 1)) / maxval) * 255 + al / 2) / al;
+         }
       }
    }
    return MAPCACHE_SUCCESS;



More information about the mapserver-commits mailing list