Wednesday, December 17, 2008

Print Map with ArcGIS Server

Last week, i was to do some simple map printing of an ArcGIS Server application, the first thing i thought of is Layout view of the map, why this approach won't do the job for me ??

the reason is that im calling SOAP API operation which are stateless operations and it won't effect the Mapservice so there is no way to get that done.

as a start i thought i will take the map image put and put it in another aspx and print it along with the legned that im generating dynamically.

in my application users don't want to display the whole legend, they want to display the legend of some specific layers.

one issue thta i faced in getting the Map Image is that i have 3 rourceitems
1- Graphics Layer
2- non-Cahced Service
3- Cached Service

getting the image the normal would get only the non-chached service image, but found a way to get the image from all the resources for printing.

soon i'll pasting the code with some screenshots.

stay tuned

UPDATE:

create a sub folder in ur project directory or anywhere you want and call it "tmp". the "tmp" folder will be used to save the generated image.

you an extra page lets call it PrintPage.aspx

<%@ Page language="c#" Inherits="Printing.PrintPage" CodeFile="PrintPage.aspx.cs" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>PrintPage</title>
<style type="text/css">

</style>
</head>
<body style="margin:0 0 0 0">
<form id="Form1" method="post" runat="server">
<table border="0" width="100%" align="center">
<tr>
<td style="width: 671px" align="left"><img src="GenerateImage.aspx" id="MapImage" Width="671" Height="606" runat="server" style="border-right: black 1px solid; border-top: black 1px solid; border-left: black 1px solid; border-bottom: black 1px solid" /></td>
<td valign="top" align="left">
<asp:GridView id="GVLegend" runat="server" Width="129px" Height="63px" GridLines="Horizontal" EmptyDataText="No Legend" AutoGenerateColumns="False">
<Columns>
<asp:ImageField DataImageUrlField="LegendImage">
<ItemStyle Height="40px" Width="30px" />
</asp:ImageField>
<asp:BoundField DataField="LegendName" >
<ItemStyle Font-Size="Smaller" />
</asp:BoundField>
</Columns>
</asp:GridView>
</td>
</tr>
</table>
</form>
</body>
</html>



the code behind PrintPage.aspx.cs


using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using ESRI.ArcGIS.ADF.Web;

namespace Printing
{
public partial class PrintPage : System.Web.UI.Page
{
protected void Page_Load(object sender, System.EventArgs e)
{
MapImage.Src = Session["MapImageURL"].ToString();
}
}

}



in you default.aspx add a button that causes a callback to this function

