In a previous article, I showed how to Locate the Nearest Radar Station and Display Radar Images. A commenter, mike, pointed out the idea of merging the image layers using PHP instead of layering all the images separately using CSS. Here is how to do it.
Just like the previous article on finding the closest radar station, I am going to use IP geolocation to find the closest radar site. See that previous article for an explanation on how to do that.
<?php /* replace with your own DB connection code */ require('../includes/database.php'); $db = db_connect(); /* get the IP address and make sure it is an unsigned integer */ $ip = sprintf('%u', ip2long($_SERVER['REMOTE_ADDR'])); /* fetch the location id */ $query = "SELECT locId FROM CityBlocks WHERE $ip BETWEEN startIpNum AND endIpNum LIMIT 1"; $result = mysql_query($query, $db) or die(mysql_error()); $row = mysql_fetch_assoc($result); /* now fetch the location */ $locId = $row['locId']; $query = "SELECT * FROM CityLocation WHERE locId = $locId LIMIT 1"; $result = mysql_query($query, $db) or die(mysql_error()); $location = mysql_fetch_assoc($result); /* offset the coordinates by 3, and find the closest station */ $lat = $location['latitude'] + 3; $lon = $location['longitude'] - 3; $query = "SELECT *, SQRT(POW(69.1 * (lat - $lat), 2) + POW(69.1 * ($lon - lon) * COS(lat / 57.3 ), 2 )) AS distance FROM RadarSites ORDER BY distance ASC LIMIT 1"; $result = mysql_query($query, $db) or die(mysql_error()); $radar = mysql_fetch_assoc($result); /* we are using the snoopy class to download the images */ include('../includes/Snoopy.class.php'); $snoopy = new Snoopy(); /* cache the files locally */ function dl_cache($url, $filename) { if (!file_exists($filename) || filemtime($filename) + 600 < time()) { global $snoopy; $snoopy->fetch($url); file_put_contents($filename, $snoopy->results); $snoopy->results = ''; } } /* download the radar images */ $radar_id = $radar['id']; dl_cache("http://radar.weather.gov/Overlays/Topo/Short/{$radar_id}_Topo_Short.jpg", "maps/{$radar_id}_Topo_Short.jpg"); dl_cache("http://radar.weather.gov/RadarImg/N0R/{$radar_id}_N0R_0.gif", "maps/{$radar_id}_N0R_0.gif"); dl_cache("http://radar.weather.gov/Overlays/County/Short/{$radar_id}_County_Short.gif", "maps/{$radar_id}_County_Short.gif"); dl_cache("http://radar.weather.gov/Overlays/Highways/Short/{$radar_id}_Highway_Short.gif", "maps/{$radar_id}_Highway_Short.gif"); dl_cache("http://radar.weather.gov/Overlays/Rivers/Short/{$radar_id}_Rivers_Short.gif", "maps/{$radar_id}_Rivers_Short.gif"); dl_cache("http://radar.weather.gov/Overlays/Cities/Short/{$radar_id}_City_Short.gif", "maps/{$radar_id}_City_Short.gif"); dl_cache("http://radar.weather.gov/Legend/N0R/{$radar_id}_N0R_Legend_0.gif", "maps/{$radar_id}_N0R_Legend_0.gif"); dl_cache("http://radar.weather.gov/Warnings/Short/{$radar_id}_Warnings_0.gif", "maps/{$radar_id}_Warnings_0.gif"); /* load the radar layers into an array */ $layers = array(); $layers[] = imagecreatefromjpeg("maps/{$radar_id}_Topo_Short.jpg"); $layers[] = imagecreatefromgif("maps/{$radar_id}_N0R_0.gif"); $layers[] = imagecreatefromgif("maps/{$radar_id}_County_Short.gif"); $layers[] = imagecreatefromgif("maps/{$radar_id}_Highway_Short.gif"); $layers[] = imagecreatefromgif("maps/{$radar_id}_Rivers_Short.gif"); $layers[] = imagecreatefromgif("maps/{$radar_id}_City_Short.gif"); $layers[] = imagecreatefromgif("maps/{$radar_id}_N0R_Legend_0.gif"); $layers[] = imagecreatefromgif("maps/{$radar_id}_Warnings_0.gif"); $image = imagecreatetruecolor(600, 550); /* merge the layers */ for ($i = 0; $i < count($layers); $i++) { imagecopy($image, $layers[$i], 0, 0, 0, 0, 600, 550); } /* we're done! output the image... */ header('Content-type: image/jpeg'); imagejpeg($image); /** * Why do I comment out the PHP closing tag? * See: http://phpstarter.net/2009/01/omit-the-php-closing-tag/ */ /* ?> */
The code from line ~31 on is pretty self-explanatory. Basically, I am caching the maps locally, and then loading the images into PHP image resources. I am putting the images in a PHP array because I want to make it easy add/delete/move layers. For the application I’m using it for, it’s not likely, but your needs may differ.
The important function is imagecopy(), which is defined as:
bool imagecopy ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h )
Since I am copying whole pictures directly on top of each other – all the same size – it’s very easy. You can specify image sizes and location in case you are copying a smaller image onto a larger image, like a logo copyright on a photo, for example.
So there you have it. Although I believe the first method of layering the images via CSS works just fine, this method will work when you need to deliver a single image.