ThinkGeo.com    |     Documentation    |     Premium Support

GetMapCore returning tiles with 'outline'

Hi there,

We have recently seen some ‘lines’ in our maps, and after a bit of time debugging the issue this is what we’ve found:



 - Depending on the tile colors, this effect can be almost imperceptible. For light shades of gray, it is quite visible;

 - What is happening is that the method  ‘GetMapCore’ is returning tiles with the first row and column ‘modified’.

   The colors are normally slightly darker than the rest of the tile. 



- The issue only happens when we have a ‘FileBitmapTileCache’ in ‘MapConfiguration’  with the pre-crunched map. 

If a TileCache is not present, the tiles are created on the fly and they are perfect.



With a bit of research, we’ve found this stackOverflow thread which we believe it is the root cause of the issue:

stackoverflow.com/questions/…resized-im



Is there any way around this?



Please find in attach the screenshot from the browser loading the map with the ‘outlined’ tiles as well as a sample of the response tiles (side by side) coming from GetMapCore.









Thanks,

Eduardo.


Hi Eduardo, 
  
 Thanks for let us know your question. 
  
 Sorry I haven’t produce your issue local succeed. 
  
 I need more detail information for reproduce that, so please let me know your dll version, what is your client side(winform or web). If you can reproduce that in our HowDoISample, that’s should be more helpful. 
  
 I tested it use our latest dll package, use the winform version sample as client side. My environment is win7 x64, vs2010 and dotnet 4.0. 
  
 As below is my modified code in DisplayASimpleMap for reproduce that: 
  
 void DisplayASimpleMap_Load(object sender, EventArgs e)
        {
            // Setup the map control            
            winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
            winformsMap1.CurrentExtent = new RectangleShape(-126.826171875, 57.104766845702, -70.83984375, 18.960235595702);
            winformsMap1.BackgroundOverlay.BackgroundBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 174, 174, 174));            

            // Create the TiledWmsOverlay and pass in the URL to the server
            // The ActiveLayerName needs to match the value you return in the GetNameCore of the plugin
            TiledWmsOverlay tiledWmsOverlay = new TiledWmsOverlay(new Uri(“localhost:62626/WmsHandler.axd”));
            tiledWmsOverlay.TileCache = new FileBitmapTileCache(@“D:\tmp\cache”, “round1”);
            tiledWmsOverlay.ActiveLayerNames.Add(“Display A Simple Map”);
            tiledWmsOverlay.ActiveStyleNames.Add(“DEFAULT”);

            // Add the overlay to the map
            winformsMap1.Overlays.Add(“TiledWmsOverlay”, tiledWmsOverlay);

            winformsMap1.Refresh();
        }
 
  
 Regards, 
  
 Don

Hi Don,



Your sample does not use the method “GetMapCore”. This is the method inside “WmsLayerPlugin” returning the tiles with borders.

I’m downloading the ThinkGeoProductCentre demo and will try to get a sample going with the issue reproed.

Hi Don,

How do I send the sample code to you?

The zipped folder with the code + my tiles has 14Mb and I cannot upload it here?



Thanks,

Eduardo.

Hi Eduardo, 
  
 I haven’t modified the GetMapCore because it looks the code in it don’t need be modified in our HowDoISamples. 
  
 If your sample is about 14mb, please zip that and sent it to our mailbox: forumsupport@thinkgeo.com 
  
 Here is the detail about it: wiki.thinkgeo.com/wiki/Map_Suite_Sending_Data_to_Support 
  
 Regards, 
  
 Don

Hi Don,



Just sent the e-mail with the attachment and all required information on how to reproduce the issue.





The change I’ve made was on WorldMapPlugin.cs on the following method below.






