Select to view content in your preferred language

Export map to png

5588
12
01-11-2011 09:19 AM
NancyHernandez
Emerging Contributor
Hello!! I want to export a control map to png image format, I found this page

http://geekswithblogs.net/braulio/archive/2009/07/12/export-canvas-to-png-and-save-it-in-your-local....

where describe the way to export the content of a canvas control, like this:

[HTML]<Canvas x:Name="canvasToExport" Width="300" Height="180">
                <Rectangle Canvas.Left="10" Canvas.Top="10" Fill="DarkBlue" Width="200" Height="100" Stroke="Blue" StrokeThickness="5">
                </Rectangle>
                <Ellipse Canvas.Left="50" Canvas.Top="50" Height="100" Width="200" StrokeThickness="5" Stroke="Black"  Fill="Gold"/>         
            </Canvas>
        <Button Content="Export canvas to PNG" x:Name="btnExport" Width="200" Margin="5" Click="btnExport_Click"/>[/HTML]

 private void btnExport_Click(object sender, RoutedEventArgs e)
        {
            CanvasToPNG canvasToPNG = new CanvasToPNG();

            // It will export to PNG the canvas content
            // parameter canvas ID
            canvasToPNG.ShowSaveDialog(canvasToExport);
        }


and the class CanvasToPNG is

 public class CanvasToPNG
    {        
        public void ShowSaveDialog(Canvas canvasToExport)
        {
            // Instantiate SaveFileDialog
            // and set defautl settings (just PNG export)
            SaveFileDialog sfd = new SaveFileDialog()
            {

                DefaultExt = "png",
                Filter = "Png files (*.png)|*.png|All files (*.*)|*.*",
                FilterIndex = 1
            };

            if (sfd.ShowDialog() == true)
            {                
                SaveAsPNG(sfd, canvasToExport);
            }
        }

        private void SaveAsPNG(SaveFileDialog sfd, Canvas canvasToExport)
        {
            WriteableBitmap bitmap = new WriteableBitmap(canvasToExport, new TranslateTransform());
            EditableImage imageData = new EditableImage(bitmap.PixelWidth, bitmap.PixelHeight);

            try
            {
                for (int y = 0; y < bitmap.PixelHeight; ++y)
                {
                    for (int x = 0; x < bitmap.PixelWidth; ++x)
                    {
                        int pixel = bitmap.Pixels[bitmap.PixelWidth * y + x];
                        imageData.SetPixel(x, y,
                        (byte)((pixel >> 16) & 0xFF),
                        (byte)((pixel >> 8) & 0xFF),
                        (byte)(pixel & 0xFF), (byte)((pixel >> 24) & 0xFF)
                        );
                    }
                }
            }            
            catch (System.Security.SecurityException)
            {
                throw new Exception("Cannot print images from other domains");                                
            }
            // Save it to disk
            Stream pngStream = imageData.GetStream();
            StreamReader sr = new StreamReader(pngStream);
            byte[] binaryData = new Byte[pngStream.Length];
            long bytesRead = pngStream.Read(binaryData, 0, (int)pngStream.Length); using (Stream stream = sfd.OpenFile())
            {
                stream.Write(binaryData, 0, binaryData.Length);
                stream.Close();
            }
        }
    }


I rename the canvas control by the control map, when the project is running does not send error messages, but the website throws this error

Mensaje: Unhandled Error in Silverlight 2 Application Cannot print images from other domains   en ESRI.ArcGIS.Samples.SilverMapDemo.ExportarToPNG.SaveAsPNG(SaveFileDialog sfd, Map Map)
   en ESRI.ArcGIS.Samples.SilverMapDemo.ExportarToPNG.ShowSaveDialog(Map Map)
   en ESRI.ArcGIS.Samples.SilverMapDemo.Page.btnabrir_Click(Object sender, RoutedEventArgs e)
   en System.Windows.Controls.Primitives.ButtonBase.OnClick()
   en System.Windows.Controls.Button.OnClick()
   en System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   en System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)
   en MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)

What I should do?
0 Kudos
12 Replies
dotMorten_esri
Esri Notable Contributor
Silverlight does not allow you to grab a screendump of images that comes from a different domain and then read the pixel values. So you must have your .xap file hosted on the same domain as your ArcGIS Server data, or use the ProxyUrl property to push the tiles through the proxy so it will look like it comes from the same domain.
Alternatively, you can run the app in full trust out of browser mode which doesn't have this security restriction.
0 Kudos
NancyHernandez
Emerging Contributor
Thanks for the reply!!

