[mapserver-commits] r11599 - trunk/mapserver
svn at osgeo.org
svn at osgeo.org
Tue Apr 19 01:14:17 EDT 2011
Author: tbonfort
Date: 2011-04-18 22:14:17 -0700 (Mon, 18 Apr 2011)
New Revision: 11599
Modified:
trunk/mapserver/HISTORY.TXT
trunk/mapserver/mapimageio.c
trunk/mapserver/mapquantization.c
trunk/mapserver/mapserver.h
trunk/mapserver/mapsymbol.h
Log:
fix incorrect quantization for images with very large number of
colors (#3848)
Modified: trunk/mapserver/HISTORY.TXT
===================================================================
--- trunk/mapserver/HISTORY.TXT 2011-04-19 05:09:19 UTC (rev 11598)
+++ trunk/mapserver/HISTORY.TXT 2011-04-19 05:14:17 UTC (rev 11599)
@@ -15,6 +15,9 @@
Current Version (SVN trunk):
----------------------------
+- fix incorrect quantization for images with very large number of
+ colors (#3848)
+
- fix poor performance of polygon hatching (#3846)
- upgrade clipper library to 4.2 (related to #3846)
Modified: trunk/mapserver/mapimageio.c
===================================================================
--- trunk/mapserver/mapimageio.c 2011-04-19 05:09:19 UTC (rev 11598)
+++ trunk/mapserver/mapimageio.c 2011-04-19 05:14:17 UTC (rev 11599)
@@ -194,18 +194,20 @@
int remapPaletteForPNG(rasterBufferObj *rb, rgbPixel *rgb, unsigned char *a, int *num_a) {
int bot_idx, top_idx, x;
int remap[256];
+ unsigned int maxval = rb->data.palette.scaling_maxval;
+
+ assert(rb->type == MS_BUFFER_BYTE_PALETTE);
+
/*
- ** Step 3.5 [GRR]: remap the palette colors so that all entries with
+ ** remap the palette colors so that all entries with
** the maximal alpha value (i.e., fully opaque) are at the end and can
** therefore be omitted from the tRNS chunk. Note that the ordering of
- ** opaque entries is reversed from how Step 3 arranged them--not that
- ** this should matter to anyone.
+ ** opaque entries is reversed from how they were previously arranged
+ ** --not that this should matter to anyone.
*/
- assert(rb->type == MS_BUFFER_BYTE_PALETTE);
-
for (top_idx = rb->data.palette.num_entries-1, bot_idx = x = 0; x < rb->data.palette.num_entries; ++x) {
- if (rb->data.palette.palette[x].a == 255)
+ if (rb->data.palette.palette[x].a == maxval)
remap[x] = top_idx--;
else
remap[x] = bot_idx++;
@@ -219,20 +221,29 @@
*num_a = bot_idx;
for(x=0;x<rb->width*rb->height;x++)
- rb->data.palette.pixels[x] = remap[rb->data.palette.pixels[x]];
+ rb->data.palette.pixels[x] = remap[rb->data.palette.pixels[x]];
+
for (x = 0; x < rb->data.palette.num_entries; ++x) {
- a[remap[x]] = rb->data.palette.palette[x].a;
- if(a[remap[x]] == 255) {
+ if(maxval == 255) {
+ a[remap[x]] = rb->data.palette.palette[x].a;
rgb[remap[x]].r = rb->data.palette.palette[x].r;
rgb[remap[x]].g = rb->data.palette.palette[x].g;
rgb[remap[x]].b = rb->data.palette.palette[x].b;
} else {
- double da = a[remap[x]]/255.0;
- rgb[remap[x]].r = rb->data.palette.palette[x].r / da;
- rgb[remap[x]].g = rb->data.palette.palette[x].g / da;
- rgb[remap[x]].b = rb->data.palette.palette[x].b / da;
+ /* rescale palette */
+ rgb[remap[x]].r = (rb->data.palette.palette[x].r * 255 + (maxval >> 1)) / maxval;
+ rgb[remap[x]].g = (rb->data.palette.palette[x].g * 255 + (maxval >> 1)) / maxval;
+ rgb[remap[x]].b = (rb->data.palette.palette[x].b * 255 + (maxval >> 1)) / maxval;
+ a[remap[x]] = (rb->data.palette.palette[x].a * 255 + (maxval >> 1)) / maxval;
}
+ if(a[remap[x]] != 255) {
+ /* un-premultiply pixels */
+ double da = 255.0/a[remap[x]];
+ rgb[remap[x]].r *= da;
+ rgb[remap[x]].g *= da;
+ rgb[remap[x]].b *= da;
+ }
}
return MS_SUCCESS;
@@ -287,7 +298,7 @@
PNG_FILTER_TYPE_DEFAULT);
remapPaletteForPNG(rb,rgb,a,&num_a);
-
+
png_set_PLTE(png_ptr, info_ptr, (png_colorp)(rgb),rb->data.palette.num_entries);
if(num_a)
png_set_tRNS(png_ptr, info_ptr, a,num_a, NULL);
@@ -387,10 +398,13 @@
qrb.width = rb->width;
qrb.height = rb->height;
qrb.data.palette.pixels = (unsigned char*)malloc(qrb.width*qrb.height*sizeof(unsigned char));
+ qrb.data.palette.scaling_maxval = 255;
if(force_pc256) {
qrb.data.palette.palette = palette;
qrb.data.palette.num_entries = atoi(msGetOutputFormatOption( format, "QUANTIZE_COLORS", "256"));
- ret = msQuantizeRasterBuffer(rb,&(qrb.data.palette.num_entries),qrb.data.palette.palette, NULL, 0);
+ ret = msQuantizeRasterBuffer(rb,&(qrb.data.palette.num_entries),qrb.data.palette.palette,
+ NULL, 0,
+ &qrb.data.palette.scaling_maxval);
} else {
int colorsWanted = atoi(msGetOutputFormatOption( format, "QUANTIZE_COLORS", "0"));
const char *palettePath = msGetOutputFormatOption( format, "PALETTE", "palette.txt");
@@ -414,14 +428,15 @@
qrb.data.palette.palette = palette;
qrb.data.palette.num_entries = MS_MAX(colorsWanted,numPaletteGivenEntries);
ret = msQuantizeRasterBuffer(rb,&(qrb.data.palette.num_entries),qrb.data.palette.palette,
- paletteGiven,numPaletteGivenEntries);
+ paletteGiven,numPaletteGivenEntries,
+ &qrb.data.palette.scaling_maxval);
}
}
if(ret != MS_FAILURE) {
ret = msClassifyRasterBuffer(rb,&qrb);
ret = savePalettePNG(&qrb,info,compression);
}
- //msFreeRasterBuffer(&qrb);
+ msFree(qrb.data.palette.pixels);
return ret;
}
else if(rb->type == MS_BUFFER_BYTE_RGBA) {
Modified: trunk/mapserver/mapquantization.c
===================================================================
--- trunk/mapserver/mapquantization.c 2011-04-19 05:09:19 UTC (rev 11598)
+++ trunk/mapserver/mapquantization.c 2011-04-19 05:14:17 UTC (rev 11599)
@@ -121,16 +121,21 @@
* - forced_palette: entries that should appear in the computed palette
* - num_forced_palette_entries: number of entries contained in "force_palette". if 0,
* "force_palette" can be NULL
+ * - palette_scaling_maxval: the quantization process may have to reduce the image depth
+ * by iteratively dividing the pixels by 2. In case palette_scaling_maxval is set to
+ * something different than 255, the returned palette colors have to be scaled back up to
+ * 255, and rb's pixels will have been scaled down to maxsize (see bug #3848)
*/
int msQuantizeRasterBuffer(rasterBufferObj *rb,
unsigned int *reqcolors, rgbaPixel *palette,
- rgbaPixel *forced_palette, int num_forced_palette_entries) {
+ rgbaPixel *forced_palette, int num_forced_palette_entries,
+ unsigned int *palette_scaling_maxval) {
rgbaPixel **apixels=NULL; /* pointer to the start rows of truecolor pixels */
register rgbaPixel *pP;
register int col;
- unsigned char maxval, newmaxval;
+ unsigned char newmaxval;
acolorhist_vector achv, acolormap=NULL;
int row;
@@ -142,7 +147,7 @@
assert(rb->type == MS_BUFFER_BYTE_RGBA);
- maxval = 255;
+ *palette_scaling_maxval = 255;
apixels=(rgbaPixel**)msSmallMalloc(rb->height*sizeof(rgbaPixel**));
@@ -162,41 +167,25 @@
apixels, rb->width, rb->height, MAXCOLORS, &colors );
if ( achv != (acolorhist_vector) 0 )
break;
- newmaxval = maxval / 2;
+ newmaxval = *palette_scaling_maxval / 2;
for ( row = 0; row < rb->height; ++row )
for ( col = 0, pP = apixels[row]; col < rb->width; ++col, ++pP )
- PAM_DEPTH( *pP, *pP, maxval, newmaxval );
- maxval = newmaxval;
+ PAM_DEPTH( *pP, *pP, *palette_scaling_maxval, newmaxval );
+ *palette_scaling_maxval = newmaxval;
}
newcolors = MS_MIN(colors, *reqcolors);
- acolormap = mediancut(achv, colors, rb->width*rb->height, maxval, newcolors);
+ acolormap = mediancut(achv, colors, rb->width*rb->height, *palette_scaling_maxval, newcolors);
pam_freeacolorhist(achv);
*reqcolors = newcolors;
- /*
- ** rescale the palette colors to a maxval of 255
- */
-
- if (maxval < 255) {
- for (x = 0; x < newcolors; ++x) {
- /* the rescaling part of this is really just PAM_DEPTH() broken out
- * for the PNG palette; the trans-remapping just puts the values
- * in different slots in the PNG palette */
- palette[x].r = (acolormap[x].acolor.r * 255 + (maxval >> 1)) / maxval;
- palette[x].g = (acolormap[x].acolor.g * 255 + (maxval >> 1)) / maxval;
- palette[x].b = (acolormap[x].acolor.b * 255 + (maxval >> 1)) / maxval;
- palette[x].a = (acolormap[x].acolor.a * 255 + (maxval >> 1)) / maxval;
- }
- } else {
- for (x = 0; x < newcolors; ++x) {
- palette[x].r = acolormap[x].acolor.r;
- palette[x].g = acolormap[x].acolor.g;
- palette[x].b = acolormap[x].acolor.b;
- palette[x].a = acolormap[x].acolor.a;
- }
+ for (x = 0; x < newcolors; ++x) {
+ palette[x].r = acolormap[x].acolor.r;
+ palette[x].g = acolormap[x].acolor.g;
+ palette[x].b = acolormap[x].acolor.b;
+ palette[x].a = acolormap[x].acolor.a;
}
free(acolormap);
Modified: trunk/mapserver/mapserver.h
===================================================================
--- trunk/mapserver/mapserver.h 2011-04-19 05:09:19 UTC (rev 11598)
+++ trunk/mapserver/mapserver.h 2011-04-19 05:14:17 UTC (rev 11599)
@@ -2620,7 +2620,9 @@
/* in mapimageio.c */
-int msQuantizeRasterBuffer(rasterBufferObj *rb, unsigned int *reqcolors, rgbaPixel *palette, rgbaPixel *forced_palette, int num_forced_palette_entries);
+int msQuantizeRasterBuffer(rasterBufferObj *rb, unsigned int *reqcolors, rgbaPixel *palette,
+ rgbaPixel *forced_palette, int num_forced_palette_entries,
+ unsigned int *palette_scaling_maxval);
int msClassifyRasterBuffer(rasterBufferObj *rb, rasterBufferObj *qrb);
int msSaveRasterBuffer(mapObj *map, rasterBufferObj *data, FILE *stream, outputFormatObj *format);
int msSaveRasterBufferToBuffer(rasterBufferObj *data, bufferObj *buffer, outputFormatObj *format);
Modified: trunk/mapserver/mapsymbol.h
===================================================================
--- trunk/mapserver/mapsymbol.h 2011-04-19 05:09:19 UTC (rev 11598)
+++ trunk/mapserver/mapsymbol.h 2011-04-19 05:14:17 UTC (rev 11599)
@@ -72,6 +72,7 @@
unsigned char *pixels; /*stores the actual pixel indexes*/
rgbaPixel *palette; /*rgba palette entries*/
unsigned int num_entries; /*number of palette entries*/
+ unsigned int scaling_maxval;
} paletteArrayObj;
typedef struct {
More information about the mapserver-commits
mailing list