/// <summary> /// Renders the map to an image /// </summary> /// <returns></returns> public virtual Image Render() { // DateTime startTime = DateTime.Now; // Used when logging Rendering time of Map if (Size.IsEmpty) { return(null); // nothing to render } if (MapRendering != null) { MapRendering(null); } if (image != null && (Size.Width != image.Width || Size.Height != image.Height)) // re-create only when it is required { image.Dispose(); ResourceMonitor.OnResourceDeallocated(this, image); image = null; } if (image == null) { image = new Bitmap(Size.Width, Size.Height, PixelFormat.Format32bppPArgb); ResourceMonitor.OnResourceAllocated(this, image); } if (rendering) { return(null); } rendering = true; // TODO: draw using multiple threads /* Action<int> renderLayer = delegate(int i) * { * if (Layers[i].RenderRequired) * { * Layers[i].Render(); * } * }; * Parallel.For(0, Layers.Count, renderLayer); */ var visibleLayers = GetAllMapLayers(layers, true, true).OrderByDescending(l => l.RenderOrder).ToArray(); // draw decoration layers on top var gridVectorLayer = GetGridLayer(); if (gridVectorLayer != null) { visibleLayers = visibleLayers.Concat(new[] { gridVectorLayer }).ToArray(); } // merge all layer bitmaps var g = Graphics.FromImage(image); g.Clear(BackColor); foreach (var layer in visibleLayers) { if (!(layer.MaxVisible >= Zoom) || !(layer.MinVisible < Zoom)) { continue; } if (layer.RenderRequired || layer.Image == null) { layer.Render(); } if (layer.Image == null) { continue; } if (Math.Abs(layer.Opacity - 1.0) > 0.0000001) { var srcWidth = layer.Image.Width; var srcHeight = layer.Image.Height; g.DrawImage(layer.Image, new Rectangle(0, 0, srcWidth, srcHeight), 0, 0, srcWidth, srcHeight, GraphicsUnit.Pixel, CalculateOpacityImageAttributes(layer)); } else { g.DrawImage(layer.Image, 0, 0); } if (MapLayerRendered != null) { MapLayerRendered(g, layer); } if (layer.LastRenderDuration < 100) // do not keep Bitmap if it is very fast to render { layer.ClearImage(); } } g.Transform = MapTransform; g.PageUnit = GraphicsUnit.Pixel; if (MapRendered != null) { MapRendered(g); } g.Dispose(); foreach (var layer in Layers) { ClearLayerImages(layer); } // don't delete, enable when optimizing performance //double dt = (DateTime.Now - startTime).TotalMilliseconds; //log.DebugFormat("Map rendered in {0:F0} ms, size {1} x {2} px", dt, Size.Width, Size.Height); RenderRequired = false; rendering = false; return(Image); }
//private bool rendering; public virtual void Render() { /* * if (rendering) * { * return; // can be dangerous, rendering from two threads? * } * * rendering = true; * * try * { */ DateTime t = DateTime.Now; if (image != null && Map != null && (Map.Size.Width != image.Width || Map.Size.Height != image.Height)) // check if we need to re-create bitmap { ClearImage(); } if (Map == null) { if (image != null) { ClearImage(); } return; } if (image == null) { image = new Bitmap(Map.Size.Width, Map.Size.Height, PixelFormat.Format32bppPArgb); ResourceMonitor.OnResourceAllocated(this, image); } if (!Visible || MaxVisible < Map.Zoom || MinVisible > Map.Zoom) { return; } Graphics graphics = Graphics.FromImage(image); graphics.Transform = Map.MapTransform.Clone(); graphics.Clear(Color.Transparent); graphics.PageUnit = GraphicsUnit.Pixel; // call virtual implementation which renders layer OnRender(graphics, Map); if (LabelLayer != null && LabelLayer.Visible) { ((LabelLayer)LabelLayer).OnRender(graphics, map); } // fire event if (LayerRendered != null) { LayerRendered(this, graphics); } graphics.Dispose(); lastRenderDuration = (DateTime.Now - t).Milliseconds; /* * } * finally * { * rendering = false; * } */ RenderRequired = false; }