protected override Bitmap GetMapCore(GetMapRequest getMapRequest, MapConfiguration mapConfiguration, HttpContext context)
        {
            string imageFormat = context.Request.QueryString[“Format”];
            string userName = context.Request.QueryString[“UserName”];



            BackgroundLayer backgroundLayer = mapConfiguration.Layers[“Background”] as BackgroundLayer;
            if (backgroundLayer != null) backgroundLayer.BackgroundBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 153, 179, 204));



            Bitmap mapImage = null;
            bool userValidated = SecurityHelper.AuthenticateUserRequest(context);
            ShapeFileFeatureLayer layer = mapConfiguration.Layers[“WorldLayer”] as ShapeFileFeatureLayer;



            //---------------------------------------------------------------------------
            var baseDir = “C:\Sample Templates\WorldMapWmsService\”;
                        
            var TilesPath = baseDir + “Tiles”;
            var savedTilePath = baseDir + “SavedTile\SavedTile.png”;
            var fileCache = new FileBitmapTileCache(TilesPath);


            fileCache.TileAccessMode = TileAccessMode.ReadOnly;


            fileCache.CacheId = “tilecache”;
            mapConfiguration.TileCache = fileCache;
            //---------------------------------------------------------------------------
            


            if (layer != null)
            {
               layer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = GetAreaStyleByUserName(userName, userValidated);
                mapImage = base.GetMapCore(getMapRequest, mapConfiguration, context);
            }
            if (!userValidated)


             {
                 mapImage = mapImage ?? base.GetMapCore(getMapRequest, mapConfiguration, context);
                 PointShape centerPoint = getMapRequest.BoundingBox.GetCenterPoint();
                 GdiPlusGeoCanvas canvas = new GdiPlusGeoCanvas();
                 canvas.BeginDrawing(mapImage, getMapRequest.BoundingBox, GetGeographyUnit(getMapRequest.Crs));
                 canvas.DrawTextWithWorldCoordinate(“Your watermark here”, new GeoFont(“Arial”, 11, DrawingFontStyles.Bold), new GeoSolidBrush(new GeoColor(100, GeoColor.StandardColors.Purple)), centerPoint.X, centerPoint.Y, DrawingLevel.LevelOne);
                 canvas.EndDrawing();
             }
            //---------------------------------------------------------------------------


            mapImage.Save(savedTilePath);
            //---------------------------------------------------------------------------
            return mapImage;


        }



The simplest and most isolated way I’ve reproduced the issue was launching the app and then copying and pasting the following URI on the browser:



localhost:52289/WmsHandler.axd?LAYERS=WorldMap&STYLES=DEFAULT&FORMAT=image%2Fpng&DISPLAY=small1&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&

SRS=EPSG%3A4326&BBOX=43.06183431486,60.225316987559,47.614116647816,64.777599320515&WIDTH=256&HEIGHT=256



Or, if you setup IIS and point a ‘RandomWebsite’ to the sourceCode:



localhost/RandomWebsite/WmsHandler.axd?LAYERS=WorldMap&STYLES=DEFAULT&FORMAT=image%2Fpng&DISPLAY=small1&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&

SRS=EPSG%3A4326&BBOX=43.06183431486,60.225316987559,47.614116647816,64.777599320515&WIDTH=256&HEIGHT=256






This will make a request for a tile that always comes back with the “outline”. 
I’m saving this tile in  “SavedTile\SavedTile.png” but if you use chrome, you can also copy and paste the image from the browser into Paint multiple times 

and check the lines at the bottom and at the right hand side.







Thanks a lot for your help.



Eduardo.




Hi Eduardo, 
  
 Thanks for your detail information and email, today I haven’t get time to look into it, I will focus on it next work day. 
  
 Any update I will let you know. 
  
 Regards, 
  
 Don

Thanks Don,



Looking forward to the results of your investigation.

My guess is that it’s got something to do with this:

stackoverflow.com/questions/…resized-im



Thanks,

Eduardo.

Hi Eduardo, 
  
 Sorry for the delay as Ethan was out office today, seems like we were still unable to reproduce the problem, I just copied the code in the "World Map Kit Server" source code, and run the application, however all works fine, I will talk with Ethan tomorrow and dig into further to see the problem, if you have any details, please feel free to let us know. 
  
 Thanks, 
 Johnny

Hi Johnny,



Sorry if I’m a bit repetitive here, but just copying the code will not reproduce the issue.

You have to force the code to search through the tileCache and combine them to produce the requested tiles with a specific zoomLevel and boundingBox.



So if you do not have the tile cache, issue does not happen. If you do not have the proper boundingBox in the request, it does not happen.

It might seem like this is an isolated and “hard to reproduce” problem, but in our application it happens all the time as we are zooming in and out constantly, getting the tiles from the tileCache.



So please, make sure you have the tileCache folder in the proper place (as provided in the attached file on previous e-mails) and you make the proper request for the tile. If you just run the sample code provided, this is the request for the tile:



localhost:52289/WmsHandler.axd?LAYERS=WorldMap&STYLES=DEFAULT&FORMAT=image%2Fpng&DISPLAY=small1&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&

SRS=EPSG%3A4326&BBOX=43.06183431486,60.225316987559,47.614116647816,64.777599320515&WIDTH=256&HEIGHT=256



This is guaranteed to give you a tile with borders, and the easiest way to make them more visible is copying and pasting the tile multiple times as shown on previous message.





Hope this can help. Let me know how you go with it.





