Printing at 300 DPI with ArcGIS Server purely through the ADF
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.
Great post.
I am actually in the process of right the same thing you described here for one of our customers and using relative the same approach.
One thing I am adding different is create layout page where the user can rearrange where each element will go and the size of it. Basically have a colored Div box for each element and some javascript that handles drag and drop and resize of them. When the user clicks generate pdf button, it sends the locate and size of all the div tags to server then my code will place them in the correct location using the iTextsharp library.
Right now I am about half way done on mine. I would love to see your code on how you do this especially the part about the legend since I haven’t started that one yet. If you are able share any of it, please email me at kdunlop@spateng.com.
Thanks for the great post.
Hi Kevin,
I am taking the approach of using a configuration file to specify the XY location and the height/width of the image elements. I am also using an existing PDF file as a template and just inserting the map image, legend, title, name, date into it using the PDFStamper class in iTextSharp. This way only the dynamic elements are positioned during map generation.
I will send the code you had asked for to you via email.
Thank You,
Vish
http://Vishcio.us
Hey Vish,
I’d love the code. In fact, I’d love any of your code ;).
ggoodrich (at) enspiria.com
Thanks!!
Vish,
We’ve come up with a few approaches to this from the wildy unmaintainable (twice!) to much simpler and more configurable. The approach we’ve taken most recently is to use a .NET port of the Apache FOP project called nFOP. We can establish a nice layout in a configurable XSL format and then just supply the map image and other info like a DataTable of some tabular information we want to display. Apply the transformation and voila, we’ve got PDF output and some other formats as well. I’ve used PDFSharp in the past to do the same as what you’ve got with iTextSharp, but this FOP approach seems more flexible since the end user can monkey with the XSL and update their layout.
Anyway, I am definitely interested in your approach to generate legend images and also deal with GraphicsLayer. Can you shoot me a snippet to dvhthomas at gmail dot com? Thanks for a well written and interesting post.
Dylan
Hi Dylan,
I would throw out a word of caution on using the XSL-FO standard. The standard is a great idea but is real hard to implement. None of the products or frameworks in the market is completely compliant with XSL-FO. In fact, they had to come up with various (3) levels of conformance with XSL-FO for the products out there because of that reason.
I will have the code out to you over the weekend.
I am real interested in the success you have had with it though. I definitely agree that XSL-FO is the future for reporting.
Thank You,
Vish
http://www.Vishcio.us
hi vish,
i want the code to generate legend & pdf using itextsharp.
If you can share your code?
thanks
Pragnesh
Vish,
I have also created a very similar task using iTextSharp. I originally used a static image for the legend to avoid problems of the legend being to big or not fitting in the alloted space. I would love to see the code that you are using for your dynamic legend if you don’t’ mind? I appreciate the help.
Thanks for the great post.
Alex
Vish,
Wow…first of my coworker and I have struggled with printing via the web ADF and have implemented a very similar approach using iTextSharp and the WebADF. One isse that we have had is that we are not able to print a map to scale in the same manner that we are able to using the IMapServerLayout or the way we did via ArcIMS. Have you had similar issues? Also I would LOVE to see the snippet of code you are using to generate a legend. Right now we are just using a static image. My email address is bcd_mtb@hotmail.com. Thanks for such an awesome blog.
Cheers,
Blair
Hi Vish,
We are also working on a print task, but we are using the Print custom task for the .Net WebADF found at ArcScript. The approach here is to use a server object extension to print the map in layouts generated in ArcMap. We are still having some problems with the graphics layer as it seems we cannot get the transparent fill types to work in pdf. I thin kwe will solve it by generating an image of the graphics layer with DrawExtent and at the image as a raster layer to the layout before printing.
Anyway, we also need to have the legend so I would appreciate to see you code for creating the legend. My email is jonasengedal at gmail . com.
Thx
Jonas
PS. Nice post
Hi Vish,
I’m getting ready to start programming for the same product you already created. If you wouldn’t mind sharing, that would be great!! Awesome work and it would save me tons of time. Thanks!
Scott
scw115@excite.com
What Scott said —
I need to be able to print a map layout from a map control that looks at more than one service, so this looks like just the ticket. If you don’t mind sharing, that would be great…
danl
[…] grew out of being able to print multiple map resources on the map through the ADF. I had blogged about it before here. I have made some changes to the code snippet after input from some other people trying to do the […]
A very interesting post – I am starting to work on developing a print task that can handle multiple map resources. The approach I had taken is to return each map image from each map resource and then merge them (same as you). I would be grateful if you could share your printing code with me as it would help me out a lot! – email: chris.vipond@hotmail.com
Hi Vish,
I’m getting ready to start developing a print task to publich a PDF with lezend and Index dynamically. If you wouldn’t mind sharing, that would be great!!and it would save me lot of time. Thanks! email: itagsubbu@gmail.com
Subbu
Hey Vish,
I just started working a print task where I need to be able to print graphics, I would be grateful if I could get my hands on your print code.
Thanks Jay
Hi, Vish. Great post. Would you be willing to share the code at my e-mail address? Thanks in advance.
Hi Vish,
Talk about convergent development. Your task does exactly what our one does, encounters the same issues and overcomes them with the same solutions (those distorded Graphics Layers were a pig and I only found the solution through pure dumb luck).
What interests me is that you haven’t encountered any size limitations. I was only able to get metre square images at a dpi of 160 before the System.Drawing.Graphics DrawImage method call gives out with a OutOfMemoryException error. This is what I’m using to merge the images from the multiple resources and graphics layers and I assume you’re using something similar. If not what are you using to merge the images?
This is more of a catch all error in the Drawing namespace but I was only testing the bounds rather than explicitly printing to A0 for a particular project so I wasn’t terribly concerned and just assumed I’d reached the limitations of this approach.
ArcGISServer allows you to create images the size of a whale so you can be sure a User will eventually do so.
Phil.
Hi Phil,
I didn’t have any OutOfMemoryExceptions(s). What is the dimensions of the image you are trying to generate in pixels?
Thank You,
Vish
It seems inconsistent, possibly related to the type of data being printed and the size of the subsequent generated image, but an image of Height 9150px and Width 6575px at a DPI of 230 generates an image fine in ArcGISServer but throws the Out of Memory exception when attepting to merge the images.
I’ve also seen your “Parameter is not valid” error message, though not exclusively on Graphics Layers.
Great post.
I am actually in the process of right the same thing you described here for one of our customers and using relative the same approach.
please share the code to me my email id is neeraja.ec@gmail.com, it will be help ful for me. thanks
Hi,
I too am interested in the code to create the legend. Thanks for a great blog.
Andrew
Hi Vish,
This is a great post and got me started in the right direction I am having problems with the graphics layer getting stretched and have not figured out how you are pre-calculating the extents is there any chance you could e-mail me a snippet of your pre-calculate method.
Thanks,
Jason
jstewart143@tampabay.rr.com
I am experiencing the same issues that you wrote about. Could you please provide me with the code?
Hi Vish,
Would you be willing to share the code at my e-mail address? Thanks in advance.
Subbu
Great work. Can you share your code: laksh.gisprog@gmail.com
Vish,
Great post – would you mind sharing any of your available code to grefly at gmail . com? Thanks in advance –
Gregg
hi vish,
This is great post.
I work around all the point described by you and able to generate the perfact export to pdf as you shown above.
But, I am not able to do it with Graphics Layer.
I will be very thankful to you, If you help me to work around Graphics Layer.
Waiting for your Response !!
Thanks
Pragnesh
HI, Vish,
Could I ask if you’re altering the size of your map control at run time before generating? Do you have a code snippet just for fetching the image, i’ve tried numerous ways all resulting in the same resolution. Any code snippet would be greatly appreciated.
Dan
Hi Vish,
I just landed on your blog after constant searching for the same thing I am trying to do. I have been trying to analyze code that is already out there and seem to have hit a road block, but your blog has inspired me and was hoping you can email me the code snippet for the legend creator and how you were able to pass the DisplaySettings and get the Graphics Layer to export with the PDF.
Great blog BTW!
-Fernando
Hello,
Uhm, you seem to have hit a sweep spot with the several map services, grahic layer and legend printing requirements. I have a task for a similar solution in my very near future, but I was looking at it from a web service implementation perspective.
I would appreciate if you can share your code to give me a big headstart.
Thanks,
Felix
Vish:
I’m curious about two portions of your approach. First how you are performing the extent pre-calculation for the graphics layer. I’ve been getting around this issue by ‘reprojecting’ the graphicslayer image using GDI+ but this seems like a hack, your approach sounds more promising. I’m also interested in how you are setting up the layout for your dynamic legend so any code examples for these would be appreciated. Thanks for alerting me to iTextSharp, it is a great resource
Vish,
Great work,I really want to know what you’ve done with printing PDF.Would you please share the code?
Sean,
One approach to precalculating the extent to avoid the Graphics Layer being skewed is described on the ESRI User Forums.
forums.esri.com/Thread.asp?c=158&f=2276&t=251310&mc=2#769164
hi vish,
Once again i am here.
Is there any way to give the Name to the legend created as graphics?
it comes long guid string. Is there any way to change the guid string with name??
thanks
Hi,
I am working on creating a dynamic legend of Scale dependent Map service. Every time i made a request i didnt get the updated legend. Can you please provide me the code through which you are performing the following task.
Thanks
Deep
deeplakhanpal@yahoo.co.in
Hi Deep,
See here https://viswaug.wordpress.com/2008/03/16/dynamic-legend-generation-through-the-adf/
Thank You,
Vish
Hi Vish,
Like everyone else, I think this is a great post. I’m on a tight deadline to do something similar and I would appreciate it if you could share your code to give me a head start.
Keep up the good work!
thanks,
Steve
Hi Vish,
Thanks for the legend code you sent. I’d actually already sorted this issue, and was more interested in the code you have used to create layouts using itext. I’ve been working with itext and following their examples for a few days now, but the results aren’t always as expected.
Also, I was wondering if anyone else is having issues with layer transparency when using the print task? I have a problem where transparency is seemly ignored sometimes (rendering the layer black in the resulting image). This occurs intermittently, and seems to be connected to the scale you are viewing the map at. Any help would be appreciated!
Thanks,
Steve
Hi viswaug
interesting post. from the EDN forums, all i’ve seen are local connections using the IMapServerLayout interface, so your implementation using DrawExtent method on the IMapFunctionality is interesting.
do you experience any delay in generating the pdf, as i find that using local connection and the IMapServerLayout interface is slow and sometimes the ? This is using the internet connection instead of local connection right?
Hi Mei,
The delay is propotional to the image size being retreived. If you are trying to retreive an image for a 300 DPI print, there is going to be bigger delay. But the delay is not at all bad enough to not use this technique.
Hi Vish,
Great post and good discussion here! I am developing a similar function if not exactly the same. I am facing difficulties in generating an image from Graphics Layer and creating legend. It would be great help if you would share your code with me at xdhong at gmail.com?
I appreciate it.
Don
Hi Vish,
I’m really struggling to get the combined resources to print out with the pagelayout without converting back to AGS objects…
It would really help if I could see a snippet of your code to help me on my way.
Many thanks,
James
hemphill101@hotmail.com
Hi viswaug
Im looking for a very same tool can you please provide me with your code at askailla@gmail.com
Hi Viswaug,
Nice work…
I a workign on a similar task and have almost done with the print task. I am interested in the legend part. Can you share the code with me please for generating the legend. That would be of great help.
Keep up the good work Viswaug..
Thanks,
Vibhav
Hi viswaug,
I have done something similar to what you describe here. I, too, would like to print my maps at 300dpi, but I can’t get my scale bar to return at that resolution – only 96 dpi – which means it does not accurately display the scale of my map. How did you get your scale bar to print out correctly?
Thanks for your help.
Vish,
Outstanding post. I have been battling with this for some time and your approach to the legend is very nice. Is there any way that you would be willing to also share your print code? I know that this took awhile to complete, but would really be of great value to me and the ArcGIS Server community. Let me know what you can do and thanks again for the great post and ideas!
Thanks for the support!
Aaron
It’s a good post. It will be very helpful if you could you also share the implementation way of the above code.
Vish,
I need to display the legend with only the item in the current map extent durin print process.Can anybody tell me what changes I need to do in the above posted code so that I can get legend information of layers visible in the current Map extent???
-Thanan
Hi Vish,
This is a fantastic article. I am about to embark on adding printing capabilities to an ArcGIS Server application as well. I would really appreciate it if you could share your code on how you were able to print the map including the featuregraphics layer and TOC. Thanks!
Jennifer
Thanks for the great post Vish, I am traditionally an ArcObjects developer now creating an ArcGIS Server website with the 9.3 ADF. I have all the elements in place but would love to incorporate the kind of print capability you have employed. I need to print multiple services and graphics layers. I would really appreciate you code for this if possible. Keep up the good work.
Great job!!
i need to print multiple resources and one graphiclayer too. i would really appreciate your code for this.
best regards
hi vish,
i want the code to generate legend & pdf using itextsharp.
If you can share your code?
thanks
Vish,
I think you’re a good ways ahead of the curve here (still). Those of us on the back end appreciate you putting this online. Would you be willing to share your code for this?
Thanks a lot.
Brad
Wow, that is some great thinking! Code I get a copy of your code? I’m using 9.3, but I’m guessing there aren’t too many changes.
Just in case,
Could I also get a copy of your code for the dynamic legend?
Thanks,
Lynn
This would help me out a lot in all of my 9.3 ArcServer ADF apps. Could I also get a copy of your code?
thanks,
Matt
Hello!
Great thinking about printing! I am looking for code to teach myself how to do this and I was wondering if you would be ok with sending me the code so I can get some ideas? I am working with 9.2.
Thank you again!
I am actually in the process of right the same thing you described here for one of our customers and using relative the same approach.
Can you please share the code and help me out in completing this task.
Regards,
Bobby.
Great post. Like all the others, I too need to export multiple map resources. I would very much appreciate getting your code.
Thanks
chad
Hi Vish,
Great post.
Could you please share the code to my email carpla@gmail.com?
I hope this help me on printing PDF maps depending on scale, dpi, size, … for multiple services and graphics layers.
Thanks!
Carlos
Hi Vish, I am looking for code to print PDF maps with ADF.
Could you please share the code to my email nalcoba@gmail.com?
Thanks, Natalia
Vish,
I’ve seen lot’s of people requesting your code and no replies from you saying you won’t. So…., could you please email me the code to print PDF of different sizes & multiple layers: vmbackus AT msn.com.
Thanks so much – Vickie
Hello.
I´m trying to do something like that.
I see you blog and the article is very interesting.
Could you please share the code to my email mtienda@sigsa.info, please?
Thanks so much
I, like many others, am trying to do the samething.
Please share the code with me at shelton@lojic.org.
Thanks a ton
Vish, could you please send me your code for creating high res PDF map layouts with the Graphic Layer.
davehighness@gmail.com
Thank you, Dave
Hi Vish,
Like everyone else, I think this is a great post. I’m on a tight deadline to do something similar and I would appreciate it if you could share your code to give me a head start.
could you please send me your code for creating high res PDF map layouts with the Graphic Layer.
Keep up the good work!
thanks,
abhi,
Does anyone know, how to print the transparent graphics layer? I sent the buffered features to SOE, which has transparencies. But they are printing non-transparent.
I set the graphics symbol transparent, but still no luck.
Any workaround besides saving it as a shapefile and bring it back to SOE.
Thanks,
Shail
Vish,
How to print the map from internet resource instead of local resource?
I was using the SOE to print the map. Any hint would be appreciated.
Vish,
Have you considered publishing your code to the ESRI forums (or have you already)? I’d like to take a look at what you did if you could send me the source code.
Thanks!
Eric
Vish,
Looks like a great tool I’ve had problems myself accomplishing these features, would you mind sharing the source code with me.
Great Post.
Gary
More than a year has gorne and it still looks to be the best attempt. Why can’t ESRI understand that our customers wants to print what they see in a good quality?
In my attempt I have a problem with the custom graphics. Colors and size works fine but the style doesn’t. I hope your code could inspire me, so would you please send me a copy? Thanks
\Morten
Hi,
Like everyone else…great post. We are looking to implement the same functionality and a look at the code would be greatly appreciated if possible.
Thanks,
Neil
do you have the code for this task? i need do something simliar
Hi , i have problems with itextsharp to scale images , can you tell me what is wrong?
Dim tableImg As New PdfPTable(2)
Dim widths As Integer() = {((PageSize.A4.Rotate.Width * 80) / 100) + PageSize.A4.Rotate.Width, ((PageSize.A4.Rotate.Width * 20) / 100) + PageSize.A4.Rotate.Width}
tableImg.SetWidths(widths)
Dim jpegMap As Image = Image.GetInstance(pimageMap)
jpegMap.ScaleAbsolute(600, 500)
jpegMap.Alignment = iTextSharp.text.Image.ALIGN_LEFT
Dim cellImagen As PdfPCell = New PdfPCell(jpegMap,False)
cellImagen.Border = 15
cellImagen.BorderColor = Color.BLACK
tableImg.AddCell(cellImagen)
Dim jpeglegend As Image = Image.GetInstance(pimagelegend)
jpeglegend.ScaleAbsolute(200, 500)
cellImagen = New PdfPCell(jpeglegend, False)
tableImg.AddCell(cellImagen)
tableImg.WidthPercentage = 100
document.Add(tableImg)
Hi,
I’ve to do some something similiar to combine multiple resources (cache + dynamic data) for printing. Would be great if you could share your code!
Thx
Florian
Hi Vish,
Thanks for your post. It helps great!!!. Can you send me code for generating layout as shown in picture? Email id:vipal.shah@gmail.com
Thanks,
Vipal
Wish, great stuff… I’ll stand the queue for sharing the code. I have problem especially with the graphics layer that is always skewed. thank you. nnevie@gmail.com
Hello – This is similar to what we have been struggling with. If you are willing to share the code, I would sure appreciate it. Thank you in advance!
Hi Vish, i am struggling with a similar task. can u plz share the code for this at my email: usman.jamil08@gmail.com
Thanx in advance
Great post.
Could you please share the code to my email said.boubakri@gmail.com?
I hope this help me on printing PDF maps depending on scale, dpi, size, … for multiple services ( Local, BingMaps….) and graphics layers.
Thanks!
Hi Vish,
I have been working on this fore days, I would like to ask you to share your code, if it is possible for you this is my email defelice.luca at gmail.com.
thanks a lot
Luca