Well the fact is I don't have enough knowledge with this kind of things jeje,:confused:

how I can use the ProxyUrl poperty?

use the ProxyUrl property to push the tiles through the proxy so it will look like it comes from the same domain.


Thanks again!!
0 Kudos
JenniferNery
Esri Regular Contributor
0 Kudos
PLadd
by
Frequent Contributor
I pasted your code into my project and got everything accepted except this line:

EditableImage imageData = new EditableImage(bitmap.PixelWidth, bitmap.PixelHeight);

After I do a Build it says:

"The type or namespace name 'EditableImage' could not be found (are you missing a using directive or an assembly reference?)"

What am I missing?
0 Kudos
JenniferNery
Esri Regular Contributor
I believe EditableImage in the code-snippet came from this SL sample: http://blogs.msdn.com/b/jstegman/archive/2008/04/21/dynamic-image-generation-in-silverlight.aspx
0 Kudos
BabakSekandari1
Deactivated User
@SharpGIS, thank you for stating:
"use the ProxyUrl property to push the tiles through the proxy so it will look like it comes from the same domain."

@jenniferdnery, thank you for stating:
"You can read about Proxy here: http://help.arcgis.com/en/webapi/sil...0000022000000/ "

The link indicated states:
"Use a proxy page to provide access to a secure service by defining the ProxyURL property on a service layer. The proxy page stores credentials to authenticate with the secure service, relays requests to the service, and returns responses to the client. The user credentials remain secure in the server-side proxy page and thus, not visible to the client."

The following link:
http://help.arcgis.com/en/webapi/silverlight/apiref/ESRI.ArcGIS.Client.Toolkit.DataSources~ESRI.ArcG...
gives the following information:
Gets or sets the URL to a proxy service that brokers Web requests between the Silverlight client and a WMS service. Use a proxy service when the WMS service is not hosted on a site that provides a cross domain policy file (clientaccesspolicy.xml or crossdomain.xml). You can also use a proxy to convert png images to a bit-depth that supports transparency in Silverlight.
That is for the WmsLayer Class : ProxyUrl Property.

The following link:
http://help.arcgis.com/en/webapi/silverlight/apiref/ESRI.ArcGIS.Client~ESRI.ArcGIS.Client.Tasks.Task...
gives the following information:
"Gets or sets the URL to proxy the request through. "
That is for the ESRI.ArcGIS.Client.Tasks Namespace > TaskBase Class : ProxyURL Property


Please give more information on how to use the ProxyURL property. Which ProxyURL property is the correct one to use?

I have a Map UI Element which gets some REST layers from our ArcGIS server, and it gets the base map layer from ESRI.
I want to create a PNG or JPEG of the map to create a custom print page for our users.
Because that is a cross domain url, the WriteableBitMap object will not allow access to the pixels.

If I use the ProxyURL property on a layer, can I still add that layer to the other layers on the map?

Do I need to create my own proxy server? I ask that because SharpGIS stated, "to push the tiles through the proxy."

Please provide an example of "defining the ProxyURL property on a service layer."
0 Kudos
BabakSekandari1
Deactivated User
The information on the ProxyURL just states:
Use a proxy page to provide access to a secure service by defining the ProxyURL property on a service layer. The proxy page stores credentials to authenticate with the secure service, relays requests to the service, and returns responses to the client. The user credentials remain secure in the server-side proxy page and thus, not visible to the client.

How does one do that?
What is an example of doing that?
How does one create a proxy page?
How does one define the ProxyURL property on a service layer?
Do extra steps have to be taken to store the credentials to authenticate?
How does one make the proxy page relay requests to the service and then return responses to the client?
0 Kudos
BabakSekandari1
Deactivated User
I attempted the following:
<esri:ArcGISTiledMapServiceLayer  
ID="StreetMap"
ProxyURL="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"
Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" />

And I got this error:

Message: System.Runtime.Serialization.SerializationException: 'html> <head>
<meta http-equiv='X-UA-Compatible" content="IE=7" />
<title>...

I tried it without the URL parameter and I got this error:
System.ArgumentNullException: Value cannot be null
Parameter name: URL
0 Kudos
PreetiMaske
Esri Regular Contributor
Open Proxy.ashx and look for line:
req.ContentType = "application/x-www-form-urlencoded";

REPLACE ABOVE LINE WITH THE FOLLOWING LINE.
req.ContentType = context.Request.Headers["Content-Type"];

Hope that helps!
0 Kudos