Maps for Garmin Devices

Maps on portable devices

Getting working maps on a mobile device is reasonably straightforward, especially if you're able to be connected to a cellular service.

The challenge starts to increase when you may not have connectivity, or have limited bandwidth or speed on your device. Offline maps within tools like Google Maps generally work well enough, but start to become feature limited in terms of POIs.

And while cellular coverage is obviously great in most parts of civilized Canada, there are still many close destinations that lack connectivity (specifically highway 93 in Alberta).

For use outside of geocaching, I make good use of OsmAnd for more general routing and POI destinations. Maps of the region(s) you might find yourself in are generally available and usually correct enough to get you around. While OsmAnd isn't free, it often goes on a good enough sale to make it worthwhile. I've skipped the "live maps" subscription within the app itself.

For geocaching, my app of choice is C:Geo. Offline maps can be downloaded from within the app, or loaded from your computer to your phone's storage. I keep a set of maps on my phone refreshed periodically from Mapsforge or OpenAndroMaps. My caching area is generally small enough and in developed areas enough that my maps can be months old without causing any challenges.

Maps within C:Geo aren't used for routing (not "computer" routing; you can obviously still eyeball routes based on what the trails look like), but navigating to a cache using OsmAnd is a cheezeburger menu item away.

Garmin Fenix

So I've got this Garmin Fenix 5. Great watch for running, riding, occasional geocaching (though I generally use my phone for this) and so on. The usual issue with non-connected devices exists: How do you update maps?

The easy answer is to wait for Garmin to update them for you. This happens at some frequency within the Garmin Express desktop application.

This is where my complaints start:

  • ALL the maps are loaded all the time. I don't ride outside of Alberta all that often, nevermind outside of Canada. I don't really need maps of Mexico ...
  • More maps mean longer start-up times for my watch

So - the easy answer is to remove the maps from your watch - right? This question has been posted to the Garmin forums, with the solution being that you can delete gmapsupp?.img files. Just be sure to leave the basemap files (gmapbmap.img and gmapbmap.sum). After you take a backup of your watch's content first, of course...

Now with all the maps gone, I want to get regional maps.

I have used Free maps for Garmin brand GPS devices in the past, but as of this post, it seems that getting a map download is ~150 days old, and using map data is well over a year old:

Garmin openstreetmap.nl not being current

Sure enough, upon submission for a download, I am still waiting for my download link. Given the week or so that's passed.. I think I believe them.

Working with BBBike Extract Maps

Poking at some references listed on The OpenStreetMap wiki, I find BBBike Extracts which seems to do what I want... and with a handy help page!

Find your region (or use the Search function), select your baselayer (on the right - I prefer OSM Mapnik) and choose the format to be "Garmin BBBike (Latin1)". My watch, in it's current firmware, did not understand the UTF-8 format - so stick with Latin1 for now. Click "New", highlight your region, adjust as necessary. Key in your email address, and click "Extract". Wait for the email.. and there's your map.

The help page (at https://extract.bbbike.org/extract.html) discusses the different styles that can be applied. BBBike seems to be reasonably good for outdoor activities, and has been functional for the runs that we do today.

bbbike.org extract example

Extract the gmapsupp.img file from the downloaded ZIP, load it on to your watch and you're in business.

Multiple Maps

So far so good. I ran into a problem when I wanted to load two different regions - in my case Edmonton and Banff. The Wiki page tells me I can append a prefix or suffix to the filename, provided that the .img extension remains - as the device will load any .img files it finds in the /Garmin/ folder on it's internal storage. So, I name my two files gmasupp-edmonton.img and gmapsupp-banff.img. Checking the watch, I find that only one map gets loaded (in my testing, the Edmonton map was loaded - maybe because that's where I was doing the testing? Hard to say...). Remove the Edmonton map, and leave the Banff map - and the Banff map loads just fine (though I can't locate myself on it because I'm not there).

In the end, I had to edit the data within the file with a hex editor. Copied right from the Wiki page:

1- Edit bytes 0x49-0x5C to assign a new name using ASCII printable characters.
2  - Pad unused characters at the end of the name with spaces.
3  - In some map files, 0x5D is a space character, but it is not part of the name field.
4- Additional map descriptive text may be placed in characters 0x65-0x82.
5  - Unused characters at the end of the field are padded out with spaces.

