How to get the Image from the MXD using ArcObjects

First thanks to all the people that helped me with ArcObjects. I have a project using Silverlight that need to populate the TOC with the image in each layer. All the symbology is stored on the Map Service. Silverlight uses the REST layer to communication with the ArcGIS server, because of that and the rest layer does not return the symbology of the layer itself I had to create an ASP.NET application to extend the Rest API to be able to write my own C# to get the images.

image

Now is important to remember that you want to cache the image on the server as you do not want to generate the image every time Silverlight calls the server to request the image. So you’ll see that I save the Bitmap and then the server will send the location of the Bitmap back to the Silverlight client.

The main part is to get access to the mxd itself, and then to go over the layers and get the the ISymbol:

            Init();

            ESRI.ArcGIS.Carto.IMap map = null;

            ESRI.ArcGIS.Carto.IMapDocument tempDoc = new ESRI.ArcGIS.Carto.MapDocument();
            tempDoc.Open(@"\\Computer\Template.mxd", "");

            map = tempDoc.get_Map(0);

            for (int i = 0; i < map.LayerCount; i++)
            {
                IFeatureLayer layer = map.get_Layer(i) as IFeatureLayer;
                if (layer is IGeoFeatureLayer)
                {
                    IGeoFeatureLayer layerSymbol = layer as IGeoFeatureLayer;
                    Bitmap image = GetSymbol(layerSymbol) as Bitmap;

                    string ID = GetID(layer);

                    image.Save("c:\\temp\\symbol\\" + ID + ".png", System.Drawing.Imaging.ImageFormat.Png);
                }
                else
                {
                    ILayer genericLayer = map.get_Layer(i) as ILayer;
                    IGroupLayer groupLayer = genericLayer as IGroupLayer;
                    if (groupLayer != null)
                    {
                        ICompositeLayer pCompositelayer = groupLayer as ICompositeLayer;
                        if (pCompositelayer != null)
                        {
                            for (int t = 0; t < pCompositelayer.Count; t++)
                            {
                                IFeatureLayer insideLayer = pCompositelayer.get_Layer(t) as IFeatureLayer;
                                if (insideLayer is IGeoFeatureLayer)
                                {
                                    IGeoFeatureLayer layerSymbol = insideLayer as IGeoFeatureLayer;
                                    Bitmap image = GetSymbol(layerSymbol) as Bitmap;

                                    string ID = GetID(insideLayer);

                                    image.Save("c:\\temp\\symbol\\" + ID + ".png", System.Drawing.Imaging.ImageFormat.Png);
                                }
                            }
                        }
                    }
                }
            }

            tempDoc.Close();

The magic happens at the method GetSymbol where there are 2 types of Layers.

        private static Image GetSymbol(IGeoFeatureLayer geoLayer)
        {
            Image image = null;
            IFeatureRenderer render = geoLayer.Renderer;
            ESRI.ArcGIS.Display.ISymbol symbol = null;

            if (render is ISimpleRenderer)
            {
                ISimpleRenderer simple = render as ISimpleRenderer;
                symbol = simple.Symbol;
            }
            else if (render is IClassBreaksRenderer)
            {
                IClassBreaksRenderer breakRender = render as IClassBreaksRenderer;
                symbol = breakRender.get_Symbol(0);
            }

            if (symbol != null)
            {
                Size size = new Size(20, 20);
                
                image = PointSymbolToImage(symbol, size);
            }

            return image;
        }

The method PointSymbolToImage is the one that converts the ISymbol to a Image

        private static Image PointSymbolToImage(ISymbol symbol, Size imageSize)
        {
            double x = imageSize.Width / 2;
            double y = (imageSize.Height - 1) / 2;

            IPoint point = new PointClass();
            point.PutCoords(x, y);

            Bitmap bmp = new Bitmap(imageSize.Width, imageSize.Height);
            Graphics g = Graphics.FromImage(bmp);

            symbol.SetupDC(g.GetHdc().ToInt32(), null);
            try { symbol.Draw(point); }
            catch { }
            symbol.ResetDC();

            g.Dispose();
            
            return (Image)bmp;
        }

This is pretty much it, with that you’ll be able to generate the images from the symbology.

Cheers

Al

Published Thursday, May 07, 2009 10:24 PM by albertpascual

Comments

# re: How to get the Image from the MXD using ArcObjects

Tuesday, January 17, 2012 3:56 PM by Ming

Great article!

I need to do something similar, but I need to create an image from list of lat/long that retrieved from Oracle Database. Is it possible to an image without the MXD file?

# re: How to get the Image from the MXD using ArcObjects

Friday, March 23, 2012 11:45 AM by Александр

Очень полезный пример. Огромное спасибо!

Leave a Comment

(required) 
(required) 
(optional)
(required)