public void PrintMap()
{
string MapImageURL = GISFunctions.ExportMapImage(Map1, Page.Request.PhysicalApplicationPath + @"tmp\");
Session["MapImageURL"] = "tmp/" + MapImageURL;


Map1.CallbackResults.Add(GeneralUtilities.Utilities.GetCallBack(null,null,"javascript","window.open('" + "PrintPage.aspx', 'PrintWindow', 'dependent=yes ,width=800, height=500, status=no, toolbar=no, menubar=yes, location=no, resizable=yes, scrollbars=yes');"));
mapstring = Map1.CallbackResults.ToString();
}


the ExportMapImage function code

public static string ExportMapImage(ESRI.ArcGIS.ADF.Web.UI.WebControls.Map ADFMap, string OutputPath)
{
System.Collections.Generic.List<System.Drawing.Image> bitmaps = new System.Collections.Generic.List<System.Drawing.Image>();
foreach (ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality mf in ADFMap.GetFunctionalities())
{
if (mf != null)
{
ESRI.ArcGIS.ADF.Web.MapImage mapImage = mf.DrawExtent(ADFMap.Extent);

mapImage = mf.DrawExtent(ADFMap.Extent);
if (mapImage == null)
continue;
if (mapImage.GetImage() != null)
{
bitmaps.Add(mapImage.GetImage());
}
}
}

System.Drawing.Bitmap newImg = new System.Drawing.Bitmap(Convert.ToInt16(ADFMap.Width.Value), Convert.ToInt16(ADFMap.Height.Value));

System.Drawing.Graphics imgGraphics = System.Drawing.Graphics.FromImage(newImg);
int i = bitmaps.Count - 1;
while (i >= 0)
{
imgGraphics.DrawImage(bitmaps[i], 0, 0, Convert.ToInt16(ADFMap.Width.Value), Convert.ToInt16(ADFMap.Height.Value));
i += -1;
}
long Ticks = DateTime.Now.Ticks;
string ImagePath = OutputPath + "mapimage" + Ticks + ".jpg";
newImg.Save(ImagePath, System.Drawing.Imaging.ImageFormat.Jpeg);

return "mapimage" + Ticks + ".jpg";
}


in the same way, you can add the legend next to the map, the reason why i didn't add it in code in the im displaying the legend based on different criterias which i didn't want to confuse others including it my code, but still if u need to know how to generate the legend, can can mail me.

13 comments:

Anonymous said...

hi i really appreciate your help but one question about your solution
what if it s a web mapping site that is for everybody so everyone would be creating images for printing and you need the save them on disk. Imagine 100,000 people do that in one day.Tell me what can i do for solve that problem and thanx for you help.

andres tejada
and_k_27@yahoo.com

Noureddine El-Zaatari said...

for that, i guess that you should create a windows service or a simple windows task that runs every 30 min to delete the images in the folder, i have a windows scheduled task that run everyday at 12:00 am

hope this helps

jd said...

Hi! I would greatly appreciate if you could publish your code to generate the legend as well. I'm currently struggling with generating the legend. not all layers are properly drawn.

Seth said...

Hey--

Thanks for the post, this will really help me out. Can you post the project code?

Thanks,
Seth

Anonymous said...

I have a question. I am getting an error for GISFunctions and GeneralUtilities. Is there a reference I need for these two? Also the NewImg as System.Drawing.Bitmap height and width values is throwing an error say that a short cannot be converted to a bitmap. Any ideas. I've changed your code from C# to VB.

Thanks!

Anonymous said...

Can anyone recommend the robust Network Monitoring utility for a small IT service company like mine? Does anyone use Kaseya.com or GFI.com? How do they compare to these guys I found recently: N-able N-central malware detection
? What is your best take in cost vs performance among those three? I need a good advice please... Thanks in advance!

Anonymous said...

[url=http://tinyurl.com/y9qxher][img]http://i069.radikal.ru/1001/35/75e72b218708.jpg[/img][/url]



Related keywords:
can you buy Tramadol cash on delivery
prescription Tramadol without
next day air ups Tramadol Tramadol
Tramadol online purchase saturday delivery
Tramadol money order
Tramadol 50 mg tablets
Tramadol buy
buy deine nachricht online site Tramadol
[url=http://www.zazzle.com/AlexanderBlack]Tramadol cTramadol [/url]
[url=http://seobraincenter.ru]http://seobraincenter.ru[/url]
cheap order Tramadol
buy cheap Tramadol online no prescription
buy cheap Tramadol free fedex shipping
Tramadol and cod saturday delivery
euphoria Tramadol
Tramadol free consultation fedex overnight delivery
best price for Tramadol generic Tramadol

Anonymous said...

hey. Great Blog you've got here. I've been tooling around trying to find some new information and I think i found it! Thanks a lot!
I have a website too. You can check it out at Satellite TV for PC

Gil said...

Hi, i dont know if you can help me , but...
I m trying to implement a printask map using Silverlight Visual Basic.net but it aint easy, i need use a layout that is in the MXD of an ArcGIS file, and to completed i need to export the map to some fileformats like pdf, jpg, bmp.
can you help me??
thanks

Noureddine El-Zaatari said...

the silverlight APIs doest support export for the moment, u need to create a webservice that exports to several image formats using arcobjects

Gil said...

Thanks for your answer.
Can you tell me how can i do what you say?

didik said...

Can you help me abaout GISFunctions and GeneralUtilities? I can find it to declare.

Thank.

Noureddine El-Zaatari said...

guys, common it east from the general utilities, im just calling this

public static CallbackResult GetCallBack(string Controltype, string ControlID, string EventArgs, params object[] Parameters)
{
return new CallbackResult(Controltype, ControlID, EventArgs, Parameters);
}



and the other function im using is exportmapimage which is posted up there, just use the functions directly..