Changes between Version 13 and Version 14 of MapGuideRfc60
- Timestamp:
- 01/08/10 13:09:08 (15 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
MapGuideRfc60
v13 v14 7 7 == Status == 8 8 9 ||RFC Template Version|| (1.0)||10 ||Submission Date|| (27.02.2009)||11 ||Last Modified|| (UV Wildner)[[Timestamp]]||12 ||Author|| (UV Wildner)||13 ||RFC Status|| (adopted)||14 ||Implementation Status|| (in testing)||15 ||Proposed Milestone|| (2.1)||9 ||RFC Template Version||1.0|| 10 ||Submission Date||27.02.2009|| 11 ||Last Modified||UV Wildner [[Timestamp]]|| 12 ||Author||UV Wildner|| 13 ||RFC Status||adopted|| 14 ||Implementation Status||completed|| 15 ||Proposed Milestone||2.1|| 16 16 ||Assigned PSC guide(s)||Bruce Dechant|| 17 17 ||'''Voting History'''||May 7, 2009|| … … 24 24 == Overview == 25 25 26 The color quantization for PNG8 tiles does not preserve the base colors of the map. This leads to visible color differences in adjacent map tiles. 27 By providing the base colors of the map as a palette to the image renderer the visual appearance of the map can be significantly improved. 26 The color quantization for PNG8 tiles does not preserve the base colors of the map. This leads to visible color differences in adjacent map tiles. By providing the base colors of the map as a palette to the image renderer the visual appearance of the map can be significantly improved. 28 27 29 28 == Motivation == 30 29 31 The color palette for PNG8 tiles is computed in the AGG renderer from truecolor tiles (AGGImageIO.cpp) on a one by one basis. 32 The used quantization algorithm in the gd library (gd_topal.c) does not preserve the base colors of the map as they are not know at this place. 33 Therefore adjacent map tiles might use different colors for map areas crossing tile boundaries. This is very obvious and disturbing to the human eye. 30 The color palette for PNG8 tiles is computed in the AGG renderer from truecolor tiles (AGGImageIO.cpp) on a one by one basis. The used quantization algorithm in the gd library (gd_topal.c) does not preserve the base colors of the map as they are not know at this place. Therefore adjacent map tiles might use different colors for map areas crossing tile boundaries. This is very obvious and disturbing to the human eye. 34 31 35 32 Ticket #813 PNG8 Compression isn't preserving fill colors … … 37 34 == Proposed Solution == 38 35 39 By providing the base colors of the map in a palette file and using an improved color quantification algorithm which adds a forced palette to the image the resulting map can be significantly improved. 40 This can be done by using the median-cut algorithm as used in the mapserver code base in the function `ImageCopyForcePaletteGD`. 36 By providing the base colors of the map in a palette file and using an improved color quantification algorithm which adds a forced palette to the image the resulting map can be significantly improved. This can be done by using the median-cut algorithm as used in the mapserver code base in the function `ImageCopyForcePaletteGD`. 41 37 42 38 {{{ … … 57 53 }}} 58 54 59 == server code integration ==55 == Server Code Integration == 60 56 61 The interesting task is how to feed the base colors of the map to the Image Renderer making the image. 62 The base colors of a map can be extracted most efficiently during map generation in MapingUtil::StylizeLayers(). 63 To do this the VectorScaleRange gets an additional method called VectorScaleRange::GetUsedColorList(). 57 The interesting task is how to feed the base colors of the map to the Image Renderer making the image. The base colors of a map can be extracted most efficiently during map generation in MappingUtil::!StylizeLayers(). 58 To do this the !VectorScaleRange gets an additional method called VectorScaleRange::!GetUsedColorList(). 64 59 This is a computed property implemented as a singleton which creates the list upon access. Subsequent requests from other threads read the same list. The singleton is not protected with a mutex as a second thread would recreate the same datastructure....in the worst case I can imagine a few kBytes of memory leak with a very low probability.... less costly than a mutex I suppose. 65 60 66 At the end of the stylization GetUsedColorList is called and the resulting color list is stored in the runtime map object MgMap. 67 (Map->SetColorPalette(pStringColorList)) This method sorts and uniquifies the color list upon storage. 61 At the end of the stylization !GetUsedColorList is called and the resulting color list is stored in the runtime map object !MgMap (Map->!SetColorPalette(pStringColorList)). This method sorts and uniquifies the color list upon storage. 68 62 69 The colors from the MdfMModel are MdfStrings and the algorithm simply collects all different strings. So in order to support expressions for those colors the list simply needs to be interpreted when read from theMgMap object.63 The colors from the !MdfModel are !MdfStrings and the algorithm simply collects all different strings. So in order to support expressions for those colors the list simply needs to be interpreted when read from the !MgMap object. 70 64 71 The RenderingService reads the color list from the map object, and converts it into a list of RsColor objects. 72 This color palette is then passed down via the AGGRenderer to the AGGImageIO objects Save method. Here the png color quantification 73 algorithm is included to force the provided palette into the rendered image - this way making sure that the correct base colors survive the compression and/or color quantization. 74 see also the sequence [http://trac.osgeo.org/mapguide/attachment/wiki/MapGuideRfc60/GetTile2.png] 65 The !RenderingService reads the color list from the map object, and converts it into a list of !RS_Color objects. 66 This color palette is then passed down via the AGGRenderer to the AGGImageIO object's Save method. Here the png color quantification algorithm is included to force the provided palette into the rendered image - this way making sure that the correct base colors survive the compression and/or color quantization. See also the sequence [http://trac.osgeo.org/mapguide/attachment/wiki/MapGuideRfc60/GetTile2.png] 75 67 76 68 == Implications == 77 69 78 No Implications are intended as this behaviour is desired by default. We just get better looking maps. The cost of extracting the colors from the in-memory representation of the XML data describing the map are presumed to be neglig able. However, the color quantification is a bit more costly.70 No Implications are intended as this behaviour is desired by default. We just get better looking maps. The cost of extracting the colors from the in-memory representation of the XML data describing the map are presumed to be negligible. However, the color quantification is a bit more costly. 79 71 80 72 == Test Plan == … … 84 76 setting up a unit test seems excessively complex. Any ideas are most welcome. 85 77 86 So far some debugging code has been included to verify the collection of the colors within the rendering service. 87 The success is then evaluated on visually inspecting the map and testing if the base colors made it through using IrfanView. 78 So far some debugging code has been included to verify the collection of the colors within the rendering service. The success is then evaluated on visually inspecting the map and testing if the base colors made it through using !IrfanView. 88 79 89 80 Any suggestions are most welcome. … … 93 84 Some funding is to be provided by Explore Australia. 94 85 95 == closed Issues ==86 == Closed Issues == 96 87 97 1. No user stored palettes are used in this approach as the colors are defined in the map & layer definitions. The whole idea of providing the colors in an external file has been dropped as its more consistent and also fairly easy to create another version of the map having other colors defined within. 98 Supplying an user specified color palette to override the colors specified in the map fails at the missing mapping from a linear color list to the complex hierarchical structure of the map definition. 88 1. No user stored palettes are used in this approach as the colors are defined in the map and layer definitions. The whole idea of providing the colors in an external file has been dropped as it's more consistent and also fairly easy to create another version of the map having other colors defined within. Supplying a user specified color palette to override the colors specified in the map fails at the missing mapping from a linear color list to the complex hierarchical structure of the map definition. 99 89 100 2. The quantization algorithm can use quite some memory. 3 different memory allocation schemes have been provided. [[BR]] 101 Due to recent problems in low memory situations a choice has been made to use the most memory conservative stack based allocation scheme. 90 2. The quantization algorithm can use quite some memory. Three different memory allocation schemes have been provided. Due to recent problems in low memory situations a choice has been made to use the most memory conservative stack based allocation scheme. 102 91 103 3. In this phase only the colors from the VectorLayerDefinitions and in there the Area, Line, and Point Symbolizations are parsed 104 as cleartext. Any further evaluation requires resource lookups which are a higher order of complexity and should not be permanently enabled. 92 3. In this phase only the colors from the !VectorLayerDefinitions and in there the Area, Line, and Point Symbolizations are parsed as cleartext. Any further evaluation requires resource lookups which are a higher order of complexity and should not be permanently enabled. 105 93 106 4. No more memory issues. After some problems the code has been changed to duplicate any data from the MdfModel. Now the objects are created after stylization and destroyed after the tile has been created.94 4. No more memory issues. After some problems the code has been changed to duplicate any data from the !MdfModel. Now the objects are created after stylization and destroyed after the tile has been created. 107 95 108 5. The algorithm parsing the MdfModel collects all different MdfStrings from the color fields. In order to support expressions for those colors the list simply needs to be reinterpreted when read from theMgMap object. Like the resource lookup this can be added at a later point in time when test cases and clearer specs have been established.96 5. The algorithm parsing the !MdfModel collects all different !MdfStrings from the color fields. In order to support expressions for those colors the list simply needs to be reinterpreted when read from the !MgMap object. Like the resource lookup this can be added at a later point in time when test cases and clearer specs have been established.