Photo

WordPress NextGEN Gallery and GPS data

NextGen(eration) Gallery is a WordPress plugin from Alex Rabe. It provides image galleries, albums with great ease of administration.
As said by the author, it fills a gap in WordPress gallery systems.

It can handle « display » templates, which can be added to the plugin Views or simply in your theme. That’s what I’m working on right now for the Photo Theme I’m using in my new Photo Blog.
This way you don’t have to install another plugin and use hooks.

While it’s working well, it still have some features missing.

One of the missing stuffs is beeing able to display GPS data.
My photo blog have Geo-Tagged pictures. I want to be able to display them along with a google map image so my readers can see where it was taken. I also want to display some of the EXIF informations, like lense type, aperture, shutter speed and so on…

While some of them (most) are already handeled by the NextGen gallery, some of them are not.
NextGen Gallery is using the exif_read_data function to get the data from the file like :

  1. $this->exif_data = @exif_read_data($this->image->imagePath , 0, true );

Then, the RAW exif datas are separated in arrays. When trying to access the EXIF tags (using get_EXIF), only the part of the array under [EXIF] will be used. In fact this is partly false, as the get_EXIF function also dig under IFD0 and WINXP.
As the GPS data from my Nikon D700 are under the [GPS] array, there is no chance that NextGen gallery sees them even if you use the wordpress filter to add some new EXIF tags.

Then you only have one solution : check in the RAW meta-data or… change NextGen so it can handle them in the EXIF tags stored in the database.

So, my solution is divided in few parts :

  • Hardcode some new EXIF tags
  • get the GPS data inside get_EXIF
  • add a function to parse the GPS data and make them readable/usable by Google Map

Let’s do it :

Hardcode some new EXIF tags

