Displaying imagine location in wordpress using their gps coords proved to be not as easy as I initially thought, but it is something I wanted to get done from some time now, so I decided to get down on it. I have chosen to use geotag plugin for its capability to read exif data from images spread through a post and nicely locate them on a google map, among other stuff.
Unfortunately, after uploading few images I discovered that the cool functionality of searching photos with gps exif data and displaying their location on map was not working. That was because the images displayed don`t have any exif data stored in the file, as wordpress automatically stripes it down on image upload, but not before data is read so it can be stored serialized in postmeta table from db. Instead of altering wordpress core files to modify this behavior, I preferred to find a different approach and try using the meta info already stored into database. But the problem is that wp save only some tags from exif, and GPS information in not among them, so first step is to add the following filter to the wp_read_image_metadata hook:
add_filter('wp_read_image_metadata', 'saveGeoExif','',3);
function saveGeoExif($meta,$file) {
$exif = @exif_read_data($file);
if (isset($exif['GPSLatitude'])){
$meta['GPSLatitude'] = $exif['GPSLatitude'];
}
if (isset($exif['GPSLatitudeRef'])){
$meta['GPSLatitudeRef'] = trim($exif['GPSLatitudeRef']);
}
if (isset($exif['GPSLongitude'])){
$meta['GPSLongitude'] = $exif['GPSLongitude'] ;
}
if (isset($exif['GPSLongitudeRef'])){
$meta['GPSLongitudeRef'] = trim($exif['GPSLongitudeRef']);
}
if (isset($exif['GPSAltitudeRef'])){
$meta['GPSAltitudeRef'] = trim($exif['GPSLongitudeRef']);
}
if (isset($exif['GPSAltitude'])){
$meta['GPSAltitude'] = trim($exif['GPSLongitudeRef']);
}
if (isset($exif['GPSTimeStamp'])){
$meta['GPSTimeStamp'] = $exif['GPSLongitudeRef'];
}
if (isset($exif['GPSDOP'])){
$meta['GPSDOP'] = $exif['GPSLongitudeRef'];
}
if (isset($exif['GPSImgDirectionRef'])){
$meta['GPSImgDirectionRef'] = trim($exif['GPSLongitudeRef']);
}
if (isset($exif['GPSImgDirection'])){
$meta['GPSImgDirection'] = trim($exif['GPSLongitudeRef']);
}
return $meta;
}
This will save all GPS information into database upon image upload.
Next we need to search all the photo attachments belonging to a post, calculate their coordinates and extract image url, and then pass them to geotag plugin.
add_filter("the_content", 'getGeodataFromMeta');
function fractionResult($fraction){
list($sup, $sub) = explode('/', $fraction);
if(floatval($sub) != 0){
return $sup / $sub;
}else{
return 0;
}
}
function getCoord($fractional, $ref){
$coord = 0;
if(is_array($fractional)){
$coord = fractionResult($fractional[0]) + fractionResult($fractional[1]) / 60 + fractionResult($fractional[2]) / 3600;
}
if($ref == "S" || $ref == "W"){
$coord = -$coord;
}
return $coord;
}
function getGeodataFromMeta($content){
global $photoMetaCoords;
$postId = get_the_ID();
$attachments = get_posts('post_type=attachment&post_mime_type=image&post_parent=' . $postId);
foreach ($attachments as $attachment){
$meta = wp_get_attachment_metadata($attachment->ID);
if(isset($meta['image_meta']['GPSLatitude'])){
$lat = getCoord($meta['image_meta']['GPSLatitude'], $meta['image_meta']['GPSLatitudeRef']);
$long = getCoord($meta['image_meta']['GPSLongitude'], $meta['image_meta']['GPSLongitudeRef']);
$imageUrl = wp_get_attachment_image_src($attachment->ID, array(133, 133));
$photo = array(
'lat' => $lat,
'lon' => $long,
'uri' => $imageUrl[0]
);
$photoMetaCoords[] = $photo;
}
}
return $content;
}
Last thing we need to do in order to get all this to work is to alter a bit geotag plugin, so it will also load the images from $photoMetaCoords array. In function getGeotagsFromPhotos() add the following line before if (empty($geotags)) {return null;} else… :
$geotags = array_merge($geotags, $photoMetaCoords); $photoMetaCoords = array();
Also at the begining of getGeotagsFromPhotos() function change:
global $post;
to
global $post, $photoMetaCoords;
That`s it!
All the code presented here should be added in functions.php or in geotag.php (except the last line which should always go in geotag.php, of course :) ).



by littlepao
20 May 2010 at 16:23
Hello Lucian,
I try but it shows some error.
I put your two blocks code into functions.php and the last block code into geotag.php.
The first block code is working very well. GeoExif data was save into database.
But it show error below that $photoMetaCoords is not an array.
“Warning: array_merge() [function.array-merge]: Argument #2 is not an array in /home/remotic/domains/remotic.com/public_html/wp/wp-content/plugins/geotag/geotag.php”
What went wrong.
Thanks,
Littlepao
by Lucian Marica
20 May 2010 at 17:53
That warning is raised because $photoMetaCoords variable is not an array. To avoid seeing the error, you should simply initialize the variable somewhere outside the function like this :
but that will not solve the problem.
The variable not being an array means that was not populated. I don`t know why this is happening, but I can help you debug it and solve it.
First check if the $attachments array is populated, with a line like this :
put after $attachments = get_posts( ….. .
If there you have info about the photos attached, do the same thing with variable $meta inside the foreach loop, and post the results.
by littlepao
22 May 2010 at 06:30
Hello Lucian,
I may wrong in adding your code to Geotag, here is my file that need your advice again.
http://www.lepapin.com/geotag-mod.zip
Thank You,
Littlepao
by littlepao
22 May 2010 at 06:31
Hello Lucian,
I just move my blog to http://www.lepapin.com/exif
I may wrong in adding your code to Geotag, here is my file that need your advice again.
http://www.lepapin.com/geotag-mod.zip
Thank You,
Littlepao
by Lucian Marica
22 May 2010 at 18:34
Oups!
I forgot to specify in this tutorial that $photoMetaCoords should be added to global instruction in getGeotagsFromPhotos() function.
Fixed now.
by Marcin
06 Jul 2010 at 20:18
Hi Lucian,
During last few days I am looking for wordpress plugin that works similar to your tutorial. I will try it.
The perfect plugin for me would be:
- i sent email with image attachement from my mobile (no metter what OS I have)
- plugin reeds image exif and email body and place image on map and body as a post
- I can place all sent images on one map
Have you ever heard about such plugin ? If yes please let me know.
:)
by Corey
10 Aug 2010 at 01:11
I am trying to integrate this into my website and I am having problems. I inserted the following code into the geotag.php and made all the changes needed.. No google map is showing up. I added the [gmap] shortcode to the post and the image is attached to the post.
No map at all.. where do I look in the database to check to make sure the geo coordinates are getting taken from the iPhone image?
Thanks.
by Lars
03 Sep 2010 at 11:34
Thank you very much! Works like a charm!
by Lucian Marica
06 Sep 2010 at 18:11
I`m glad you found it useful.
by Lars
07 Sep 2010 at 13:02
Hi Lucian,
okay … perhaps I was a little bit too fast. Unfortunately I now have the problem that not all images in the post are in the $attachments array.
What could be the reason? In the Mediathek, all images are related to the post.
Thanks Lars
by Lucian Marica
07 Sep 2010 at 14:45
Hello Lars,
Just to make sure, you have checked the $attachments array after using get_post? Then the problem must be with get_posts somehow… maybe I am not using it ok. I will investigate the issue.
by Lars
08 Sep 2010 at 10:01
Yes, correct. I checked the $attachments array after using get_post.
by Steve
19 Sep 2011 at 02:46
Hello Lucian, thanks a lot for your nice work, which I’m currently using as a baseline to add some “fancy” features to my photo gallery. Something weird I’ve experienced upon first try is that not all pictures were showing in the map (this might relate to Lars problem).
After a little bit of debugging I’ve found out that the problem was due to a global wordpress settting, which was returning just 5 results. Just modifying the query like this in the function.php file (row 26 in your snippet above) solved the issue:
$attachments = get_posts(‘numberposts=-1&post_type=attachment&post_mime_type=image&post_parent=’ . $postId);
Maybe this can help someone else out there. Again, thanks a lot for your great work!
Steve