[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