Incomplete image using GetMap()

Topics: General Topics
Jul 5, 2013 at 2:59 PM
Hi!

I need to save tile layer Bing map as an image in good resolution (for example 2500x2500). I tried several methods, but result is practically the same. Image is only partly saved. The resulting image differs each time, sometimes it is fully saved. Image (The black part was transparent before I process the image through IrfanView batch to reduce the size for hosting)
  1. Method:
Size tmp_size = map.Size;
map.Size = new System.Drawing.Size(2500, 2500); //Set output size         
Image map_image = map.GetMap();
map_image.Save(saveFileDialog1.FileName);
map.Size = tmp_size;         
  1. Method:
Size tmp_size = mapBox1.Size;
mapBox1.Size = new System.Drawing.Size(2500, 2500); //Set output size         
map.Size = mapBox1.Size;
Image map_image = map.GetMap();
map_image.Save(saveFileDialog1.FileName);
mapBox1.Size = tmp_size;         
Using BruTile.dll v 0.7.5.0
SharpMap.dll v 1.0.0.0

CPU i5-3570 @3.4Ghz 3.8Ghz
RAM 4GB

Any ideas? Thank you in advance.
Coordinator
Jul 5, 2013 at 6:39 PM
What type of layer do you use?
If you want the full bing layer rendered, you cannot use AsyncTileLayer.
Jul 8, 2013 at 6:04 AM
Edited Jul 8, 2013 at 6:14 AM
I am using TileLayer
BingRequest br = new BingRequest(BruTile.Web.BingRequest.UrlBing, "", BingMapType.Hybrid);
BingTileSource bts = new BingTileSource(br);
TileLayer tl3 = new TileLayer(bts, "TileLayer - " + BingMapType.Hybrid.ToString(), Color.Transparent, true, "Cache_brutile");

map.Layers.Add(tl3); 
I have noticed that when I change mapBox1 size, it is get zoomed. Zoom value doesn't change, but pixel width, pixel height values change. Often map disappears and some time is required while image is saved and then map appears normal again.
Coordinator
Jul 8, 2013 at 7:16 AM
I see you are using file caching, that is good. Maybe you could use an absolute path to your directory?
The more often you request tiles for an image, the more complete it should be.

You may want to
  • increase BruTile.Web.RequestHelper.TimeOut value.
  • request tiles for smaller images and stitch them together
Jul 8, 2013 at 7:53 AM
I tried to use the absolute path to my cache dictionary and increase TimeOut value from 10000 to 60000 ( I suppose it is 60 seconds now), but it saves image faster than 60 sec and still there is while tiles in the image in random places.

As far as I understand then when I am resizing the mapbox or map then tiles are automatically stitched to get mapbox or map filled, so I don't understand why there is some white tiles.
Coordinator
Jul 8, 2013 at 8:33 AM
I don't know how many tiles you need to build such an image, but the Bing maps server might consider it being to much for the purpose it was set up for.
My hope is that if you request fewer tiles within an amount of time the bing server is more willing to serve your requests
Jul 8, 2013 at 8:46 AM
It is not the server problem, because I have cached tiles on my PC's SSD drive, so I can even disconnect the LAN cable and I can get image with random white tiles on the image for the same location on mapbox.
Coordinator
Jul 8, 2013 at 8:56 AM
Could you convert your code to a unittest and post it along an issue about your problem? Thanks
Jul 8, 2013 at 9:15 AM
Honestly I don't know how to do that.
Coordinator
Jul 8, 2013 at 1:19 PM
Have a look at the UnitTests project. Basically you create s.th. like this.
[NUnit.Framework.TestFixture]
public class TileLayerIssues
{
    [Test, Description("Map.GetMap() returns incomplete image")]
    public void TestIncompleteImage()
    {
        var br = new BingRequest(BruTile.Web.BingRequest.UrlBing, "", BingMapType.Hybrid);
        var bts = new BingTileSource(br);
        var tl = new TileLayer(bts, "TileLayer - " + BingMapType.Hybrid.ToString(), Color.Transparent, true, "Cache_brutile");
        var m = new SharpMap.Map(new Size(2500, 2500))
        m.Layers.Add(tl)
        var mi = m.GetMap();
        mi.Save("tmp.bmp",  ImageFormat.Bmp)
    }
}
Writing these lines, you did not add your tile layer to the Map.BackgroundLayers collection?
Jul 8, 2013 at 1:45 PM
Is your example similar to this article?

map.BackgroundLayers.Count=0 while map.Layers.Count =1

