Opened 16 years ago
Closed 16 years ago
#2422 closed enhancement (fixed)
force_palette could be optimized
Reported by: | tbonfort | Owned by: | tbonfort |
---|---|---|---|
Priority: | normal | Milestone: | 5.2 release |
Component: | MapServer C Library | Version: | unspecified |
Severity: | normal | Keywords: | |
Cc: | assefa, zjames, jmckenna |
Description
the caching strategy when using a forced palette isn't optimal and results in substantial slowdowns, especially for large images
Attachments (2)
Change History (8)
comment:1 by , 16 years ago
by , 16 years ago
Attachment: | plot-small.png added |
---|
same plot for small image sizes. allocation cost doesn't seem too important
comment:2 by , 16 years ago
from my benchmarking, it seems the cost of allocating the cache is marginal, therefore this method could be used whatever the image size being renderered.
However, there might be some situations where this large memory allocation may not be wanted. We could add a new
FORMATOPTION "PALETTE_METHOD=conserve_mem"
that would revert to using the current method.
comment:3 by , 16 years ago
Someone got their math horribly wrong here ;)
a full 32MB are allocated, not 3
by , 16 years ago
Attachment: | plot-large.png added |
---|
paletting time in ms. x is image size. red is current. green is high mem. blue is with a hash
comment:4 by , 16 years ago
I added an intermediate caching strategy. On my test map, 6000*6000, approx 4MB was allocated.
static int msImageCopyForcePaletteGD6(gdImagePtr src, gdImagePtr dst) { int x, y; int w, h; int c, r, g, b,color; if(!src || !dst) return MS_FAILURE; if(gdImageSX(src) != gdImageSX(dst) || gdImageSY(src) != gdImageSY(dst)) return MS_FAILURE; if(!gdImageTrueColor(src) || gdImageTrueColor(dst)) return MS_FAILURE; /* 24-bit to 8-bit */ w = gdImageSX(src); h = gdImageSY(src); unsigned short ***cols=(unsigned short***)calloc(256,sizeof(unsigned short**)); unsigned short **data=(unsigned short**)calloc(256*256,sizeof(unsigned short*)); for(r=0;r<256;r++) { cols[r]=&(data[r*256]); } for (y = 0; (y < h); y++) { for (x = 0; (x < w); x++) { int index; c = gdImageGetPixel(src, x, y); index=c&0xFFFFFF; r = gdTrueColorGetRed(c); g = gdTrueColorGetGreen(c); b = gdTrueColorGetBlue(c); if(cols[r][g]==NULL) { cols[r][g]=(unsigned short*)calloc(256,sizeof(unsigned short)); } if(!cols[r][g][b]) { color = gdImageColorClosest(dst, r, g, b); dst->pixels[y][x] = color; cols[r][g][b]=color+1; } else { dst->pixels[y][x] = cols[r][g][b]-1; } } } for(r=0;r<256;r++) for(g=0;g<256;g++) if(cols[r][g]) free(cols[r][g]); free(data); free(cols); return MS_SUCCESS; }
plot-large.png shows the updated banchmarking.
comment:5 by , 16 years ago
Tomas,
I had similar results testing with 6000/6000 with the latest function. I think it is the best compromise. I like the fact that the old way is still there with an option parameter so that if for some reason someone is currently using it and find an issue he can still have the old behavior. Personally I think you should go with the commit. Great work. Thanks
comment:6 by , 16 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
I propose a more agressive caching of paletted images
which is substantially faster, but allocates 3MB of memory on the heap.
attaching some benchmark graphs