It seems as though the name of the map, as well as the descriptive text, is visible on the Fenix when you're selecting maps. It also seems that they need to be "considerably" distinct. In the image below,

  • The two windows on the right are the original download. The highlighted bytes are the map name as well as the description. The two fields are unique between the two files. The only file that was visible on my watch was Edmonton.
  • The two windows on the left are modified. I have changed the name and description to be the region that the map file is for. Both files are visible after this change.

Hex editing Garmin .IMG files

So this mostly worked - though I am seeing corruption in the Edmonton map after loading this in, but I am able to see both maps...

Testing with 2 map regions located near each other, but not overlapping. Loading both on my watch then checking the settings, I do only see one map file loaded, and attempting to navigate "using map", only one map section is shown.

After changing the name and description on my test maps, they're still not showing as two separate maps - meaning I goofed something on the first pass through.

Merging Maps

Using mkgmap, I'm not successfully able to merge the two testing maps together:

1tim@tim:~/Downloads/mkgmap-r4802$ java -jar mkgmap.jar --gmapsupp ../gmapsupp-t1.img ../gmapsupp-t2.img
2Mkgmap version 4802
3Time started: Sun Jul 25 15:30:57 MDT 2021
4Number of MapFailedExceptions: 0
5Number of ExitExceptions: 0
6Time finished: Sun Jul 25 15:30:58 MDT 2021
7Total time taken: 397 ms

This generates a fresh gmapsupp.img in the working directory, which happens to be basically empty and unusable:

1tim@tim:~/Downloads/mkgmap-r4802$ ls -al ./*.img
2-rw-rw-r-- 1 tim tim    2560 Jul 25 16:24 ./gmapsupp.img
3-rw-rw-r-- 1 tim tim  536064 Jul 25 15:12 ./gmapsupp-t1.img
4-rw-rw-r-- 1 tim tim 1601536 Jul 25 15:12 ./gmapsupp-t2.img
5-rw-rw-r-- 1 tim tim    5120 Jul 25 16:24 ./osmmap.img

There's a few potential issues - one is that the baked in map ID is the same between the two source .img files, and they effectively overwrite each other. Another potential is that it's missing a TYP file to define how the Garmin device should interpret the .img file, but given how my device doesn't seem to be able to identify both map files on it at the same time - I feel like it has something more to do with some internal metadata in the map file.

Making Maps

So, instead of downloading the BBBike maps, we can download the PBF (Protocolbuffer) type, then merge those into a single map file. In my case, my two regions downloaded and merged can be run with:

tim@tim:~/Downloads$ java -jar mkgmap-r4802/mkgmap.jar --ea --mapname=<some random 8 digits> --description="Edmonton Area Test" --family-id=9432 --product-id=4 --remove-short-arcs --route --location-autofill=is_in,nearest --index --show-profiles=1 --make-opposite-cycleways --housenumbers --add-pois-to-areas --code-page=1252 --gmapsupp ./*.pbf

This command was more or less generated from the BBBike format download. There's a log file in the ZIP file that contains the commands executed, so I've simply adapted what was generated in the log file to see if I can figure this out.

Of note, I didn't need to use splitter - probably because the PBF files I've downloaded are small enough. Looking at the output of splitter, the .pbf files are slightly larger than the original source file. I suspect I'd need to use splitter if I had a larger set of source maps.

The output here is close. It's evident that I'm missing some styling information (and possibly TYP files?):

One map section, BBike STyle

Both sections, merged

The end result loads well on my watch, so that's something.

Still more to do

Ideally, it'd be nice to be able to create this all on my own machine without needing to download the map data from another site. This removes the dependency on other sites and services that may be under load or no longer available.

In the short term, I need to understand how styles and TYPs work so that I can better format the generated map. While I'm not married to the BBBike style, there are some pretty glaring omissions within the default map - shared paths, or what I would call bike trails, are really NOT visible on my watch at all.

I was able to extract the TYP file from a working .img file, but when applied to the raw PBF data when generating a map - I'm missing some shared trails. Are they missing from the map data? Are they omitted by missing styling? I don't really know.

In the end, it's easier for me to go to BBBike Extracts and select a large region that includes the spaces that I'm looking for. The whole file is around 50mb - a far cry from the several GB that the Garmin supplied maps were set at.

I'd still like to explore making styles / TYP files so that I can customize (and remove!) elements from the maps that aren't needed. Do I need to see each house's outline on my watch while on a run or ride? Probably not - but it might be helpful to see that while caching.

So.. carry on.