In the file lib/meta.php, change the get_common_meta function so it look like :

  1. function get_common_meta() {
  2.                 global $wpdb;
  3.  
  4.                 $meta = array(
  5.                         ‘aperture’ => 0,
  6.                         ‘credit’ =>  »,
  7.                         ‘camera’ =>  »,
  8.                         ‘caption’ =>  »,
  9.                         ‘created_timestamp’ => 0,
  10.                         ‘copyright’ =>  »,
  11.                         ‘focal_length’ => 0,
  12.                         ‘iso’ => 0,
  13.                         ‘shutter_speed’ => 0,
  14.                         ‘flash’ => 0,
  15.                         ‘title’ =>  »,
  16.                         ‘altitude’ =>  »,
  17.                         ‘longitude’ =>  »,
  18.                         ‘latitude’ =>  »,
  19.                         ‘timestamp’ =>  »,
  20.                         ‘datestamp’ =>  »,
  21.                         ‘satellites’ =>  »,
  22.                         ‘direction’ =>  »,
  23.                         ‘lense’ =>  »,
  24.                         ‘keywords’ =>  »
  25.                 );

As you can see, I add all the GPS data, plus « lense », which is just a hook as the EXIF tag for the lense is actualy « UndefinedTag:0xA434″

You can also add the new tags in the i8n translation function

  1. function i8n_name($key) {
  2.  
  3.                 $tagnames = array(
  4.                 ‘aperture’                      => __(‘Aperture’,‘nggallery’),
  5.                 ‘credit’                        => __(‘Credit’,‘nggallery’),
  6.                 ‘camera’                        => __(‘Camera’,‘nggallery’),
  7.                 ‘caption’                       => __(‘Caption’,‘nggallery’),
  8.                 ‘created_timestamp’ => __(‘Date/Time’,‘nggallery’),
  9.                 ‘copyright’             => __(‘Copyright’,‘nggallery’),
  10.                 ‘focal_length’          => __(‘Focal length’,‘nggallery’),
  11.                 ‘iso’                           => __(‘ISO’,‘nggallery’),
  12.                 ‘shutter_speed’         => __(‘Shutter speed’,‘nggallery’),
  13.                 ‘title’                         => __(‘Title’,‘nggallery’),
  14.                 ‘author’                        => __(‘Author’,‘nggallery’),
  15.                 ‘tags’                          => __(‘Tags’,‘nggallery’),
  16.                 ‘subject’                       => __(‘Subject’,‘nggallery’),
  17.                 ‘make’                          => __(‘Make’,‘nggallery’),
  18.                 ‘status’                        => __(‘Edit Status’,‘nggallery’),
  19.                 ‘category’                      => __(‘Category’,‘nggallery’),
  20.                 ‘keywords’                      => __(‘Keywords’,‘nggallery’),
  21.                 ‘created_date’          => __(‘Date Created’,‘nggallery’),
  22.                 ‘created_time’          => __(‘Time Created’,‘nggallery’),
  23.                 ‘position’                      => __(‘Author Position’,‘nggallery’),
  24.                 ‘city’                          => __(‘City’,‘nggallery’),
  25.                 ‘location’                      => __(‘Location’,‘nggallery’),
  26.                 ‘state’                         => __(‘Province/State’,‘nggallery’),
  27.                 ‘country_code’          => __(‘Country code’,‘nggallery’),
  28.                 ‘country’                       => __(‘Country’,‘nggallery’),
  29.                 ‘headline’                      => __(‘Headline’,‘nggallery’),
  30.                 ‘credit’                        => __(‘Credit’,‘nggallery’),
  31.                 ‘source’                        => __(‘Source’,‘nggallery’),
  32.                 ‘copyright’                     => __(‘Copyright Notice’,‘nggallery’),
  33.                 ‘contact’                       => __(‘Contact’,‘nggallery’),
  34.                 ‘last_modfied’          => __(‘Last modified’,‘nggallery’),
  35.                 ‘tool’                          => __(‘Program tool’,‘nggallery’),
  36.                 ‘format’                        => __(‘Format’,‘nggallery’),
  37.                 ‘width’                         => __(‘Image Width’,‘nggallery’),
  38.                 ‘height’                        => __(‘Image Height’,‘nggallery’),
  39.                 ‘flash’                         => __(‘Flash’,‘nggallery’),
  40.                 ‘latitude’                      => __(‘Latitude’,‘nggallery’),
  41.                 ‘longitude’                     => __(‘Longitude’,‘nggallery’),
  42.                 ‘altitude’                      => __(‘Altitude’,‘nggallery’),
  43.                 ‘lense’                      => __(‘Lense’,‘nggallery’),
  44.                 );

get the GPS data inside get_EXIF

Now, every time you insert a new image or re-import the meta-data, the new tags will be asked. We need to change the get_EXIF function so it can find them.
Still in lib/meta.php, go down to the get_EXIF function and change it to  :

  1. function get_EXIF($object = false) {
  2.  
  3.                 if ( !$this->exif_data )
  4.                         return false;
  5.  
  6.                 if (!is_array($this->exif_array)){
  7.  
  8.                         $meta= array();
  9.  
  10.             if ( isset($this->exif_data[‘EXIF’]) ) {
  11.                 $exif = $this->exif_data[‘EXIF’];
  12.  
  13.                         if (!empty($exif[‘FNumber’]))
  14.                                 $meta[‘aperture’] = ‘F ‘ . round( $this->exif_frac2dec( $exif[‘FNumber’] ), 2 );
  15.                         if (!empty($exif[‘Model’]))
  16.                                 $meta[‘camera’] = trim( $exif[‘Model’] );
  17.                         if (!empty($exif[‘DateTimeDigitized’]))
  18.                                 $meta[‘created_timestamp’] = date_i18n(get_option(‘date_format’) . ‘ ‘ . get_option(‘time_format’), $this->exif_date2ts($exif[‘DateTimeDigitized’]));
  19.                         if (!empty($exif[‘FocalLength’]))
  20.                                 $meta[‘focal_length’] = $this->exif_frac2dec( $exif[‘FocalLength’] ) . __(‘ mm’,‘nggallery’);
  21.                         if (!empty($exif[‘ISOSpeedRatings’]))
  22.                                 $meta[‘iso’] = $exif[‘ISOSpeedRatings’];
  23.                         if (!empty($exif[‘ExposureTime’])) {
  24.                                  $meta[‘shutter_speed’]  = $this->exif_frac2dec ($exif[‘ExposureTime’]);
  25.                                  $meta[‘shutter_speed’]  =($meta[‘shutter_speed’] > 0.0 and $meta[‘shutter_speed’] < 1.0) ? ( ’1/’ . round( 1 / $meta[‘shutter_speed’], -1) ) : ($meta[‘shutter_speed’]);
  26.                                  $meta[‘shutter_speed’] .=  __(‘ sec’,‘nggallery’);
  27.                                 }
  28.                         //Bit 0 indicates the flash firing status
  29.                         if (!empty($exif[‘Flash’]))
  30.                                 $meta[‘flash’] =  ( $exif[‘Flash’] & 1 ) ? __(‘Fired’, ‘nggallery’) : __(‘Not fired’,‘ nggallery’);
  31.  
  32.                         if (!empty($exif[‘UndefinedTag:0xA434′]))
  33.                                 $meta[‘lense’] = $exif[‘UndefinedTag:0xA434′];
  34.             }
  35.  
  36.                         // additional information
  37.             if ( isset($this->exif_data[‘IFD0′]) ) {
  38.                         $exif = $this->exif_data[‘IFD0′];
  39.  
  40.                         if (!empty($exif[‘Model’]))
  41.                                 $meta[‘camera’] = $exif[‘Model’];
  42.                         if (!empty($exif[‘Make’]))
  43.                                 $meta[‘make’] = $exif[‘Make’];
  44.                         if (!empty($exif[‘ImageDescription’]))
  45.                                 $meta[‘title’] = utf8_encode($exif[‘ImageDescription’]);
  46.                         if (!empty($exif[‘Orientation’]))
  47.                                 $meta[‘Orientation’] = $exif[‘Orientation’];
  48.             }
  49.             // additional GPS information
  50.             if ( isset($this->exif_data[‘GPS’]) ) {
  51.                         $exif = $this->exif_data[‘GPS’];
  52.                         // send exif data to the function to get GPS on one line
  53.                         if (!empty($exif[‘GPSLatitudeRef’])) {
  54.                                 $GPS=self::get_Exif_GPS($exif, 1);
  55.                                 $meta[‘latitude’] = $GPS[‘latitude’];
  56.                                 $meta[‘longitude’] = $GPS[‘longitude’];
  57.                                 $meta[‘altitude’] = $GPS[‘altitude’]." metres";
  58.                                 $meta[‘timestamp’] = $GPS[‘timestamp’];
  59.                                 $meta[‘direction’] = $GPS[‘direction’];
  60.                                 if (!empty($exif[‘GPSSatellites’]))
  61.                                         $meta[‘satellites’] = $exif[‘GPSSatellites’];
  62.                                 if (!empty($exif[‘GPSDateStamp’]))
  63.                                         $meta[‘datestamp’] = $exif[‘GPSDateStamp’];
  64.                                 }
  65.             }

You can see two things here :
- if the meta asked is « lense », we look for the un-named attribute
- when we are done with EXIF and IFD0, we check in the GPS array

add a function to parse the GPS data and make them readable/usable by Google Map

Now we create the function to re-calculate the GPS coords. Create a function somewhere in the class. A good place is at the end of the lib/meta.php file, just before the last closing bracket.

  1. function get_Exif_GPS($exif, $assoc = false) {
  2.                 //get the Hemisphere multiplier
  3.                 $LatM = 1; $LongM = 1;
  4.                 if($exif["GPSLatitudeRef"] == ‘S’) {
  5.                         $LatM = -1;
  6.                         }
  7.                 if($exif["GPSLongitudeRef"] == ‘W’) {
  8.                         $LongM = -1;
  9.                         }
  10.  
  11.                 //get the GPS data
  12.                 $gps[‘LatDegree’]=$exif["GPSLatitude"][0];
  13.                 $gps[‘LatMinute’]=$exif["GPSLatitude"][1];
  14.                 $gps[‘LatgSeconds’]=$exif["GPSLatitude"][2];
  15.                 $gps[‘LongDegree’]=$exif["GPSLongitude"][0];
  16.                 $gps[‘LongMinute’]=$exif["GPSLongitude"][1];
  17.                 $gps[‘LongSeconds’]=$exif["GPSLongitude"][2];
  18.                 $gps[‘Altitude’]=$exif["GPSAltitude"];
  19.                 $gps[‘TimeHour’]=$exif["GPSTimeStamp"][0];
  20.                 $gps[‘TimeMin’]=$exif["GPSTimeStamp"][1];
  21.                 $gps[‘TimeSec’]=$exif["GPSTimeStamp"][2];
  22.                 $gps[‘direction’]=$exif["GPSImgDirection"];
  23.  
  24.                 //convert strings to numbers
  25.                 foreach($gps as $key => $value) {
  26.                         $pos = strpos($value, ‘/’);
  27.                         if($pos !== false) {
  28.                                 $temp = explode(‘/’,$value);
  29.                                 $gps[$key] = $temp[0] / $temp[1];
  30.                                 }
  31.                         }
  32.  
  33.                 //calculate the decimal degree
  34.                 $result[‘latitude’] = $LatM * ($gps[‘LatDegree’] + ($gps[‘LatMinute’] / 60) + ($gps[‘LatgSeconds’] / 3600));
  35.                 $result[‘longitude’] = $LongM * ($gps[‘LongDegree’] + ($gps[‘LongMinute’] / 60) + ($gps[‘LongSeconds’] / 3600));
  36.                 $result[‘altitude’] = $gps[‘Altitude’];
  37.                 $result[‘timestamp’] = $gps[‘TimeHour’].‘:’.$gps[‘TimeMin’].‘:’.$gps[‘TimeSec’];
  38.                 $result[‘direction’] = $gps[‘direction’];
  39.  
  40.                 if($assoc) {
  41.                         return $result;
  42.                         }
  43.  
  44.                 return json_encode($result);
  45.         }

Conclusion

Re-importing the meta-data of all your pictures should add the new stuffs.

I’v posted in the WordPress forum and asked for this to be added to the NextGen Gallery dev tree. Still have no answer for now. Maybe someone will come with a better code or better idea ?
I also asked for someone to check how GPS data are included in files from other brands as I can only tell for the Nikon’s D700.

New gallery: ete-2010

Vacances d’été 2010 en Provence (04) et dans les Alpes (05)
Lire la suite de l’article »

Introducing new Photo Blog

As I’ve just stopped working for SPI (Casino Barriere and La Française des Jeux), I have to fill my days. And hopefully, I do have a lot of stuffs going on here…
Starting with all my video stuffs and my creation stuffs, like the Remote Follow Focus I’m building with an Arduino.

I also got a video stabilizer (a steadycam) from l’Aigle, which was my past article. It’s a lot of work and practice to get it right and use it right.

As you know I’m also into static photography, and I bought a Nikon D700 last year to use with the lenses I put on the camcorder with the Shoot35 SG-Blade.

I finaly bought two new optics, a Nikon 35-70 macro f2.8 and the new Samyang 14mm manual prime.
This puts me in more photography, and I wanted to be full equiped. I also bought a flashlight (Nissin), a remote shutter and a lightweight carbon tripod from Benro. I just ordered a Nikon compatible GPS to geo-tag the pictures so I can link them easily to Google map…

The final part missing is « what the hell will I do with all this photos… ». I do have the capacity to hold them in the RAID tower I built last year, but that’s not the point. I want to SHARE.

Picasa is fine, so is Fliker… But I’m not in the easy thing, and I want to do more. So I made a « photo » blog.

The real thing is that it’s not a photo-blog. It’s not only photo… But it will evolve, and the goal remain to be focused of photo.
So there you go :

http://blog.lecentre.net

New gallery: Autres


dsc_5693

A new gallery: Autres
Lire la suite de l’article »

New gallery: Mouchette


dsc_5220

A new gallery: Mouchette
Lire la suite de l’article »

Salon Agriculture 2010

Des vaches, des vaches, mais pas seulement…

DSC_2534

Lire la suite de l’article »

Nikon D700 with Auto-ISO mode, still feat. Mouchette

I tried Auto-ISO with the Aperture First mode.
As I’m using Prime (fixed) lenses, I can play the aperture on the lense (defined as a « no CPU lense, so the D700 knows exactly which aperture I’m in) and have the D700 manage the shutter speed and, if needed, the ISO level, with a max at 3200 ISO.
I also think I’ll have to adjust the dioptrie on the viewfinder…

This is full RAW converted to PNG 150dpi (original is 240dpi).
mouchette22 mouchette21

Nikon D700 first test (feat. Mouchette)

images
First tests with the Nikon D700 and manual lenses.
With really low light and no knowledge of the camera, see how beautiful Mouchette can be :)

mouchette1
Lire la suite de l’article »