I’ve searched everywhere for this but couldn’t find the solution, so I decided to write my own class for this in PHP. Some what I succeed in it with iPhone image file and instagram image but I am not sure if it works with all other cameras especially with Android supported phones and cameras with GPS. Can anyone help me out with this? Below is my code and its implementation.
<?php
class Filer {
/**
* Some Variables
*/
private $_gpsLatitude;
private $_gpsLongitude;
private $_gpsLatitudeRef;
private $_gpsLongitudeRef;
/**
* Constructor Method
*/
public function __construct(){
/**
* GPS Meta (In reference to iphone's image file)
* May be Android folow the same thing (Haven't checked)
*/
$this->_gpsLatitude = 'GPSLatitude';
$this->_gpsLongitude = 'GPSLongitude';
$this->_GPSLongitudeRef = 'GPSLatitudeRef';
$this->_gpsLongitudeRef = 'GPSLongitudeRef';
}
/**
* Check if the file contains GPS information
* @param: (string)$_file
* @return: (array) File's EXIF data (If the file contains GPS information)
*/
public function getCoordinate($_file){
$_Metas = $this->checkGPS($_file);
$_GPS = $_Metas['GPS'];
$_latitude = $this->DMStoDEC(
$_GPS[$this->_gpsLatitude][0],
$_GPS[$this->_gpsLatitude][1],
$_GPS[$this->_gpsLatitude][2],
$_GPS[$this->_GPSLongitudeRef]
);
$_longitude = $this->DMStoDEC(
$_GPS[$this->_gpsLongitude][0],
$_GPS[$this->_gpsLongitude][1],
$_GPS[$this->_gpsLongitude][2],
$_GPS[$this->_gpsLongitudeRef]
);
$_location = array($_latitude, $_longitude);
return $_location;
}
/**
* Check if the file contains GPS information
* @param: (string)$_file
* @return: (array) File's EXIF data (If the file contains GPS information)
*/
public function checkGPS($_file){
return exif_read_data($_file, 'GPS', true);
}
/**
* Get Meta information of file
* @param: (string)$_file
* @return: (array) File's EXIF data
*
*/
public function getExif($_file){
return exif_read_data($_file, 'IFD0', true);
}
/**
* Converts DMS ( Degrees / Minutes / Seconds )
* To decimal format longitude / latitude
* @param: (string)$_deg, (string)$_min, (string)$_sec, (string)$_ref
* @return: (float)
*/
private function DMStoDEC($_deg, $_min, $_sec, $_ref){
$_array = explode('/', $_deg);
$_deg = $_array[0]/$_array[1];
$_array = explode('/', $_min);
$_min = $_array[0]/$_array[1];
$_array = explode('/', $_sec);
$_sec = $_array[0]/$_array[1];
$_coordinate = $_deg+((($_min*60)+($_sec))/3600);
/**
* + + = North/East
* + - = North/West
* - - = South/West
* - + = South/East
*/
if('s' === strtolower($_ref) || 'w' === strtolower($_ref)){
// Negatify the coordinate
$_coordinate = 0-$_coordinate;
}
return $_coordinate;
}
/**
*
* Converts decimal longitude / latitude to DMS
* ( Degrees / minutes / seconds )
*
* This is the piece of code which may appear to
* be inefficient, but to avoid issues with floating
* point math we extract the integer part and the float
* part by using a string function.
* @param: (string)$_file
* @return: (array)
*/
private function DECtoDMS($_dec){
$_vars = explode(".", $_dec);
$_deg = $vars[0];
$_tempma = "0.".$_vars[1];
$_tempma = $_tempma * 3600;
$_min = floor($_tempma / 60);
$_sec = $_tempma - ($_min*60);
return array("deg"=>$_deg, "min"=>$_min, "sec"=>$_sec);
}
} // End class
/**
*
* Usage Example
*
*/
$_file = './image2.jpg';
$_Filer = new Filer();
if($_Filer->checkGPS($_file)){
$_location = $_Filer->getCoordinate($_file);
// File doesn't have GPS information
echo '<h4>File\'s GPS information</h4>';
var_dump($_location);
} else {
// File doesn't have GPS information
echo '<h4>Sorry your file doesn\'t supply GPS information</h4>';
var_dump($_Filer->getExif($_file));
}
?>
The Exiv2 documentation has an excellent tags reference which may help you identify fields you may have missed. Your implementation otherwise looks pretty solid to me, I can’t see any glaring errors.
Exif Tags supported by Exiv2