.. _rfc55:

======================================================================
MS RFC 55: Improve control of output resolution
======================================================================

:Date: 2009/03/09
:Authors: Daniel Morissette
:Contact: dmorissette at mapgears.com
:Last Edited: 2009/10/06
:Status: Adopted (2009/03/16) and Implemented.
:Version: MapServer 5.6

Overview
------------------------------------------------------------------------------

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.

Technical Solution
------------------------------------------------------------------------------

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)
* width (lines)

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)
* pattern (line)
* gap (line)
* outlinewidth (labels)
* 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.


Usage example
------------------------------------------------------------------------------

Example 1:

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


Example 2:

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.


Documentation notes
------------------------------------------------------------------------------

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.

Files Impacted
------------------------------------------------------------------------------

* 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


Ticket Id
------------------------------------------------------------------------------

* https://github.com/mapserver/mapserver/issues/2948

* https://github.com/mapserver/mapserver/issues/3153

Voting History
------------------------------------------------------------------------------

Adopted on 2009/03/16 with +1 from DanielM, HowardB, SteveW, TamasS, PericlesN and AssefaY.
