MS RFC 55: Improve control of output resolution¶
dmorissette at mapgears.com
- Last Edited:
Adopted (2009/03/16) and Implemented.
MapServer is often used to produce a printable map corresponding to the map currently being displayed in the Web interface.
Printed maps will usually require a resolution higher than the default 72 pixels per inch which is commonly used for the screen (e.g. 150 or 300 dpi). In general printing is done by setting the map.resolution and requesting a larger size image for the same map extents. Setting map.resolution to a higher value ensures that the layers minscaledenom/maxscaledenom are properly evaluated for the larger image, but one thing is missing: symbology (line widths, symbol and font sizes, etc) is not adjusted to reflect the resolution change and the result is a map in which symbology looks smaller than what it looked on screen.
This RFC proposes a mechanism to fix this by automatically scaling the symbology when resolution changes so that the map maintains the same look at each resolution.
A new optional DEFRESOLUTION keyword will be added in the mapObj with a default value if 72 if not set. DEFRESOLUTION is the reference or default resolution for which all symbology sizes are defined in the mapfile.
At rendering time, if RESOLUTION is set to something different from DEFRESOLUTION, then the symbology in the layer definitions will be adjusted by a factor corresponding to RESOLUTION/DEFRESOLUTION. More specifically, this is done by multiplying the layer->scalefactor value by the resolution/defresolution ratio in msPrepareImage().
The following rendering parameters will be affected:
size (symbols and labels)
The following rendering parameters which were not impacted by scaling in the past will also be fixed to follow the scaling from now on:
offsets (line, point, polygon)
shadowsize, background-shadow-size (labels)
buffer around labels (collision)
minfeaturesize, mindistance (labels)
The case of outlinewidth for line styles is a bit different: it ignores the scalefactor so that we get a fixed outline width no matter what we use for size units, but we want it to follow the resolution/defresolution factor. For this case the line drawing code will need to have a reference to the mapObj passed to msDrawLineSymbol() so that it can access the resolution and defresolution parameters and do the right thing.
In the case of pixmap symbols, they will be scaled only if a size is set. If no size is set then no scaling happens.
Let's say we've got a mapfile that we use to produce a 400x400 pixels image for use on the Web, with both defresolution and resolution set to 72.
MAP ... RESOLUTION 72 DEFRESOLUTION 72 SIZE 400 400 ... END
In order to produce a 300dpi image for printing, the application code should request an image of 1667 x 1667 pixels (400*300/72=1667) and set resolution=300. MapServer will automagically scale all symbology sizes by a factor of 300/72=4.1667.
The new values of size and resolution for printing will likely be passed as URL parameters or set via MapScript in most applications, but for the purpose of this example, expressed in mapfile syntax then we'd use the following mapObj settings for printing:
MAP ... RESOLUTION 300 DEFRESOLUTION 72 SIZE 1667 1667 ... END
An application is using a mapfile developed for map.resolution=96 with MapServer 5.x. In order to take advantage of the new feature, one should set DEFRESOLUTION=96 in the mapfile, and at rendering time, setting RESOLUTION=300 will result in all symbology being scaled by a factor of 300/96=3.125.
Backwards Compatibility Issues¶
Existing apps or mapfiles that set RESOLUTION to a value other than 72 without setting DEFRESOLUTION will end up with their symbology scaled. This change in behavior is more likely to be considered as a feature than as a bug in most cases, but in case this is a problem for an existing app then the fix will be to simply add a DEFRESOLUTION to the mapfile which matches the resolution for which all mapfile classes and styles are defined.
The rendering parameters listed above that did not follow scaling in the past will be fixed to follow the scaling.
In addition to documenting the new feature, a note should be added somewhere in the mapserver docs that as of this change, the size values will reflect valid sizes (according to the SIZEUNITS settings, MS_PIXELS by default) only when the RESOLUTION is set to the default 72 or equal to the DEFRESOLUTION setting.
mapserver.h: new defresolution member in mapObj
mapfile.c, maplexer.l, etc: new DEFRESOLUTION mapfile keyword
mapdraw.c: adjust scalefactor as needed in msPrepareImage()
mapscript/php3/php_mapscript.c: expose new defresolution member
Adopted on 2009/03/16 with +1 from DanielM, HowardB, SteveW, TamasS, PericlesN and AssefaY.