I just finished up a task for the current project I am working on where the client needed to be able print all the resources in the map at multiple resolutions and paper sizes. There are a lot of code snippets on ArcScripts that let you print maps using ArcGIS Server using the IMapServerLayout interface on the MapServer object. But using that approach did not solve 2 major requirements I had to satisfy
- Ability to print multiple map resources that might be loaded on the map
- Ability to print the GraphicsLayer from the web tier
Both these requirements would prevent using the IMapServerLayout interface for the printing task since IMapServerLayout works only on single map server objects and it cannot include the GraphicsLayer easily. So, I had just decided to use the DrawExtent method on the IMapFunctionality of every resource on the map after setting the required values on the DisplaySettings property and merge them together to get the complete map. Since, I had to print at 300 DPI, the size of the images I was requesting from ArcGIS Server was pretty huge. For printing a map on a A4 size paper, I was requesting an image size of ( ~ 3000 X 2000). But, whenever I made a call to DrawExtent for an image that size, I kept getting an image of size (2048 X 2048). After, banging my head against the walls for a few hours and using SOEXplorer, I figured out that MapServer objects have “MaxImageWidth” and “MaxImageHeight” settings that default to 2048. Once, I bumped up that number I was getting back images of the size that I requested. You can also bump up the “MaxRecordCount” property to enable ArcGIS Server to return more than 500 records for large queries. But before you bump this number up, take a minute to think about the consequences of handling such large number of records on the client side.
I was also concerned about the performance of ArcGIS Server when requesting images this size but the performance was acceptable and ArcGIS Server kept chugging along pretty good after several such requests. The GraphicsLayer also didn’t cause any problems for images that size (~ 3000 X 2000).
I moved on to generating ANSI D (plotter size maps) which resulted in size of images requested being more than (~ 10000 X 10000). To my pleasant surprise, ArcGIS Server didn’t throw a fit when requesting images that size. But, the GraphicsLayer didn’t like the request that size and decided to throw an exception saying ‘Parameter is not valid”. So, printing on a ANSI D size paper at 300 DPI should be possible if you don’t need that GraphicsLayer in the printout.
The GraphicsLayer decided to misbehave again when I was requesting images whose aspect ratio did not match the aspect ratio of the map on the browser. The ArcGIS Server had again played nice and returned map images with the aspect ratio requested. So, with the two resources not behaving consistently, I ended up with the final merged map images looking like below. You can see that the polygon on the GraphicsLayer was getting stretched vertically instead nicely overlaying the polygon from ArcGIS Server below.
But, this problem above I was able to work around. I was able to pre-calculate the extents that will be returned by the server and request the same size from the GraphicsLayer.
After all this, the printing functionality was not complete, the ADF had no easy way of obtaining a legend for all the resources on the map. You would think that the ADF would have the ability to generate a legend for the map already, but no luck on that yet. Hopefully in 9.3? But we couldn’t wait and hope for ESRI to include that feature. So, I went ahead and built the legend for the map dynamically. It wasn’t really that hard to do. I was able to request the swatches for the legend from the IMapTocFunctionality and create an image of the legend dynamically. Please contact me if you interested in the piece of code that generates the legend. I will be happy to share it with you. An example of the dynamically generated legend image is shown below.
With all the ingredients in place, I was able to generate a PDF of the map print out (looking like below) using the iTextSharp library.