This email is about limitations viewing some raster maps such as MBTILES, ECW, and also GeoTIFF with internal overviews.
I think this is a very important issue because it limits too much the use of maps in QMS, so I have been chasing it for months, trying different strategies, and luckily I have found a workaround.
Probably this workaround could be improved, thats the reason to expose all this by email and request your opinion before exposing anything at the issue page of QMS nor adding it as a trick in the wiki section.
BRIEF SUMMARY:
-
QMS detects overviews for VRT files containining an unique ECW, MBTILES, or GeoTIFF file. However overviews are not detected for VRTs that contain more than one source file , and therefore QMS applies the pixel limitation ( TILELIMIT value).
-
What are we doing for now?
- use one VRT per source file. :-( we lose the advantages of VRT format.
- make external overviews with gdaladdo. :-( is inefficient for formats such as MBTILES, ECW, or GeoTiFF that already have them..
-
I have tested with success another workaround: place next to the VRT a minimum size .OVR (16x16 px). The funny thing is that we can do it in 2 seconds ( out of QMS).
-
Probably this workaround can be improved, or may be we can avoid it at all making some tweaks in the QMS code.
IN DETAIL:
QMS does handle pretty well GeoTIFF, MBTILES or ECW files wrapped in a VRT file. I can load an unique ECW file for all the pyrenees (more than 2Gb) and it is shown flawless at all zoom levels. The same when I load a 500 Mb MBTILES, and identical for those Geotiff that contain internal overviews. I don't need to make any external overview (.OVR) because QMS detects they do have internal overviews.
This works while the VRT calls an unique source file. However when several of such files are combined in a VRT, QMS does no detect the overviews from source files, (hasoverviews) then it applies the pixel limitation showing only the map border until you get the top zoom level of the source.
This brings us to a frustrating paradox. 4 contiguous files loaded one by one are shown well, but if combined in a VRT they are not shown , although in both cases QMS has to request the same amount of pixels.
So for now we are forced to use a single VRT for each source file, and/or create external overviews when generating the VRT. Both ways have serious drawbacks.
-Drawbacks when doing one VRT per source file:
Here we loss one of the poweful things of VRTs that is combine several files and handle them as an unique dataset, eg: combine several maps from the same family and have an unique name in the map list, or make a derivated map from the combined VRT, and so on…
(with this panorama I understand why the VRT format is so unpopular for new QMS users, they assume that they have to make a unique VRT for each raster for nothing....and they will never know about its advantages.)
In addition doing one VRT for each source leads to another specific problem for Mbtiles: Some delicious MBTILES contains different information for different zoom levels, ( eg: imagery at the top zoom level, then a 1:25k topomap, then a 1:50K map, then a 1:100k map,…) . I have observed that QMS shows one zoom level or the next one based on the number of pixels of the mbtiles contained on the canvas [2], so when you have loaded several contiguous VRT ( 1 mbtiles per VRT) and you drag the map near to the border of one of them you get a pretty Frankestein map, with different zoom levels ,thus different apparience, mixed ( view screenshots) .
In QMS this “frankestein effect“ could be solved by combining all the contiguous mbtiles in an unique VRT, but then we face the issue of pixel limitation and go back to the beginning.
-Drawbacks for making classical overviews with gdaladdo
I know you always reccomend doing overwiews to solve the pixel limation. That is right for formats that do not contain internal overviews, but it is unnecessary and inefficient for formats such as mbtiles or ecw containing internal overviews, and the pain in the ass is that the gdaladdo process to create a single overview (eg 1:64) for a medium area can take hours and hours...for nothing.
There is another important detail about external .ovr that affects multi-scale mbtiles containing different mapsets. The external overviews are a downsampled copy of the top level, so we lose the magic of the multi-scale map. This is more frustrant if you also use the same maps in other gdal app like QGIS that would load the external ovr if it find one.
Take in mind that this is not related to the use of the zoom range locks to show one map or another. I know I could put another general topo map for outer levels and play with zoom range locks, and usually I do if I have one, but we are now into correctly display our detailed map.
WORKAROUNDS TO SOLVE THIS
At first I started playing with the TILELIMIT value in CmapVRT.cpp, but increasig that value does not solve the problem for all cases. ( appart this, maybe this values is very restrictive and it could be a bit more tolerant)
The key is in the check that QMS makes about overviews. I remember you said that it checks the first band of the archive to count overviews.
dataset->GetRasterBand(1)->GetOverviewCount()
I have observed that this works for VRTs containing an unique source file, but not for VRTs containing more than one but I can't figure out why. It is strange.
The goal is to make QMS detect overviews with no pain for other apps, and with no extra time/work for the user.
To do so we can place a “fake” or minimum size .OVR next to the VRT.
At first I have been playing with a 16x16 pixels generic tiff for all my VRTs. Assuming I have a generic tiff named “fake.ovr”, getting the correspondant “fake” OVR for every VRT is trivial in the command line.
cp fake.ovr mymap.vrt.ovr
This makes the magic. QMS detects this overview but does not really use it, and the internal ovr of the source files are shown, even with nested and derivated VRTs. Also for other apps like QGIS the .ovr image is so little that it is not shown until you get a very very outer zoom, so is no relevant.
OK, OK.. to be serious, having a fake .ovr does not sound very well, :-P
Let’s do similar with a “true” .ovr
This will create a minimum size true .ovr for mymap.vrt:
gdal_translate mymap.vrt mymap.vrt.ovr -outsize 16 0 -of Gtiff
Instead of using gdaladdo , which takes hours to do the task, we use gdal_translate, which does it in a second. We can use gdal_translate because we want an .ovr with only one level at a fixed size instead of the classical /2 pyramids.
For those that have panic to the console I have also prepared two .bat and .sh files to do the task more easy. Javi and Carlos have used them with succes.
NEXT STEPS?
I would propose:
(order does not necessarily indicate preference)
1- Tweak the code to check if one band of one of the files contained in the VRT has overviews, if has overviews then the pixel limitation would not apply
2- Make the VRTBuilder to check if one band of the first file we have selected to add in the VRT has overviews, if yes then silently create a minimum size external .ovr adding at the end of the process:
gdal_translate mymap.vrt mymap.vrt.ovr -outsize 16 0 -of Gtiff
3- Include in the VRTBuilder ui the option to create this minimum size .OVR. If checked, instead of using gdaladdo, it would add at the end of the process:
gdal_translate mymap.vrt mymap.vrt.ovr -outsize 16 0 -of Gtiff
4- Do nothing with the code and add a paragraph in the tip and tricks section of the wiki about this workaround , with a command line example , and optionally providing .sh and .bat files to make it more easy for regular users.
Remarks:
#1 Seems the best , because it would applie for all new and existing VRTs, but it could have caveats. I am not absolute sure on how could detect overviews for nested VRTs. [1]
#2 ( if #1 is not possible) would be the more easy and transparent for regular users
#3 gives the user the option to choose, but maybe a regular user doesn't know anything about this, and we're complicating things.
#4 Right now it would be the easiest and fastest to do. I can take care of it, but doing so gives the impression that is a patch. I would better consider it complementary to #2 or #3, to make external .ovr of existings .vrts with no need to redo the VRT from the VRT builder, or for nested VRTs if they fail with #1.
What do you think about next step?
Should we port all this to the issue page and the mailing list?
I am not able to modify the code by myself but as always I am ready to test changes, or to put something in the wiki.
No hurry for coding...I assume right now you will be thinking more in the migration to GIT, and is not a good season for coding.