JPEG tiles

I've been rendering my own maps for I don't remember how long. It's a raster style that prioritizes what's important to me, so when I open the map, it has all the info I want right there, no queries needed. It's also a mixed use map, with contrasting roads for driving aid, useful walking data (shops, paths, etc) and some other info that allows me to plan trips and vacations. I'm no cartographer, so most probably it can be seen as 'ugly' by many, but oh well, I'm no cartographer :)

But in fact the original reason I started doing my own maps was offline mode. Back then I had a Nokia N900 that had marble as the mapping app and a crappy 3G contract. It's a basic map app, but which can cache tiles and you can pre-fill that cache at will: just deploy the tiles in the right place and they will show when offline. The problem is, there are gazillion tiles and they weight a lot.

I currently serve all non-sea tiles2 from my own web server. We're talking about 24_058_696 files. A partial render of only about 500 thousand files shows each file uses a median of 15_414 bytes, so those 24M+ files should weight 370_840_740_144 bytes; that is, more than 345GiB (it's actually 282GiB; that's statistics for you :). This definitely does not fit in a puny smartphone (well, maybe, if I could put a huge, expensive and fragile SD card on my phone, which I can, hmmm). Anyways, it's still a lot. I could try and use one of the png file optimizers, but I have found very little gain there.

In another corner of my life, I watched a video of a photographer talking how playing with the JPEG quality slider in Photoshop could get great gains is disk space saved, specially if you pushed the slider all the way to 0, without really losing detail. So I took a picture, played with ImageMagick instead, to show him that Photoshop actually is lying to him, in the sense that its 0 value seemed to be closer to 70 or 80 in real JPEG parameters. I never wrote the response, but I still have the test images. So I picked them up, found that the one at 50 quality looked good enough, and used that value to save the tiles.

The result is very good. Almost all files are 50% or less their PNG size, and the peak is around 30%. That could mean I could use a smaller, more affordable 128GiB SD card. It also means that even if I don't put all the tiles on the phone, downloading them from my home server would be around 3x faster. Luckily Leaflet, OpenLayers and even marble (which I still use it to quickly browse my local cache) support the format. It's true, the quality is not perfect, but if I'm either driving or consulting the map while hiking, I'm not going to be really worried about the color of the white halos around text being a little tinted or other artifacts here an there, and I can always switch to the online, high quality maps if I have network access.

A couple of metatiles for comparison:

PNG:

JPEG:

That also means that now osm-tile-tools now accepts --tile-file-format which can be either PNG (the default) or JPEG. It also accepts a --tile-file-format-options option, to which you can pass format strings options as documented in mapnik's wiki1.


  1. I just started reading about PNG options and found I could use t=0 to remove the alpha channel that we don't use on tiles at all. That should give a gain, but it seems the format is clever enough to not include the channel if it's not used at all. Render times were similar. 

  2. as sea tiles are missing, I just serve a sea tile for any 404 code. This also means going somewhere that I haven't rendered yet gives you a nice blue wall.