Thanks,

Eduardo






Any updates Johnny, Don?

Hi Eduardo,



Sorry for the delay as we are busy with a release 8.0.0.160 these day, including 4 new products(iOSEdition, AndroidEdition, Osm WorldMapKit SDK and WebAPI Edition) these days, seems like I was still unable to reproduce the mentioned problem, even though I request the same extent and with the TileCache. Can you help me on following questions?



1. How did you create these tile cached images which will be read by the configured TileCache? From a TileCacheGenerator or created on the fly?

2. Would you please share your test project via forumsupport@thinkgeo.com, then we can do some tests locally to determine the problem? If it’s a big project, you can contact support@thinkgeo.com for a FTP address.



Here attached is the plugin source code that I used for test, could you please do a check for us?



Thanks,

Johnny 

WorldMapKitPlugin.zip (2.11 KB)

Hi Johnny,



Thanks for your reply. 

On your questions:



1) TileCache was created using the cache generator tool. I’ve inspected all tiles and they do not have the borders. My understanding is that when then we make a request for a tile that does not match exactly to a tile in the cache, the “GetMapCore” method will use the cached tiles to create the requested tile on the fly. See image below from my tests:







Hope that answers question 1.





2) I have already shared the project via forumsupport@thinkgeo.com. Please look for the email shown below:











Please let me know if you have received the email with the project. There are instructions in the email with exact steps on how to reproduce the issue. 

In addition, can you send to me the tile which was created by the modified code and saved as “SavedTile.png”? the lines are ONLY visible when you place tiles side by side, or in this case that we are generating only one tile you should copy and paste it multiple times side by side on MS paint.









Let me know how that goes.





Thanks,

Eduardo.


Hi Eduardo,



I followed your guide to do a test and still can’t see the “outline”. Please check the test video and let us know where we are missing?

screencast.com/t/teSLdnOXr



Another thing is we didn’t receive your email with your samples and steps. would you please check it? or contact with sales@thinkgeo.com and they will setup a ftp account for you. Here is the guide on how to upload data wiki.thinkgeo.com/wiki/Map_S…to_Support




Thanks,

Troy

Hi Troy,



I’ve sent the email again today with an attachment containing a zip file.



Subject: "Re-sending e-mail regarding GetMapCore returning tiles with ‘outline’  (thinkgeo.com/forums/MapSuite/tabid/143/aft/12302/Default.aspx)"



The zip file contains the modified VS project plus the crunched tileCache with a sample of the map which causes the issue.

All instructions and steps on how to reproduce are in the e-mail.



I saw your video and checked that you did not use the same map I did. 

The issue does NOT happen with all maps we have. Only some maps come up with the lines, and our guess is that it is color dependant.

In the first post of this thread there is more info on what we think it is happening.



So please, can you unzip the file and do the same steps you did in your video, but with the tileCache I sent to you and with the sourceCode I sent to you?

I believe that this is guaranteed to produce the issue. 

In addition, copy and paste the tile returned from the request multiple times in MSPaint as this aids the visibility of the lines, as described in previous posts.



Many thanks, hope you guys get a clean repro now.



Eduardo.

Hi Eduardo,



Thanks for all your help on this thread, but seems like we were still unable to reproduce the problem, would you please check the video shown at  screencast.com/t/OVxujhTPIU to see if there is anything wrong with it? also if the problem persists, I guess should be something wrong with the pre-generated tile cache, would you please try the attached tile cache generator?



Thanks,

Johnny

ServicesEditionSample_CacheGenerator_CS_120619.zip (19.2 KB)

Hi,



Please see attached video with issue repro. It’s a zipped self-Play exe file.



This is the request I’ve used to get the tile:



localhost:52289/WmsHandler.axd?LAYERS=WorldMap&STYLES=DEFAULT&FORMAT=image%2Fpng&DISPLAY=small1&SERVICE=WMS&VERSION=1.1.1&

REQUEST=GetMap&SRS=EPSG%3A4326&BBOX=43.06183431486,60.225316987559,47.614116647816,64.777599320515&WIDTH=256&HEIGHT=256



From your sample code which is already working, make the same request from the browser and copy and paste the response tile on paint.

The issue is NOT on the cacheGenerator, as the tiles created by this tool are fine with no borders.

The issue occurs when the function ’ base.GetMapCore(getMapRequest, mapConfiguration, context)’ is called and uses the existing tiles (from the cacheGenerator tool) to create a new one.

003_002_001_capture.zip (775 KB)

Hi Eduardo,



Thanks for the video, I recreated your finally. But I found some thing that made me suspect if this is a bug.

