3

I'm working on a project that converts digital histology (microscope) slide images to 256x256 pixel JPEG tiles arranged in the Google Maps architecture. Being that these tissues are set against a background that is entirely white (see example here), I'm using a program that, when converting the microscope slide files to tiled JPEGs, it also deletes entirely white tiles. This saves a huge amount of storage space, as well as results in many fewer files to upload to a server, which is helpful since I do not have control over the server (I'm using Google Storage).

However, this leaves blank holes in the image. I'm trying to get the Google Maps script to load a single all-white JPEG image when a tile is not present at that location. I cannot find an answer anywhere, and my programming skills are novice-level at best. The closest thing I can find is using tile overlays, but I won't always know which tiles need to be replaced, and it seems like that is necessary information in order to fill in these unfilled areas.

My current (very very basic script) is as follows:

< html > < head >
  < script type = "text/javascript"
src = "https://maps.googleapis.com/maps/api/js?sensor=true&v=3" > < /script>
<script type="text/javascript
">
 function initialize()
 {
        geocoder = new google.maps.Geocoder();
     var myOptions = {
    zoom: 2,
    center: new google.maps.LatLng(0,0),
    mapTypeControl: false,
    streetViewControl: false,
    navigationControl: true,
    mapTypeId: google.maps.MapTypeId.ROADMAP
       }
          map = new google.maps.Map(document.getElementById("
map_canvas "), myOptions);
       var VM_Map = new google.maps.ImageMapType({
   name: 'Digital Histology'
   alt: 'Digital Histology',
   getTileUrl: function(coord, zoom) {return customGetTileURL(coord, zoom);},
   tileSize: new google.maps.Size(256, 256),
   minZoom: 1,
   maxZoom: 9,
   isPng: false
   });
  map.mapTypes.set('VM_Map', VM_Map);
         map.setMapTypeId('VM_Map');
}
function customGetTileURL(a,b) {
         return 'SERVER_PATH' + b + '/' + a.y + '/' + a.x + '.jpg'
}
</script>
</head>
<body id="
body " style="
margin: 0px;
padding: 0px;
overflow: hidden;
" onLoad="
initialize()
" >
<div id="
map_canvas " style="
width: 100 % ;
height: 100 % ;
"></div>
</body>
</html>

Any suggestions would be deeply appreciated.

Brandon
  • 91
  • 5
  • simple define a default-tile via [ErrorDocument404](https://httpd.apache.org/docs/2.4/custom-error.html) – Dr.Molle May 13 '16 at 09:53
  • I need to have control over the server to do that, yes? I don't have control over the server (I'm paying Google for storage... I'll add that to the post). – Brandon May 14 '16 at 16:09
  • when you want a white tile for missing tiles,simply define a white background for all tiles. – Dr.Molle May 14 '16 at 19:47
  • Oh. Duh. That'll do it! Thanks so much! Would you like to add that as an answer so I can give you credit? – Brandon May 15 '16 at 02:35
  • This doesn't apply to @Brandon's question since he only uses zoom 9 at most, but creating a tile pyramid that uses a white (or transparent) tile for empty tiles is a *terrible* idea if your map zoom covers a large area at high zoom* and your features are *boundaries* (e.g., state borders; property boundaries). Why? Because blank tiles take up ~95% of the average tile directory at zooms > 15, and zooms > 15 take up almost 95% of all tiles. Each blank tile file is 360 bytes, **but it takes up 4KB on disk** because of the **minimum block size**. Load to bounds-limits; test on client-side. – GT. Mar 19 '17 at 19:21
  • Need to clarify: "creating a tile pyramid that uses a white (or transparent) tile for empty tiles is a *terrible* idea" only applies **if a new tile is created by the tiler for any part of the tiled region that has no data**. – GT. Mar 19 '17 at 19:44

1 Answers1

1

There are some options you have, but they depend on your setup and amount of control you have over it.

1.Option: It seems that you are loading the images from server: if the server is running under your control, and it uses Apache or some other webserver solution which can be set up, you can configure it to return default image (in your case the white image) if the requested image does not exist. See this SO question on how to do that with Apache. I would definitely go with this option if possible.

2.Option:If you know beforehand, which files doesn't exist, you can add them to some js object and always check if they exist first, and if not return the url of the white image. So you would have a JS variable with structure like this:

non_existing_images = {SAMPLE_ZOOM_1:
                        {SAMPLE_X_COORD_1:
                          {SAMPLE_Y_COORD_1:true, SAMPLE_Y_COORD_2:true, ...},
                         SAMPLE_X_COORD_2:
                          {SAMPLE_Y_COORD_1:true, SAMPLE_Y_COORD_2:true, ...}
                        ...},
                       SAMPLE_ZOOM_2:...
                      }

Then have a function:

function loadNonExistingImages(){
   //this function would determine, which images do not exist on your server. and then save it in not_existing_images object. It may be a call to some backend server which returns this for you.
}

If you use some backend server, a script can connect do DB (if you are using one for images), or some other way (check if image physically exist) to return list of images which don't exist. Use the function to populate non_existing_images and after it's populated call initialize(); (if you don't have a backend server you can use js to check if images exist but I STRONGLY discourage this if you are going to use a lot of images, because this would result in huge amount of requests to server)

Then you just have to adjust customGetTileURL function to something like this:

function customGetTileURL(a,b) {
         if(non_existing_images[b] && non_existing_images[b][a.x] && non_existing_images[b][a.y]) return 'SERVER_PATH_TO_WHITE_IMAGE.jpg'; //if image doesn't exist return path to the white image
         else return 'SERVER_PATH' + b + '/' + a.y + '/' + a.x + '.jpg'
}
Community
  • 1
  • 1
Matej P.
  • 5,303
  • 1
  • 28
  • 44
  • Thanks for the comment! I do not have control over the server (I'm using Google Cloud Storage), though that seems like a good option if I ever have one under my control. I also don't easily know which tiles are missing--I could find out, but the last test file I did had 20,000 blank tiles (of originally 60,000 tiles), so this doesn't seem like a great option. – Brandon May 13 '16 at 23:24
  • @Brandon - you might have already worked this out, but fetching all tiles at once is usually not useful. Set a bounds and only load tiles that intersect those bounds. We use the screen bounds + 50% in each direction so that the user can navigate nearby reasonably seamlessly. That does several things: reduces the payload to a dozen or so tiles for each screen); improves site responsiveness; makes checking for tile existence trivial. It requires a call to the tile-fetcher when the bounds change to a previously-unviewed bounds, but that's a small tradeoff. – GT. Mar 19 '17 at 19:11
  • D'oh - should have made clear that for users with control over `httpd.conf` and/or `.htaccess`, the "checking for tile existence" stage in JavaScript is an operational decision, since the server can be set to replace non-existent images with a transparent tile globally (via a `RewriteRule` in `httpd.conf`), or it can be done on a per-directory basis with `ErrorDocument 404 /path/to/transparent.png` in `.htaccess` in the root directory of the tile pyramid. If it's done through `httpd.conf`, need to ensure that the non-existence of the image is logged server-side so it can be evaluated. – GT. Mar 19 '17 at 19:38