Line aliasing in map services

The graphics pipeline used in ArcMap is based on Microsoft's Graphics Device Interface (GDI) technology. One of the limitations of this technology is that graphics can only be represented by integer coordinates. Real-world geometry does not typically occur only on whole numbers, so the coordinates would be rounded up or down when they are drawn using this graphics pipeline. This can be seen in vector export formats such as PDF—vector lines can contain some stair-stepping when they are closely inspected.

The graphics pipeline used by basemap layers and map services can use the true noninteger coordinates of your geometry and can render with subpixel precision, resulting in greater accuracy in these vector formats. However, when these features are drawn to raster formats such as PNG or BMP, the geometries must be again rounded to render on a pixel at the requested resolution. At low resolutions, this can result in some aliasing with multilayer line symbols, such as cased road symbols.

An example of aliasing due to more precise rendering (left: Map service, right: ArcMap)

Map services are capable of applying antialiasing to alleviate the effects of the above issue, but there are some cases in which antialiasing is not the most optimal option. For example, utilizing antialiasing can reduce the performance of a map service. Depending on the requirements of the service, this may be unacceptable. Also, for target formats that use an 8-bit palette (such as PNG 8 or GIF formats), antialiasing may not be as effective due to the dithering required to render continuous progressions of color. Note that antialiasing is not available for basemap layer drawing.

Antialiasing can greatly improve a line's appearance, but at the cost of performance (left: No antialiasing; right: Best antialiasing).

To alleviate this issue without utilizing antialiasing, the Prepare window has an analyzer that will detect multilayer line symbols that could potentially exhibit this problem.

There are two solutions for this analyzer. The first is to flag the layer for automatic adjustment of line sizes upon conversion. When the map document is shared as a map service, the line widths of layers for which this option is enabled are automatically changed to ensure that they render consistently at 96 dpi or higher. The size of the symbol in the map document remains the same. For most users, this solution is sufficient. Check the Preview window to ensure that the appearance of the corrected line meets your expectations. Note that this analyzer does not appear for basemap layers because automatic adjustment is always chosen for this case.

Left: Original line widths of the expressway symbol rendered in a map service; Right: After correction. Note that the casing lines no longer appear dashed in the corrected version.

An alternative solution would be to manually change the structure of the multilayer line symbol so that the line sizes are more appropriate. This also allows conversion for use with a target dpi other than 96 dpi (for instance, 72 dpi).

Designing lines for a specific resolution (dpi)

To determine the appropriate line sizes for a given resolution, input the sizes of each of the symbols in the multilayer line symbol into the following formula. As discussed before, the value for TargetResolution should reflect the desired minimum resolution at which this symbol will be used.

WidthInPixels = (LineWidth in points * TargetResolution in dpi)/72

If WidthInPixels is less than 1.5, the width should not be changed.

If WidthInPixels is equal to or greater than 1.5, use the following formula to determine the edited width:

NewWidthInPoints = (WidthInPixels + 0.5)

Now round NewWidthInPoints to the nearest integer (whole number) value that is not greater than NewWidthInPoints.

The final line width should be set to (RoundedNewWidthInPoints * 72)/TargetResolution.

So, for example, if your desired resolution is 44 dpi, and your line symbol's width is 2.60, the math would be executed as follows:

WidthInPixels = (2.60 * 44)/72.0

WidthInPixels is 1.5888888, which is greater than 1.5, so continue:

NewWidthInPoints = (1.588888 + 0.5) = 2.10

Rounding down, NewWidthInPoints = 2.0

The final line width should be set to (2.0 * 72)/44 = 3.27 pts

In another example, if your desired resolution is 120 dpi, and your new line symbol's width is 2.60, the math would be executed as follows: