Select to view content in your preferred language

Saving Map in Image at specific extent

2768
1
12-02-2012 07:46 PM
shabbirsiddiqui2
Deactivated User
Hi,

I am using the function of snapshot to save the map in .PNG on button click at the time of submission of form.

I want this function to always save the map at specific extent, i use this function but not useful on single click.

Can any one guide me how to achieve this.


            private var quality:Number;
            private var logovis:Boolean;   
            private var sbvis:Boolean;
            private var zoomslidevis:Boolean;
            private var mapbg:uint;           
            private var ImageData:ByteArray;
            private var strEncodedString:String;       
            private var myEncoder:Base64Encoder = new Base64Encoder();

            protected function saveMapImage():void
            {
               
                // for zooming at at spacific location before saving(but not useful)
                var offset:int=300;
                var graphicsExtent:Extent;
                if (geom)
                {
                    graphicsExtent = geom.extent;
                    graphicsExtent.xmax=graphicsExtent.xmax+offset;
                    graphicsExtent.xmin=graphicsExtent.xmin-offset;
                    graphicsExtent.ymax=graphicsExtent.ymax+offset;
                    graphicsExtent.ymin=graphicsExtent.ymin-offset;
                    map.extent = graphicsExtent
                }
                // for saving the map..               
                map.infoWindow.hide();
                map.infoWindowContent = null;
                const encoder: JPEGEncoder = new JPEGEncoder(quality);
                map.scaleBarVisible=sbvis;
                map.zoomSliderVisible = zoomslidevis;
                map.opaqueBackground = mapbg;
                map.validateNow();
                const imageSnapshot:ImageSnapshot = ImageSnapshot.captureImage(map,0,encoder);
                map.scaleBarVisible=true;
                map.opaqueBackground = null;
                map.validateNow();
                ImageData = new ByteArray(); // To send through webservices to ASP.Net
                ImageData = imageSnapshot.data;   
            }
Tags (2)
0 Kudos
1 Reply
IvanBespalov
Frequent Contributor
You must handle map zoom end handler, or any other way handle (listen each layer update end) map fully updated after you change extent.