What should I do next?
Coordinator
Jul 8, 2013 at 1:50 PM
kostjadetected wrote:
Is your example similar to this article?
yes, except that we use NUnit instead of Microsoft's own unit testing framework. Have a look at the UnitTests project.
Jul 8, 2013 at 2:01 PM
Ok, I have studied your example. What more should I add to your example? Sorry I don't understand. I have aprox 20000-30000 code lines in my project.
Coordinator
Jul 8, 2013 at 2:21 PM
e.g. the viewport you are trying to get the image from (map.ZoomToBox())
Jul 9, 2013 at 6:07 AM
[NUnit.Framework.TestFixture]
public class TileLayerIssues
{
    [Test, Description("Map.GetMap() returns incomplete image")]
    public void TestIncompleteImage()
    {
        SharpMap.Map map = new SharpMap.Map();            
        map.Size = mapBox1.Size;
        mapBox1.Map = map;         
        var br = new BingRequest(BruTile.Web.BingRequest.UrlBing, "", BingMapType.Hybrid);
        var bts = new BingTileSource(br);
        var tl = new TileLayer(bts, "TileLayer - " + BingMapType.Hybrid.ToString(), Color.Transparent, true, @"C:\Users\User\Desktop\UA v64\UA Form\UA Form\bin\Debug\Cache_brutile"");
        m.Layers.Add(tl);
        map.ZoomToBox(new Envelope(last_session_xmin, last_session_xmax, last_session_ymin, last_session_ymax));
        mapBox1.Refresh();
        var m = new SharpMap.Map(new Size(2500, 2500));
        var image = m.GetMap();
        image.Save("tmp.png");
        mapBox1.Refresh();
        MessageBox.Show("Map saved", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
}
Coordinator
Jul 9, 2013 at 6:24 AM
We need some sample values for last_session_xmin, last_session_xmax, last_session_ymin, last_session_ymax
Jul 9, 2013 at 6:29 AM
xmin=-239839.49199841652
xmax=78451.759683380573
ymin=-37033.0152981899
ymax=106723.52879865949
Coordinator
Jul 9, 2013 at 7:06 AM
I'm sorry, I cannot reproduce your issue. The picture I get is complete.
Maybe you should install BruTile 0.7.4, that is the one SharpMap was linked against.
Jul 9, 2013 at 7:28 AM
I tried 0.7.4 as well, the same issue but less often. Interesting thing is that when I reopen the last session location and save that image, it saves complete.
Editor
Jul 9, 2013 at 8:18 AM
Is there not a layer loaded event that you can hook into? Then call your export routine in there rather than in the same block as the loading?
Jul 9, 2013 at 8:24 AM
Actually exportation is on button click in my original project, so layer is loaded on form load.
Coordinator
Jul 9, 2013 at 8:37 AM
kostjadetected wrote:
Interesting thing is that when I reopen the last session location and save that image, it saves complete.
If you reopen the last session, the images are taken from the file cache and not from the server. Do you have a good internet connection?
Jul 9, 2013 at 8:41 AM
As I wrote yesterday I checked this without internet and I got random incomplete tiles for same location every time. But yesterday I tried it with BruTile 0.7.5, I will check it now with 0.7.4
Jul 9, 2013 at 9:35 AM
Image is still incomplete with 0.7.4, but when I save the same location again, then it is complete. I change BruTile.Web.RequestHelper.Timeout value to 60000 and it accomplish saving process much quicker than 60seconds then why image remain incomplete for the first attempt of saving?
Coordinator
Jul 9, 2013 at 10:50 AM
There seems to be an issue within BruTile, that causes it to stop getting tiles from the online service after it has gotten a couple of timeout exceptions.
Could you try setting BruTile.Web.RequestHelper.Timout prior to requesting any tile, e.g. on applications startup?
Jul 9, 2013 at 10:53 AM
I have already added it on form load event as first function to do even before layer is added.
Coordinator
Jul 9, 2013 at 10:55 AM
kostjadetected wrote:
I have already added it on form load event as first function to do even before layer is added.
You are not using BruTile anywhere else in your application?
Jul 9, 2013 at 10:57 AM
No I don't, it is used only in one form.
Coordinator
Jul 9, 2013 at 3:02 PM
Hi,

You write that you are using SharpMap.dll v 1.0.0.0

Please upgrade to SharpMap 1.0 RC3,

In RC3 there is a fix for tiles getting swapped out of the MemoryCache before getting drawn if a large amount of tiles are requested for a GetMap operation.
That sounds like it could be your problem.
Jul 11, 2013 at 2:03 PM
I tried 1.0 RC3. So far looks that problem is solved. There were few cases when image was completely empty, but after saving the same location it gets completed. Thank you all for your help.