ThinkGeo.com    |     Documentation    |     Premium Support

Unable to get 2048 pixel images w/ Google Maps for Business

Hello,



We are using ThinkGeo MVC 7 and need to create high-quality printed maps using Google as the base map layer, generating an image of our map and outputting to ActiveReports. We have a Google Maps for Business license which allows us to request 2048x2048 imagery. After overriding the Uri that ThinkGeo uses and injecting our ClientID,  generating a Signature, and then doing map.GetBitMap(width, height), we are only able to get either 1628x1628 (too small) or if we request higher we get 3255x3255 (which Google rejects and gives a much smaller image).



We also tried overriding the dimensions that ThinkGeo sends to Google, but then our other layers don’t match up correctly. What other options are there to increase the quality of imagery we get back?



A second questions, we also tried doing multiple tile, but each tile renders the logo which interferes with the map. Is there a way to use multitile, but only have the Google logo appear in the bottom of the bottom tile?



Thanks,

Chuck


Hi Chuck,



Since our business license is unavailable, would you please do a check the request uri by registering the CreatingRequest events on GoogleMapLayer and then check what’s the request image size? You can also do a simple test by replace request image size as 2048 in this event when calling the GetBitmap method, then check if the bitmap is fine. I just want to make sure this is related with the request image size, which is calculated.



For the second question, I am afraid there is no way to keep only one logo under multi tile. This is because under multi tile, each tile request are independent for google map service and it will give the logo for each tile image.



Any questions, please feel free to let us know.

Thanks,

Troy

Hi Troy,



The values that I mentioned in my original post were gathered by doing as you suggested. Those are the image sizes that ThinkGeo is requesting from Google. Some examples:

  - Map.GetBitMap(1000, 1000) -> ThinkGeo requests 814x814 from Google

  - Map.GetBitMap(2048, 2048) -> ThinkGeo reqeusts 1628x1628 from Google



I did try overriding the request as well and do get the correct image size from Google, but then our other layers do not match up correctly. The Tile size of the Google image is what we want, but the other layers are not proportionate to the Google layer.



Chuck

Hi Chuck,



We send your new dll in your other post, does that fix this issue? If the dll does work, we will apply it in our release dll package, so that you can always get a correct one in the future.



Thanks,

Troy

Hi Troy,



The dll did fix the layers not matching up correctly, but we are still not able to get tiles from Google close to the size we are requesting. We are struggling to understand the relationship between map size, tile size, GetBitMap size and the ThinkGeo tile size request to Google. Below are two samples using the latest build (currently 8.0.0.76):



The first sample we have everything set to 1000x1000 (map size, tile size, GetBitMap) and requested several images:


