Image Tile Caching

Update (Oct 2, 2009): I’ve written a new post with links to newer versions of this script. Make sure you use the code there, not here.

For the map mosaic viewer I’m working on, the images are generated by ER Mapper’s Image Web Server from the source JPEG 2000 and ECW files. It works great, but can be a little slow, as it has to load very large images (equivalent of 100GB uncompressed) and pull tiles out. Because the viewer always uses the same tiles at each zoom level (defined by a lat/lon bounding box), it made sense to cache the images.

A real simple PHP file seemed to do the trick:

<?php

$qs = $_SERVER['QUERY_STRING'];
$from = array('=', '&', '.', ',','/');
$cf = 'cache/' . md5(str_replace($from, '_', $qs));

if (!file_exists($cf))
{
	$base = 'http://localhost/ecwp/ecw_wms.dll?';
	$handle = fopen($base . $qs, "rb");
	$contents = stream_get_contents($handle);
	fclose($handle);

	$handle = fopen($cf, "wb");
	fwrite($handle, $contents);
	fclose($handle);

	exec("e:/pngnq/pngnq.exe d:/inetpub/wwwroot/tiles/" . $cf);
	unlink($cf);
	copy($cf . '-nq8.png', $cf);
	unlink($cf . '-nq8.png');
}

header('Content-Type: image/png');
header("Content-Length: ". filesize($cf));
set_time_limit(0);

readfile($cf);

?>

The unique identifier for any requested URL is an md5 hash of the entire query string. The script checks the cache for that URL and offers up the cached file if it exists. Otherwise it requests the image from IWS and saves it to the cache.

Note that with this method, I am NOT generating the tile cache in advance (unlike Arc2Earth), but rather as the tiles are first requested. Saves load on the server and prevents having to regenerate the cache if I update the imagery. And, quite honestly, the full image at every zoom level will never be requested, so we can save cache space as well.

The images are generated by IWS as image/png, which allows transparency in Google Maps (jpeg doesn’t handle transparency), but they are rather large. So I’m using pngnq to quantize the colors from 3×8-bit down to 256 with dithering, which is visually imperceptible (by this method — don’t use ImageMagick) and cuts the file size of each tile in half.

Posted in Technology and tagged , , , .

Comments are closed.