[mapguide-commits] r4252 - sandbox/rfc60/MgDev/Common/Renderers
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Tue Sep 22 19:08:46 EDT 2009
Author: uvlite
Date: 2009-09-22 19:08:45 -0400 (Tue, 22 Sep 2009)
New Revision: 4252
Modified:
sandbox/rfc60/MgDev/Common/Renderers/AGGImageIO.cpp
sandbox/rfc60/MgDev/Common/Renderers/AGGImageIO.h
sandbox/rfc60/MgDev/Common/Renderers/AGGRenderer.cpp
sandbox/rfc60/MgDev/Common/Renderers/AGGRenderer.h
Log:
rfc60 the AGGrenderer uses the provided colortable for the color quantization of the PNG8 image
Modified: sandbox/rfc60/MgDev/Common/Renderers/AGGImageIO.cpp
===================================================================
--- sandbox/rfc60/MgDev/Common/Renderers/AGGImageIO.cpp 2009-09-22 23:03:51 UTC (rev 4251)
+++ sandbox/rfc60/MgDev/Common/Renderers/AGGImageIO.cpp 2009-09-22 23:08:45 UTC (rev 4252)
@@ -15,10 +15,10 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
+//#include "ace/OS.h"
#include "stdafx.h"
#include "RendererStyles.h"
#include "AGGImageIO.h"
-#include "AGGRenderer.h"
#include "png.h"
#include "RS_ByteData.h"
#include "agg_context.h"
@@ -26,12 +26,17 @@
#include "gd.h" //for image read support other than PNG (which means JPEG and GIF)
//NOTE: We do not use gd for reading or writing PNG since internally gd drops a bit
//from the alpha channel, which is not desirable for high quality output
-
#include "GDUtils.h"
+#include <assert.h>
+#define myassert(COND,L,F) if (!(COND)){ printf ("(%d) failed assertion in %d %s", GetCurrentThreadId(), L,F); throw new exception();}
+//#include "smartalloc.h"
#pragma warning(disable : 4611)
+enum MS_RETURN_VALUE {MS_SUCCESS, MS_FAILURE, MS_DONE};
+static bool UseColorMap = true;
+
struct png_write_context
{
unsigned char* buf;
@@ -342,9 +347,6 @@
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////
/* Read a PNG file. You may want to return an error code if the read
* fails (depending upon the failure). There are two "prototypes" given
@@ -653,17 +655,214 @@
}
////////////////////////////////////////////////////////////////////////////////////////
+/******************************************************************************
+ * mapgd.c 7803 2008-07-09 05:17:40Z sdlime
+ * Project: MapServer
+ * Purpose: GD rendering and other GD related functions.
+ * Author: Steve Lime and the MapServer team.
+ ******************************************************************************/
+/// copied from mapserver source tree --------> mapgd.c line 3248 - 3463, UV 25.02.2009
+ // copy src to dst using dst's palette
+ // src must be a truecolor image
+ // dst must be a paletted image
+ // method is to fine tune the caching used to lookup color values in the palette:
+ // -0 is the default method, which allocates cache memory when needed
+ // -1 is a memory conservative method, that uses very little caching but is much slower
+ // -2 is a memory hungry caching method (allocates 32MB on the heap) but is the fastest for large images
+ // see bug #2422 for some benchmark timings of these methods
+ //
+int AGGImageIO::ImageCopyForcePaletteGD(gdImagePtr src, gdImagePtr dst, int method)
+{
+ int x, y;
+ int w, h;
+ int c, r, g, b,color;
+ if(!src || !dst) return MS_FAILURE;
+ // input images have different sizes
+ 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);
+ if(method==0) {
+ /*default caching strategy*/
+ unsigned short ***cols=(unsigned short***)calloc(256,sizeof(unsigned short**));
+
+ /*pointer to cache, pointed by red component, indexed by green component*/
+ unsigned short **data=(unsigned short**)calloc(256*256,sizeof(unsigned short*));
+
+ for(r=0;r<256;r++) {
+ /*populate the cache*/
+ cols[r]=&(data[r*256]);
+
+ for (y = 0; (y < h); y++) {
+ for (x = 0; (x < w); x++) {
+ c = gdImageGetPixel(src, x, y);
+ r = gdTrueColorGetRed(c);
+ g = gdTrueColorGetGreen(c);
+ b = gdTrueColorGetBlue(c);
+
+ if(cols[r][g]==NULL) {
+ /*this is the first time we see this r,g couple.
+ *allocate bytes for the blue component*/
+ cols[r][g]=(unsigned short*)calloc(256,sizeof(unsigned short));
+ }
+
+ if(!cols[r][g][b]) {
+ /*this r,g,b triplet was never seen before
+ * compute its index in the palette and cache the result
+ */
+ color = gdImageColorClosest(dst, r, g, b);
+ dst->pixels[y][x] = color;
+ /*the cache data was calloc'ed to avoid initialization
+ * store 'index+1' so we are sure the test for cols[r][g][b]
+ * returns true, i.e that this color was cached*/
+ cols[r][g][b]=color+1;
+ }
+ else {
+ /*the cache data was calloc'ed to avoid initialization
+ * the cache contains 'index+1' so we must subtract
+ * 1 to get the real color index*/
+ dst->pixels[y][x] = cols[r][g][b]-1;
+ } // if
+ } // for x
+ } // for y
+ } // for r
+ for(r=0;r<256;r++)
+ for(g=0;g<256;g++)
+ if(cols[r][g]) /*only free the row if it was used*/
+ free(cols[r][g]);
+ free(data);
+ free(cols);
+ }
+ else if(method==1) {
+ /*memory conservative method, does not allocate mem on the heap*/
+ int R[10], G[10], B[10], C[10];
+ int i, color, nCache = 0, iCache =0, maxCache=10;
+
+ for (y = 0; (y < h); y++) {
+ for (x = 0; (x < w); x++) {
+ c = gdImageGetPixel(src, x, y);
+ r = gdTrueColorGetRed(c);
+ g = gdTrueColorGetGreen(c);
+ b = gdTrueColorGetBlue(c);
+ color = -1;
+
+ /* adding a simple cache to keep colors instead of always calling gdImageColorClosest
+ seems to reduce significantly the time passed in this function
+ spcially with large images (bug 2096)*/
+ for (i=0; i<nCache; i++)
+ {
+ if (R[i] == r)
+ {
+ if (G[i] == g && B[i] == b)
+ {
+ color = C[i];
+ break;
+ }
+ }
+ }
+
+ if (color == -1)
+ {
+ color = gdImageColorClosest(dst, r, g, b);
+ R[iCache] = r;
+ G[iCache] = g;
+ B[iCache] = b;
+ C[iCache] = color;
+ nCache++;
+ if (nCache >= maxCache)
+ nCache = maxCache;
+
+ iCache++;
+ if (iCache == maxCache)
+ iCache = 0;
+ }
+
+ gdImageSetPixel(dst, x, y, color);
+ }
+ }
+ }
+ else if(method==2) {
+ /*memory hungry method, fastest for very large images*/
+
+ /*use a cache for every possible r,g,b triplet
+ * this is usually a full 32MB (when short is 2 bytes) */
+ short *cache=(short*)calloc(16777216,sizeof(short));
+
+ for (y = 0; (y < h); y++) {
+ for (x = 0; (x < w); x++) {
+ int index;
+ c = gdImageGetPixel(src, x, y);
+ index=c&0xFFFFFF; /*use r,g,b for the cache index, i.e. remove alpha*/
+ if(!cache[index]) {
+ r = gdTrueColorGetRed(c);
+ g = gdTrueColorGetGreen(c);
+ b = gdTrueColorGetBlue(c);
+ color = gdImageColorClosest(dst, r, g, b);
+ cache[index]=color+1;
+ dst->pixels[y][x] = color;
+ }
+ else
+ dst->pixels[y][x] = cache[index]-1;
+ }
+ }
+ free(cache);
+ }
+ if(gdImageTrueColor(dst)) return MS_FAILURE; /* result is not 8-bit */
+ return MS_SUCCESS;
+}
////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////
+/// helper function to create an empty image with a palette provided in std::list<MgColor>
+/// inParam: 24bit image, filename of palette file, imagesixeX, imagesizeY
+/// return: 8bit image using given palette if provided ...
+gdImagePtr AGGImageIO::CreateGdImageWithPalette( gdImagePtr img24, RSCOLORS* baseColorPalette,
+ int sx, int sy)
+{
+ gdImagePtr gdPPalette, gdPPaletteFromImg24;
+ /// allow empty default parameter assert (baseColorPalette);
+ int ncolors = baseColorPalette?baseColorPalette->size():0;
+ myassert(sx > 0 && sy > 0,__LINE__, __WFILE__);
+ // create new empty palette image
+ gdPPalette = gdImageCreatePalette(sx, sy);
+ myassert (gdPPalette,__LINE__, __WFILE__);
+
+ // if the palette file contains less than 256, fill the rest with colors generated by gd
+ // those can include the base colors
+ if (ncolors < 256)
+ {
+ gdPPaletteFromImg24 = gdImageCreatePaletteFromTrueColor(img24,1,(256 - ncolors - 1));
+ myassert (gdPPaletteFromImg24,__LINE__, __WFILE__);
+
+ // copy colors from palette into new empty gdpalette
+ for (int c = 0; c < gdPPaletteFromImg24->colorsTotal; c++)
+ {
+ gdImageColorAllocate(gdPPalette,gdPPaletteFromImg24->red[c],
+ gdPPaletteFromImg24->green[c],
+ gdPPaletteFromImg24->blue[c]);
+ }
+ gdImageDestroy(gdPPaletteFromImg24);
+ }
+#ifdef _DEBUG_PNG8
+ printf("\n(%d) ########################### AGGImageIO::CreateGdImageWithPalette colors: %d\n",GetCurrentThreadId(), ncolors);
+#endif
+
+ if (baseColorPalette)
+ {
+ // add colors from the colorpalette (duplicate color entries make the used palette less than 256)
+ RSCOLORS::iterator it;
+ for (it = baseColorPalette->begin();it != baseColorPalette->end(); it++)
+ {
+ gdImageColorAllocate(gdPPalette, (*it).red(), (*it).green(), (*it).blue());
+// delete *it; // the RS_Color is on the heap and needs destruction
+ }
+// delete baseColorPalette;
+ }
+ myassert(gdImageTrueColor(gdPPalette) == 0,__LINE__, __WFILE__); // result is not a 8-bit paletted image
+ return gdPPalette; // this is an empty image with the right color palette
+}
+////////////////////////////////////////////////////////////////////////////////////////
+/// create an image using the other Save method and store it at filename
bool AGGImageIO::Save(const RS_String& filename, const RS_String& format,
unsigned int* src, int src_width, int src_height,
int dst_width, int dst_height, RS_Color& bgColor)
@@ -700,10 +899,13 @@
return true;
}
-
+////////////////////////////////////////////////////////////////////////////////////////
+/// convert imagebuffer src into the desired format using the provided baseColorPalette for 8bit
+/// (the baseColorPalette is a default parameter NULL)
RS_ByteData* AGGImageIO::Save(const RS_String& format,
unsigned int* src, int src_width, int src_height,
- int dst_width, int dst_height, RS_Color& bgColor)
+ int dst_width, int dst_height, RS_Color& bgColor,
+ PRSCOLORS baseColorPalette)
{
bool drop_alpha = bgColor.alpha() == 255;
@@ -749,77 +951,98 @@
return byteData;
}
else if (format == L"JPG" || format == L"GIF" || format == L"PNG8")
- {
- gdImagePtr gdimg = gdImageCreateTrueColor(dst_width, dst_height);
+ { // gdimg24 contains the 24bit image
+ gdImagePtr gdimg24 = gdImageCreateTrueColor(dst_width, dst_height);
- int bgc = ConvertColor(gdimg, bgColor);
+ int bgc = ConvertColor(gdimg24, bgColor);
// initialize the destination image to the bg color (temporarily turn
// off alpha blending so the fill has the supplied alpha)
- gdImageAlphaBlending(gdimg, 0);
- gdImageFilledRectangle(gdimg, 0, 0, gdImageSX(gdimg)-1, gdImageSY(gdimg)-1, bgc);
+ gdImageAlphaBlending(gdimg24, 0);
+ gdImageFilledRectangle(gdimg24, 0, 0, gdImageSX(gdimg24)-1, gdImageSY(gdimg24)-1, bgc);
// set any transparent color
if (bgColor.alpha() != 255)
- gdImageColorTransparent(gdimg, bgc);
+ gdImageColorTransparent(gdimg24, bgc);
+ // copy the src data into the gdImage
unsigned int* ptr = src;
for (int j=0; j<dst_height; j++)
{
for(int i=0; i<dst_width; i++)
{
//TODO: can be optimized
-
unsigned int c = *ptr++;
int a = c >> 24;
- int b = (c >> 16) & 0xff;
- int g = (c >> 8) & 0xff;
- int r = c & 0xff;
-
// skip any fully transparent pixels so a transparent
// background color will show through
if (a != 0)
{
- int gdc = gdImageColorAllocateAlpha(gdimg, r, g, b, a);
- gdImageSetPixel(gdimg, i, j, gdc);
+ int b = (c >> 16) & 0xff; // some simple optimization ;-)
+ int g = (c >> 8) & 0xff;
+ int r = c & 0xff;
+
+ int gdc = gdImageColorAllocateAlpha(gdimg24, r, g, b, a);
+ gdImageSetPixel(gdimg24, i, j, gdc);
}
}
}
- gdImageAlphaBlending(gdimg, 1);
+ gdImageAlphaBlending(gdimg24, 1);
// Make output image non-interlaced --- it's a little faster to compress that way.
- gdImageInterlace(gdimg, 0);
+ gdImageInterlace(gdimg24, 0);
// Make sure the alpha values get saved -- but only if required
// it is faster not to save them and makes a smaller PNG
- if (bgColor.alpha() != 255)
- gdImageSaveAlpha(gdimg, 1);
- else
- gdImageSaveAlpha(gdimg, 0);
+ gdImageSaveAlpha(gdimg24, (bgColor.alpha() != 255)?1:0);
- //convert to 256 color paletted image for PNG8, GIF
- if (format == L"GIF" || format == L"PNG8")
- gdImageTrueColorToPalette(gdimg, 0, 256);
+ gdImagePtr gdImgPalette = NULL;
+ // convert to 256 color paletted image for PNG8, GIF
+ if (format == L"GIF" || format == L"PNG8")
+ //{ //former GIF code
+ // gdImageTrueColorToPalette(gdimg24, 0, 256);
+ // gdImgPalette = gdimg24;
+ //}
+ { /// skip color quantization if no palette given or empty
+ if (baseColorPalette && !baseColorPalette->empty() && UseColorMap) // memory based switch
+ {
+ gdImgPalette = CreateGdImageWithPalette(gdimg24, baseColorPalette,
+ gdImageSX(gdimg24), gdImageSY(gdimg24));
+ myassert(gdImgPalette,__LINE__, __WFILE__);
+ // methods are described above - we use method 1 as default????? TODO what's best???
+ myassert(ImageCopyForcePaletteGD(gdimg24, gdImgPalette, 1) == MS_SUCCESS,__LINE__, __WFILE__);
+ /// forced palette GD image now in gdimgPalette
+ } else
+ {
+ gdImageTrueColorToPalette(gdimg24, 0, 256); // in place conversion
+ gdImgPalette = gdimg24;
+ }
+ }
+
//get an in-memory image stream
int size = 0;
unsigned char* data = NULL;
if (format == L"GIF") // MgImageFormats::Gif
- data = (unsigned char*)gdImageGifPtr(gdimg, &size);
+ data = (unsigned char*)gdImageGifPtr(gdImgPalette, &size);
+ else if (format == L"PNG8") // MgImageFormats::Png8
+ data = (unsigned char*)gdImagePngPtr(gdImgPalette, &size);
else if (format == L"JPG") // MgImageFormats::Jpeg
- data = (unsigned char*)gdImageJpegPtr(gdimg, &size, 75);
- else if (format == L"PNG8") // MgImageFormats::Png8
- data = (unsigned char*)gdImagePngPtr(gdimg, &size);
+ data = (unsigned char*)gdImageJpegPtr(gdimg24, &size, 75);
std::auto_ptr<RS_ByteData> byteData;
byteData.reset((NULL == data)? NULL : new RS_ByteData(data, size));
gdFree(data);
- //if we allocated a temporary image to stretch-blit, destroy it
- gdImageDestroy(gdimg);
+ if (gdimg24 == gdImgPalette)
+ gdimg24 = NULL; // reset pointer so destructor is not called twice -> exception !!!
+ else //if we allocated a temporary image to stretch-blit, destroy it
+ gdImageDestroy(gdimg24);
+ //if we allocated a paletted image, destroy it (very likely that is)
+ gdImageDestroy(gdImgPalette);
return byteData.release();
}
@@ -830,6 +1053,8 @@
return NULL;
}
+//---------------------------------------------------------------------------
+
//TODO: This routine should be rewritten to use agg to blend PNGs more accurately
void AGGImageIO::Combine(const RS_String& src1, const RS_String& src2, const RS_String& dst)
{
Modified: sandbox/rfc60/MgDev/Common/Renderers/AGGImageIO.h
===================================================================
--- sandbox/rfc60/MgDev/Common/Renderers/AGGImageIO.h 2009-09-22 23:03:51 UTC (rev 4251)
+++ sandbox/rfc60/MgDev/Common/Renderers/AGGImageIO.h 2009-09-22 23:08:45 UTC (rev 4252)
@@ -14,9 +14,10 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
+#include "gd.h"
+#include "AGGRenderer.h"
class RS_ByteData;
-
class AGGImageIO
{
public:
@@ -26,7 +27,8 @@
static RS_ByteData* Save(const RS_String& format,
unsigned int* src, int src_width, int src_height,
- int dst_width, int dst_height, RS_Color& bgColor);
+ int dst_width, int dst_height, RS_Color& bgColor,
+ PRSCOLORS baseColorPalette=NULL);
static void Combine(const RS_String& src1, const RS_String& src2, const RS_String& dst);
@@ -37,6 +39,8 @@
static unsigned int* DecodeJPEG(const unsigned char* src, size_t len, int& width, int& height);
private:
+ static gdImagePtr CreateGdImageWithPalette( gdImagePtr img24, PRSCOLORS colors, int x, int y);
+ static int ImageCopyForcePaletteGD(gdImagePtr src, gdImagePtr dst, int method);
static unsigned char* ReadFile(const RS_String& fname, size_t& len);
static void UnmultiplyAlpha(unsigned int* argb, int len);
};
Modified: sandbox/rfc60/MgDev/Common/Renderers/AGGRenderer.cpp
===================================================================
--- sandbox/rfc60/MgDev/Common/Renderers/AGGRenderer.cpp 2009-09-22 23:03:51 UTC (rev 4251)
+++ sandbox/rfc60/MgDev/Common/Renderers/AGGRenderer.cpp 2009-09-22 23:08:45 UTC (rev 4252)
@@ -88,7 +88,7 @@
bool AGGRenderer::s_bClampPoints = false;
bool AGGRenderer::s_bGeneralizeData = false;
-
+///-----------------------------------------------------------------------------------------
// constructor that allows a backbuffer
AGGRenderer::AGGRenderer(int width,
int height,
@@ -130,7 +130,7 @@
m_labeler = new LabelRendererLocal(this, tileExtentOffset);
}
-
+///-----------------------------------------------------------------------------------------
//default constructor
AGGRenderer::AGGRenderer(int width,
int height,
@@ -184,7 +184,7 @@
m_labeler = new LabelRendererLocal(this, tileExtentOffset);
}
-
+///-----------------------------------------------------------------------------------------
AGGRenderer::~AGGRenderer()
{
delete m_context;
@@ -195,9 +195,8 @@
delete[] m_rows;
}
-
-void AGGRenderer::UpdateBackBuffer(int width, int height, unsigned int* backbuffer)
-{
+///-----------------------------------------------------------------------------------------
+void AGGRenderer::UpdateBackBuffer(int width, int height, unsigned int* backbuffer){
if (m_bownbuffer)
delete[] m_rows;
@@ -211,7 +210,7 @@
m_context = new agg_context(m_rows, m_width, m_height);
}
-
+///-----------------------------------------------------------------------------------------
unsigned int* AGGRenderer::GetBackBuffer(int &width, int& height)
{
width = m_width;
@@ -219,31 +218,33 @@
return m_rows;
}
-
+///-----------------------------------------------------------------------------------------
+/// this one writes into a file not returning a ByteStream using default parameters for the W x H
void AGGRenderer::Save(const RS_String& filename, const RS_String& format)
{
Save(filename, format, m_width, m_height);
}
-
-
+///-----------------------------------------------------------------------------------------
+/// this one writes into a file not returning a ByteStream!!
void AGGRenderer::Save(const RS_String& filename, const RS_String& format, int width, int height)
{
AGGImageIO::Save(filename, format, m_rows, m_width, m_height, width, height, m_bgcolor);
}
-
-
-RS_ByteData* AGGRenderer::Save(const RS_String& format, int width, int height)
+///-----------------------------------------------------------------------------------------
+/// return the rendered image passed in via the imagebuffer (m_rows) as a bytestream in the given image format
+/// using the provided colorPalette if given
+RS_ByteData* AGGRenderer::Save(const RS_String& format, int width, int height,
+ PRSCOLORS baseColorPalette)
{
- return AGGImageIO::Save(format, m_rows, m_width, m_height, width, height, m_bgcolor);
+ return AGGImageIO::Save(format, m_rows, m_width, m_height, width, height, m_bgcolor, baseColorPalette);
}
-
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::Combine(const RS_String& fileIn1, const RS_String& fileIn2, const RS_String& fileOut)
{
AGGImageIO::Combine(fileIn1, fileIn2, fileOut);
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::StartMap(RS_MapUIInfo* mapInfo,
RS_Bounds& extents,
double mapScale,
@@ -300,7 +301,7 @@
InitFontEngine(this);
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::EndMap()
{
// turn off selection mode so the labels draw normal
@@ -313,7 +314,7 @@
m_mapInfo = NULL;
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::StartLayer(RS_LayerUIInfo* legendInfo,
RS_FeatureClassInfo* classInfo)
{
@@ -322,7 +323,7 @@
m_fcInfo = classInfo;
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::EndLayer()
{
// clear the layer/feature info
@@ -330,7 +331,7 @@
m_fcInfo = NULL;
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::StartFeature(RS_FeatureReader* /*feature*/,
bool /*initialPass*/,
const RS_String* /*tooltip*/,
@@ -342,7 +343,7 @@
{
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::ProcessPolygon(LineBuffer* lb, RS_FillStyle& fill)
{
_ASSERT(NULL != lb);
@@ -486,7 +487,7 @@
}
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::ProcessPolyline(LineBuffer* lb, RS_LineStroke& lsym)
{
_ASSERT(NULL != lb);
@@ -595,7 +596,7 @@
printf(" minx = %6.4f miny = %6.4f maxx = %6.4f maxy = %6.4f\n", ext.minx, ext.miny, ext.maxx, ext.maxy); \
printf(" width = %6.4f height = %6.4f\n", ext.width(), ext.height());
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::ProcessRaster(unsigned char* data,
int length,
RS_ImageFormat format,
@@ -625,7 +626,7 @@
}
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::ProcessMarker(LineBuffer* srclb, RS_MarkerDef& mdef, bool allowOverpost, RS_Bounds* bounds)
{
RS_MarkerDef use_mdef = mdef;
@@ -650,7 +651,7 @@
}
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::ProcessOneMarker(double x, double y, RS_MarkerDef& mdef, bool allowOverpost, RS_Bounds* bounds)
{
RS_InputStream* symbol = NULL;
@@ -1030,7 +1031,7 @@
}
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::ProcessLabelGroup(RS_LabelInfo* labels,
int nlabels,
const RS_String& text,
@@ -1047,88 +1048,88 @@
m_labeler->ProcessLabelGroup(labels, nlabels, text, type, exclude, path, scaleLimit);
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::SetSymbolManager(RS_SymbolManager* manager)
{
m_symbolManager = manager;
}
-
+///-----------------------------------------------------------------------------------------
RS_MapUIInfo* AGGRenderer::GetMapInfo()
{
return m_mapInfo;
}
-
+///-----------------------------------------------------------------------------------------
RS_LayerUIInfo* AGGRenderer::GetLayerInfo()
{
return m_layerInfo;
}
-
+///-----------------------------------------------------------------------------------------
RS_FeatureClassInfo* AGGRenderer::GetFeatureClassInfo()
{
return m_fcInfo;
}
-
+///-----------------------------------------------------------------------------------------
double AGGRenderer::GetMapScale()
{
return m_mapScale;
}
-
+///-----------------------------------------------------------------------------------------
double AGGRenderer::GetDrawingScale()
{
return m_drawingScale;
}
-
+///-----------------------------------------------------------------------------------------
RS_Bounds& AGGRenderer::GetBounds()
{
return m_extents;
}
-
+///-----------------------------------------------------------------------------------------
double AGGRenderer::GetDpi()
{
return m_dpi;
}
-
+///-----------------------------------------------------------------------------------------
double AGGRenderer::GetMetersPerUnit()
{
return m_metersPerUnit;
}
-
+///-----------------------------------------------------------------------------------------
bool AGGRenderer::RequiresClipping()
{
return m_bRequiresClipping;
}
-
+///-----------------------------------------------------------------------------------------
bool AGGRenderer::RequiresLabelClipping()
{
// always the same value as RequiresClipping
return m_bRequiresClipping;
}
-
+///-----------------------------------------------------------------------------------------
bool AGGRenderer::SupportsTooltips()
{
// set to false to disable processing of tooltips
return false;
}
-
+///-----------------------------------------------------------------------------------------
bool AGGRenderer::SupportsHyperlinks()
{
// set to false to disable processing of hyperlinks
return false;
}
-
+///-----------------------------------------------------------------------------------------
bool AGGRenderer::UseLocalOverposting()
{
return m_bLocalOverposting;
@@ -1324,7 +1325,7 @@
}
-//-----------------------------------------------------------------------------
+///-----------------------------------------------------------------------------
// scale an input number in meters to a mapping
// space number given a device or mapping space unit.
//-----------------------------------------------------------------------------
@@ -1340,13 +1341,13 @@
return number * scale_factor;
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::SetRenderSelectionMode(bool mode)
{
SetRenderSelectionMode(mode, 0x0000FF00);
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::SetRenderSelectionMode(bool mode, int rgba)
{
SE_Renderer::SetRenderSelectionMode(mode, rgba);
@@ -1367,7 +1368,7 @@
// Text drawing
//////////////////////////////////////////////////////////////////////////////
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::DrawString(const RS_String& s,
double x,
double y,
@@ -1383,7 +1384,7 @@
DrawString(c(), sConv, x, y, width, height, font, color, angleRad);
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::DrawString(agg_context* cxt,
const RS_String& s,
double x,
@@ -1742,7 +1743,7 @@
}
}
-
+///-----------------------------------------------------------------------------------------
// Called when applying a line style on a feature geometry. Line styles can
// only be applied to linestring and polygon feature geometry types.
void AGGRenderer::ProcessLine(SE_ApplyContext* ctx, SE_RenderLineStyle* style)
@@ -1825,7 +1826,7 @@
LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::_TransferPoints(agg_context* c, LineBuffer* srcLB, const SE_Matrix* xform, unsigned int* pathids, bool isPolygon)
{
if (s_bClampPoints)
@@ -1930,7 +1931,7 @@
}
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::_TransferPointsClamped(agg_context* c, LineBuffer* srcLB, const SE_Matrix* xform, unsigned int* pathids, bool isPolygon)
{
c->ps.remove_all();
@@ -2080,7 +2081,7 @@
DrawScreenPolyline(c(), srclb, xform, lineStroke);
}
-
+///-----------------------------------------------------------------------------------------
// copied from WritePolylines, except it doesn't do to screen transform - we should refactor
void AGGRenderer::DrawScreenPolyline(agg_context* c, LineBuffer* srclb, const SE_Matrix* xform, const SE_LineStroke& lineStroke)
{
@@ -2154,13 +2155,13 @@
c->ras.filling_rule(agg::fill_even_odd);
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::DrawScreenPolygon(LineBuffer* polygon, const SE_Matrix* xform, unsigned int color)
{
DrawScreenPolygon(c(), polygon, xform, color);
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::DrawScreenPolygon(agg_context* c, LineBuffer* polygon, const SE_Matrix* xform, unsigned int color)
{
if ((color & 0xFF000000) == 0)
@@ -2188,59 +2189,59 @@
}
}
-
+///-----------------------------------------------------------------------------------------
bool AGGRenderer::YPointsUp()
{
return true;
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::GetWorldToScreenTransform(SE_Matrix& xform)
{
xform = m_xform;
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::SetWorldToScreenTransform(SE_Matrix& xform)
{
m_xform = xform;
m_xform.inverse(m_ixform);
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::WorldToScreenPoint(double& inx, double& iny, double& ox, double& oy)
{
m_xform.transform(inx, iny, ox, oy);
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::ScreenToWorldPoint(double& inx, double& iny, double& ox, double& oy)
{
m_ixform.transform(inx, iny, ox, oy);
}
-
+///-----------------------------------------------------------------------------------------
// returns number of pixels per millimeter device
double AGGRenderer::GetScreenUnitsPerMillimeterDevice()
{
return m_dpi / MILLIMETERS_PER_INCH;
}
-
+///-----------------------------------------------------------------------------------------
// returns number of pixels per millimeter world
double AGGRenderer::GetScreenUnitsPerMillimeterWorld()
{
return m_dpi / MILLIMETERS_PER_INCH / m_mapScale;
}
-
+///-----------------------------------------------------------------------------------------
// screen units are pixels
double AGGRenderer::GetScreenUnitsPerPixel()
{
return 1.0;
}
-
+///-----------------------------------------------------------------------------------------
RS_FontEngine* AGGRenderer::GetRSFontEngine()
{
return this;
@@ -2252,7 +2253,7 @@
m_labeler->AddExclusionRegion(fpts, npts);
}
-
+///-----------------------------------------------------------------------------------------
// labeling - this is the entry API for adding SE labels
// to the label mananger
void AGGRenderer::ProcessSELabelGroup(SE_LabelInfo* labels,
@@ -2269,7 +2270,7 @@
m_labeler->ProcessLabelGroup(labels, nlabels, type, exclude, path);
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::DrawScreenRaster(unsigned char* data, int length,
RS_ImageFormat format, int native_width, int native_height,
double x, double y, double w, double h, double angledeg)
@@ -2277,6 +2278,7 @@
DrawScreenRaster(c(), data, length, format, native_width, native_height, x, y, w, h, angledeg);
}
+///-----------------------------------------------------------------------------------------
void AGGRenderer::DrawScreenRaster(agg_context* cxt, unsigned char* data, int length,
RS_ImageFormat format, int native_width, int native_height,
@@ -2362,7 +2364,7 @@
RenderWithTransform(src, cxt, img_mtx, format);
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::DrawScreenRasterTransform(agg_context* cxt, unsigned char* data, int length,
RS_ImageFormat format, int native_width, int native_height,
double x, double y, double w, double h,
@@ -2420,7 +2422,7 @@
#endif
}
-
+///-----------------------------------------------------------------------------------------
// Renders the mesh rectangle defined by the point mappings at the four supplied mesh indices
void AGGRenderer::RenderTransformMeshRectangle(mg_rendering_buffer& src, agg_context* cxt,
RS_ImageFormat format, TransformMesh* transformMesh,
@@ -2443,7 +2445,7 @@
mesh_pt_ur.pt_dest, mesh_pt_ul.pt_dest, mesh_pt_ll.pt_dest);
}
-
+///-----------------------------------------------------------------------------------------
// Renders the triangle in the source image defined by the three source points into
// the triangle in the supplied context defined by the three destination points.
void AGGRenderer::RenderTransformedTriangle(mg_rendering_buffer& src, agg_context* cxt, RS_ImageFormat format,
@@ -2471,7 +2473,7 @@
RenderWithTransform(src, cxt, img_mtx, format, false);
}
-
+///-----------------------------------------------------------------------------------------
// Renders the source image to the destination context, using the specified
// affine transformation matrix.
void AGGRenderer::RenderWithTransform(mg_rendering_buffer& src, agg_context* cxt,
@@ -2580,7 +2582,7 @@
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
-
+///-----------------------------------------------------------------------------------------
// Inserts the contents of a given DWF input stream into the current
// output W2D. The given coord sys transformation is applied and geometry
// will be clipped to the RS_Bounds context of the DWFRenderer.
@@ -2705,7 +2707,7 @@
}
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::AddW2DContent(RS_InputStream* in, CSysTransformer* xformer, const RS_String& w2dfilter)
{
WT_Result result;
@@ -2746,7 +2748,7 @@
m_imw2d = NULL;
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::SetActions(WT_File& file)
{
file.set_stream_open_action (agr_open);
@@ -2827,7 +2829,7 @@
file.set_gouraud_polyline_action(agr_process_gouraudPolyline);
}
-
+///-----------------------------------------------------------------------------------------
// Given an array of points in W2D logical coordinates, this function:
// 1. Transforms W2D logical coords into their model space using the
// W2D file's units structure
@@ -2950,7 +2952,7 @@
return spLB.release();
}
-
+///-----------------------------------------------------------------------------------------
// This function scales a W2D space related value from source W2D space
// to destination. Since the source W2D file can fit into a small piece
// of the destination DWF or be much larger, we need to take that scaling
@@ -2981,7 +2983,7 @@
return dDstSpace;
}
-
+///-----------------------------------------------------------------------------------------
void AGGRenderer::UpdateSymbolTrans(WT_File& /*file*/, WT_Viewport& viewport)
{
_ASSERT(m_xformer);
Modified: sandbox/rfc60/MgDev/Common/Renderers/AGGRenderer.h
===================================================================
--- sandbox/rfc60/MgDev/Common/Renderers/AGGRenderer.h 2009-09-22 23:03:51 UTC (rev 4251)
+++ sandbox/rfc60/MgDev/Common/Renderers/AGGRenderer.h 2009-09-22 23:08:45 UTC (rev 4252)
@@ -48,6 +48,14 @@
};
typedef agg::row_ptr_cache<unsigned char> mg_rendering_buffer;
+
+/// for the list of colors used to do color quantization
+typedef std::list<RS_Color*> RSCOLORLIST;
+typedef RSCOLORLIST* PRSCOLORLIST;
+/// the efficient way
+typedef std::vector<RS_Color> RSCOLORS;
+typedef RSCOLORS* PRSCOLORS;
+
class AGGRenderer : public SE_Renderer, public RS_FontEngine
{
friend class LabelRenderer;
@@ -149,7 +157,7 @@
//
RENDERERS_API void Save(const RS_String& filename, const RS_String& format);
RENDERERS_API void Save(const RS_String& filename, const RS_String& format, int width, int height);
- RENDERERS_API RS_ByteData* Save(const RS_String& format, int width, int height);
+ RENDERERS_API RS_ByteData* Save(const RS_String& format, int width, int height, PRSCOLORS baseColorPalette=NULL);
RENDERERS_API void Combine(const RS_String& fileIn1, const RS_String& fileIn2, const RS_String& fileOut);
RENDERERS_API void SetWorldToScreenTransform(SE_Matrix& xform);
More information about the mapguide-commits
mailing list