During my test, I cached some tile levels tiles in advanced and then I sent some requests in browser:



localhost:62626/WmsHandler.axd?LAYERS=Display%2520A%2520Simple%2520Map&STYLES=DEFAULT&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=

GetMap&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=-112.5,22.5,-90,45&WIDTH=256&HEIGHT=256



This url is the image url I copy from the plugin map view. Then I did add an offset by changing its bbox value with:

localhost:62626/WmsHandler.axd?LAYERS=Display%2520A%2520Simple%2520Map&STYLES=DEFAULT&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=

GetMap&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=-111.5,22.5,-91,45&WIDTH=256&HEIGHT=256



With the second url, I copy the returned image to paint software, then I can see the border on left and top side, which is exactly like yours. 

I also change the bbox as yours (43.06183431486,60.225316987559,47.614116647816,64.777599320515), still can see the border. Based on above test, 

I believed this might be a bug from map suite, However, when I debug the “issue” url by setting a breakpoint at GetMapCore method from plugin, then I save the returned bitmap at disk, I found this bitmap is fine without the border.  Besides, I can only see the border on paint, but never see them in the map no matter how I pan or zoom.



Then, I did another test by changing the image format from PNG to JPEG with the second url, at this time, I never see the border after copy to paint.

localhost:62626/WmsHandler.axd?LAYERS=Display%2520A%2520Simple%2520Map&STYLES=DEFAULT&FORMAT=image%2FJPEG&SERVICE=WMS&VERSION=1.1.1&REQUEST=

GetMap&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=-111.5,22.5,-91,45&WIDTH=256&HEIGHT=256



So, would you please try to change the image format as JPEG to see if the borders are still there? I will keep looking for this issue anyway and let us know if you get any further information.



I also attached my test video here, it includes the above all cases, I think you can have a review. screencast.com/t/njAruM2tf9wX



Hope it helps.

Thanks,

Troy

Hi Troy,



Thanks for the investigation. I’m glad you were able to repro the issue.

I’ve consulted the user experience people on our group and unfortunately using JPEG is not an option for us. They’ve got plenty of reasons for that.



I’ve retested the scenario where we make a request for a PNG tile and compared the image saved from:

 1- chrome [SavedFromChrome.png];

 2- the code (line: mapImage.Save(savedTilePath) ); [SavedFromCode.png]

 3- and breakpointing just after the line “mapImage = base.GetMapCore(getMapRequest, mapConfiguration, context);”  and saving it via “quickWatch window” as you did in your video [SavedFromDebug.png].



Unfortunately all of them had the outline and were exactly the same, apart from the watermark which gets added later:



chrome                                                               debug                                                          code

  







The lines are NOT visible when we look at the individual tiles, as you can see above.

But copied and pasted on paint, we can see the lines are brighter this time (instead of darker) In our application, they are visible when the tiles are side-by-side, all the time. 







The fact that you never saw them in the map when you pan and zoom, is because your application always “snap” the zoom level to one of the predefined discrete levels. In our application, we do not restrict the zoom levels to discrete levels (e.g.: the zoom can be somewhere between level 3 and 4). 

The main effect of that is that when we “release” the pinch gesture at the end of the zoom, the map will remain exactly at that zoom level. As a result, the requested tile might not match any of the existing tiles in the cache and the code will need to render the requested tile on the fly, based on the existing tiles in the cache. proof of that is the image below, where I’ve manually modified one tile in the cache and checked that the response tile “included” the cached tile but also needed bits and pieces of other cached tiles:







In your sample app, when you release the pinch the map will snap back to the closest discrete zoom level. 

As a result, you already have the exact cached tile which matches the request. In the example image above, the request will exactly match the red tile. 

That means that there is no internal resizing needed, and that’s why you will not get the lines in this scenario.



And that’s my theory… When resizing is needed, we might get the lines. But I do not know what’s inside the getMapCore function.

My guess is that the issue is similar to what these people found:



stackoverflow.com/questions/4772273/interpolationmode-highqualitybicubic-introducing-artefacts-on-edge-of-resized-im





That’s all the extra info I have on this.

Hope this can help.



Thanks,



Eduardo.


Hi Eduardo,



Thanks for the investigates and they helps us a lot. I made some changes on WmsServiceEdition and tested it following your case without the outline anymore. would you please try the latest development WmsServiceEdition dll package(8.0.182.0, still may be building now)

Hope the change will fix the issue and let us know if fixed.



Btw, does using JPEG can fix the issue? I am just wondering if this is an option.

Any questions, please let us know.

Thanks,

Troy