[0]: {http://maps.googleapis.com/maps/api/staticmap?center=40.894881,-100.719585&zoom=14&size=1175x1175&maptype=hybrid&format=jpg-baseline&sensor=false&client=}
[1]: {http://maps.googleapis.com/maps/api/staticmap?center=40.86384,-100.724649&zoom=16&size=978x978&maptype=hybrid&format=jpg-baseline&sensor=false&client=}
[2]: {http://maps.googleapis.com/maps/api/staticmap?center=40.862183,-100.739604&zoom=17&size=934x934&maptype=hybrid&format=jpg-baseline&sensor=false&client=}
[3]: {http://maps.googleapis.com/maps/api/staticmap?center=40.923924,-100.706456&zoom=16&size=939x939&maptype=hybrid&format=jpg-baseline&sensor=false&client=}
[4]: {http://maps.googleapis.com/maps/api/staticmap?center=40.920054,-100.730473&zoom=17&size=890x890&maptype=hybrid&format=jpg-baseline&sensor=false&client=}
[5]: {http://maps.googleapis.com/maps/api/staticmap?center=40.909075,-100.739925&zoom=16&size=906x906&maptype=hybrid&format=jpg-baseline&sensor=false&client=}



The second one we request 1600x1600 and get very different tile requests to Google:


[0]: {http://maps.googleapis.com/maps/api/staticmap?center=40.894881,-100.719585&zoom=15&size=2350x2350&maptype=hybrid&format=jpg-baseline&sensor=false&client=}
[1]: {http://maps.googleapis.com/maps/api/staticmap?center=40.86384,-100.724649&zoom=17&size=1956x1956&maptype=hybrid&format=jpg-baseline&sensor=false&client=}
[2]: {http://maps.googleapis.com/maps/api/staticmap?center=40.862183,-100.739604&zoom=18&size=1868x1868&maptype=hybrid&format=jpg-baseline&sensor=false&client=}
[3]: {http://maps.googleapis.com/maps/api/staticmap?center=40.923924,-100.706456&zoom=17&size=1877x1877&maptype=hybrid&format=jpg-baseline&sensor=false&client=}
[4]: {http://maps.googleapis.com/maps/api/staticmap?center=40.920054,-100.730473&zoom=18&size=1781x1781&maptype=hybrid&format=jpg-baseline&sensor=false&client=}
[5]: {http://maps.googleapis.com/maps/api/staticmap?center=40.909075,-100.739925&zoom=17&size=1813x1813&maptype=hybrid&format=jpg-baseline&sensor=false&client=}

We would like to get Google tiles at least close to the size we request or at least understand how ThinkGeo comes up with these large variation of request sizes.



Any direction or help is appreciated. Are we doing something wrong?



Thanks,

Chuk

Hi Chuck,



Please try the below codes and it should work:

View side:


function exportBitmap(width, height) {
    var clientExtent = getPrintExtent(width,height);
 
    Map1.ajaxCallAction(@ViewContext.RouteData.Values[“Controller”].ToString()’‘ExportBitmap’,{ ‘width’: width, ‘height’: height,‘clientExtent’:clientExtent.toString()},
        function (result) { });
}
 
function getPrintExtent(width, height) {
    var resolution = Map1.getResolution();
    var center = Map1.getCenter();
    if ((Map1.center != null) && (resolution != null)) {
        var halfWDeg = (width * resolution) / 2;
        var halfHDeg = (height * resolution) / 2;
 
        extent = new OpenLayers.Bounds(center.lon - halfWDeg,
                                       center.lat - halfHDeg,
                                       center.lon + halfWDeg,
                                       center.lat + halfHDeg);
    }
    return extent;
}

Controller side:


[MapActionFilter]
public void ExportBitmap(Map map, GeoCollection<object> args)
{
    int width = Int32.Parse(args[0].ToString());
    int height = Int32.Parse(args[1].ToString());
 
    string[] clientExtentString = args[2].ToString().Split(’,’);
    RectangleShape clientExtent = new RectangleShape(double.Parse(clientExtentString[0]), double.Parse(clientExtentString[3]), double.Parse(clientExtentString[2]), double.Parse(clientExtentString[1]));
map.CurrentExtent = clientExtent;
 
    LayerOverlay googleOverlay = map.CustomOverlays[“google”as LayerOverlay;
    googleOverlay.IsVisible = true;
    Bitmap result = map.GetBitmap(widthheight );
    result.Save(string.Format(“d:\cache\{0}.png”,Guid.NewGuid().ToString()));
}

The above key is when we call the GetBitMap method, we need to make sure the map current extent is happening to cover the bitmap width and height. That’s why we need to reset the map currentextent. After we export the bitmap, we can rollback the previous map extent.



As for your confusions on all kinds of size,  I will try to explain them below:

Map Size: it should be mapping to the client map view size which is a div.

Tile Size(request to map suite): this size only works under multi-thread(this is default in layeroverlay) and this is equal to the request tile images.

Tile Size(request to google): 


        
  • if the layeroverlay is using single thread and the googleLayer is using multi-thread, then this means the client size only request one single tile to server side. Then the map suite in server side will generate this big single tile by requesting multi tiles to google map service.

  •     
  • if the layeroverlay and the googlelayer are both using single thread, this means there is only one single tile in the whole time, from client to server side and then from the server side to google map service.


This does be a bit confusion but I hope it is clear.

Thanks,

Troy

Thank you for your reply Troy, our situation is a little different though. Since we are using the bitmap for reports, we are doing all the work on the server side. Our process is as follows:



  - Create new map in memory, setting size (1600 x 1600 for example)

  - Populate the map with our layers which includes a GoogleMapsLayer as the base layer

  - Set GoogleMapsTileMode to SingleTile

  - Add Google layer to StaticOverlay, setting IsBaseLayer to true

  - Find extent based on features in one of the layers

  - Square up the extent by increasing the width or height to match whichever is larger

  - GetBitmap(1600, 1600)



Our current need is that we get a google tile back that matches as closely as possible to the size of the map/GetBitmap call. Right now if we request 1600x1600, ThinkGeo sends a request to Google for 2350x2350 and then Google sends back 2048x2048 since this is the largest size supported. Then the Google layer is much smaller than the map size. If we request much smaller then ThinkGeo requests tiles that are 1000x1000 which are a little small and the quality of the imagery is lower than we need.



Thanks for your help.

Chuck

Hi Chuck, 
  
 Okay, got your question and we will try to find out a solution for you. 
 Thanks, 
 Troy

Hi Chuck,



Thanks for your patience. We figure out a solution and hope it helps. Please try it.



Thanks,

Troy

DisplayASimpleMapController.txt (3.21 KB)