In this code look at: map.addEventListener(ZoomEvent.ZOOM_END, onMapZoomEnd);
If map extent not changed - call function exports map image.
If map extent changed - wait until map zoomed, call function exports map image.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
      xmlns:s="library://ns.adobe.com/flex/spark"
      xmlns:esri="http://www.esri.com/2008/ags" 
      xmlns:mx="library://ns.adobe.com/flex/mx">
 
 <!-- ArcGIS API for FLEX 3.0 -->
 <!-- Adobe SDK 4.6 -->
 
 <s:layout>
  <s:VerticalLayout paddingBottom="20"
        paddingLeft="20"
        paddingRight="20"
        paddingTop="20"/>
 </s:layout>
 
 <fx:Script>
  <![CDATA[
   import com.esri.ags.Graphic;
   import com.esri.ags.events.DrawEvent;
   import com.esri.ags.events.ZoomEvent;
   import com.esri.ags.geometry.Extent;
   import com.esri.ags.geometry.Geometry;
   import com.esri.ags.symbols.SimpleFillSymbol;
   import com.esri.ags.symbols.SimpleLineSymbol;
   
   import mx.collections.ArrayCollection;
   import mx.controls.Alert;
   import mx.core.UIComponent;
   import mx.events.CloseEvent;
   import mx.graphics.codec.PNGEncoder;
   
   private const FILE_NAME:String = "screen.png";
   
   private var mapExtent:Extent;
   private var bitmapData:BitmapData;   
   private var logoBitmapData:BitmapData;
   
   /**
    * Save as png clicked
    */
   protected function onSaveAsPng(event:MouseEvent):void
   {
    trace("Save button clicked");
    
    var printableExtent:Extent = getDrawnExtent();
    var readyToPrint:Boolean = true;
    
    if (printableExtent)
    {
     mapExtent = map.extent;
     map.extent = printableExtent;
     
     map.addEventListener(ZoomEvent.ZOOM_END, onMapZoomEnd);
    }
    else
    {
     saveMapImage();
    }
   }
   
   /**
    * Map zoom endend
    */
   protected function onMapZoomEnd(event:ZoomEvent):void
   {
    trace("Map zoom ended")
    map.removeEventListener(ZoomEvent.ZOOM_END, onMapZoomEnd);
    
    // user action needed (mouse click or key press) to call FileReference.save() method
    Alert.show("Do you really want to print?", "Ready to print", Alert.YES | Alert.NO, null, onAlertClose);
   }
   
   /**
    * Confirmation dialog close handler
    */
   protected function onAlertClose(event:CloseEvent):void
   {
    trace("Confirmation dialog closed");
    if (event.detail == Alert.YES)
    {
     saveMapImage();
    }
    else
    {
     // restore map state
     showComponents();
    }
   }
   
   /**
    * @private
    */
   private function saveMapImage():void
   {
    trace("Image export started");
    var fileReference:FileReference = new FileReference();
    
    hideComponents();
    
    // add listeners to show zoom slider after execution
    fileReference.addEventListener(Event.COMPLETE, fileSaveComplete);
    fileReference.addEventListener(Event.CANCEL, fileSaveCancel);
    
    try
    {
     var mapComponent:UIComponent = map as UIComponent;
     var exportData:BitmapData = getBitmapData(mapComponent);
     if (exportData)
     {
      // encode to PNG format
      var pngEncoder:PNGEncoder = new PNGEncoder();
      var byteArray:ByteArray = pngEncoder.encode(exportData);
      // open dialog box
      fileReference.save(byteArray, FILE_NAME);
      
      exportData = null;
      bitmapData = null;
     }
    }
    catch (ioError:IllegalOperationError)
    { 
     trace(ioError.getStackTrace());
    }
    catch (error:Error)
    { 
     trace(error.getStackTrace());
    }
   }
   
   /**
    * get bitmap data from IBitmapDrawable component
    */
   private function getBitmapData(uiComponent:UIComponent):BitmapData
   {
    try
    {
     // map image size
     var mapWidth:Number = uiComponent.width;
     var mapHeigth:Number = uiComponent.height;
     // get flash map bitmap data
     bitmapData = new BitmapData(mapWidth, mapHeigth);
     var matrix:Matrix = new Matrix();
     bitmapData.draw(uiComponent, matrix);
     
     // logo image size
     var logoWidth:Number = logo.width;
     var logoHeigth:Number = logo.height;
     // get logo bitmap data
     logoBitmapData = new BitmapData(logoWidth, logoHeigth);
     logoBitmapData.draw(logo, matrix);
     
     // calculate logo left-top position on map
     var logoX:Number = mapWidth - logoWidth - 10;
     var logoY:Number = 10;
     var point:Point = new Point(logoX, logoY);
     var mult:uint = 0x100; // 100% (256) RGBA channels multipliers
     bitmapData.merge(logoBitmapData, logoBitmapData.rect, point, mult, mult, mult, mult);
    }
    catch (error:Error)
    {
     trace(error.getStackTrace()); 
    }
    return bitmapData;
   }
   
   /**
    * Hide crosshair, logo, scalebar ...
    */
   private function hideComponents():void
   {
    // TODO: complete code
    
    // force UIComponent update/redraw
    map.validateNow();
   }
   
   /**
    * Restore hidden map components: crosshair, logo, scalebar ...
    * Restore map extent.
    */
   private function showComponents():void
   {
    // TODO: complete code
    
    // restore map extent
    map.extent = mapExtent;
    mapExtent = null;
   }
   
   /**
    * @return extent of drawn graphic
    */
   private function getDrawnExtent():Extent
   {
    var graphicProvider:ArrayCollection = graphicsLayer.graphicProvider as ArrayCollection;
    if (graphicProvider && graphicProvider.length > 0)
    {
     var graphic:Graphic = graphicProvider.getItemAt(0) as Graphic;
     var geometry:Geometry = graphic.geometry;
     
     graphicsLayer.clear();
     return geometry.extent;
    }
    else
    {
     trace("Graphics provider is empty");
     return null;
    }
   }
   
   /**
    * Draw button clicked
    */
   protected function onActivateDrawTool(event:MouseEvent):void
   {
    trace("Draw button clicked");
    
    graphicsLayer.clear();
    
    drawTool.activate(DrawTool.EXTENT);
    drawTool.fillSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL, 0, 0, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, 0, 1, 2));
   }
   
   /**
    * Drawing ended
    */
   protected function onDrawEnd(event:DrawEvent):void
   {
    trace("Drawing ended");
    
    drawTool.deactivate();
   }
   
   /**
    * File upload/download canceled by user
    */
   protected function fileSaveCancel(event:Event):void
   {
    showComponents();
   }
   
   /**
    * File upload/download completed
    */
   protected function fileSaveComplete(event:Event):void
   {
    showComponents();
   }
   
  ]]>
 </fx:Script>
 
 <fx:Declarations>
  <esri:DrawTool id="drawTool"
        drawEnd="onDrawEnd(event)"
        graphicsLayer="{graphicsLayer}"
        map="{map}"/>
 </fx:Declarations>
 
 <s:HGroup width="100%">
  
  <mx:Image id="logo"
      source="http://edn.esri.com/common/style/images/esriLogoSm.gif" />
  
  <s:Button label="Save as PNG"
      click="onSaveAsPng(event)" />
  
  <s:Button label="Draw printable Extent"
      click="onActivateDrawTool(event)" />
  
 </s:HGroup>
 
 <esri:Map id="map"> 
  
  <esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"/>
  
  <esri:GraphicsLayer id="graphicsLayer" />
  
 </esri:Map>
 
 
</s:Application>


Good luck
0 Kudos