PHP özü GPS EXIF ​​verileri

8 Cevap php

I would like to extract the GPS EXIF tag from pictures using php. I'm using the exif_read_data() that returns a array of all tags + data :

GPS.GPSLatitudeRef: N
GPS.GPSLatitude:Array ( [0] => 46/1 [1] => 5403/100 [2] => 0/1 ) 
GPS.GPSLongitudeRef: E
GPS.GPSLongitude:Array ( [0] => 7/1 [1] => 880/100 [2] => 0/1 ) 
GPS.GPSAltitudeRef: 
GPS.GPSAltitude: 634/1

Ben 46/1 5403/100 ve 0/1 yorumlamak için nasıl bilmiyorum? 46 46 ° ama ne özellikle 0/1 kalanı hakkında olabilir?

angle/1 5403/100 0/1

Hakkında bu yapısı nedir?

Nasıl onları (wikipedia dan 46 ° 56'48 "N 7 ° 26'39" E gibi) "standart" olanlar dönüştürmek için? Ben bir harita üzerinde resimleri konumlarını görüntülemek için Google Maps API için thoses koordinatları geçmek istiyorum!

8 Cevap

http://en.wikipedia.org/wiki/Geotagging, ( [0] => 46/1 [1] => 5403/100 [2] => 0/1 ) 46/1 derece, 5403/100 dakika, 0/1 saniye, yani 46 ° 54.03 '0 "N. demek gerekir göre Saniye normalleştirilmesi 46 ° 54'1 .8 "incelemeleri verir

Aşağıda bu kodu (sen N / S almak ve koordine ayrı olarak W E /, hiç negatif koordinatlar olması gerektiğini verilen) sürece negatif koordinatlar alamadım gibi çalışması gerekir. Bir hata (ben şu anda kullanışlı bir PHP ortam yok) varsa bana bildirin.

//Pass in GPS.GPSLatitude or GPS.GPSLongitude or something in that format
function getGps($exifCoord)
{
  $degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0;
  $minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0;
  $seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0;

  //normalize
  $minutes += 60 * ($degrees - floor($degrees));
  $degrees = floor($degrees);

  $seconds += 60 * ($minutes - floor($minutes));
  $minutes = floor($minutes);

  //extra normalization, probably not necessary unless you get weird data
  if($seconds >= 60)
  {
    $minutes += floor($seconds/60.0);
    $seconds -= 60*floor($seconds/60.0);
  }

  if($minutes >= 60)
  {
    $degrees += floor($minutes/60.0);
    $minutes -= 60*floor($minutes/60.0);
  }

  return array('degrees' => $degrees, 'minutes' => $minutes, 'seconds' => $seconds);
}

function gps2Num($coordPart)
{
  $parts = explode('/', $coordPart);

  if(count($parts) <= 0)// jic
    return 0;
  if(count($parts) == 1)
    return $parts[0];

  return floatval($parts[0]) / floatval($parts[1]);
}

Bu benim değiştirilmiş versiyonu. Diğerleri benim için işe yaramadı. Size GPS koordinatları ondalık sürümlerini verecektir.

EXIF verileri işlemek için kod:

$exif = exif_read_data($filename);
$lon = getGps($exif["GPSLongitude"], $exif['GPSLongitudeRef']);
$lat = getGps($exif["GPSLatitude"], $exif['GPSLatitudeRef']);
var_dump($lat, $lon);

Bu formatta yazdıran:

float(-33.8751666667)
float(151.207166667)

İşte bu fonksiyonlar:

function getGps($exifCoord, $hemi) {

    $degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0;
    $minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0;
    $seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0;

    $flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1;

    return $flip * ($degrees + $minutes / 60 + $seconds / 3600);

}

function gps2Num($coordPart) {

    $parts = explode('/', $coordPart);

    if (count($parts) <= 0)
        return 0;

    if (count($parts) == 1)
        return $parts[0];

    return floatval($parts[0]) / floatval($parts[1]);
}

Bu soru uzun zaman önce sorulmuş biliyorum, ama google arama ve burada önerilen çözümler benim için çalıştı değil ise ben karşıya geldi. Yani, daha fazla arama yaptıktan sonra, burada benim için çalıştı budur.

Bazı googling ile buraya gelen herkes, aynı sorunu çözmek için farklı yaklaşımlar bulmak böylece ben burada koyuyorum:

function triphoto_getGPS($fileName, $assoc = false)
{
    //get the EXIF
    $exif = exif_read_data($fileName);

    //get the Hemisphere multiplier
    $LatM = 1; $LongM = 1;
    if($exif["GPSLatitudeRef"] == 'S')
    {
    $LatM = -1;
    }
    if($exif["GPSLongitudeRef"] == 'W')
    {
    $LongM = -1;
    }

    //get the GPS data
    $gps['LatDegree']=$exif["GPSLatitude"][0];
    $gps['LatMinute']=$exif["GPSLatitude"][1];
    $gps['LatgSeconds']=$exif["GPSLatitude"][2];
    $gps['LongDegree']=$exif["GPSLongitude"][0];
    $gps['LongMinute']=$exif["GPSLongitude"][1];
    $gps['LongSeconds']=$exif["GPSLongitude"][2];

    //convert strings to numbers
    foreach($gps as $key => $value)
    {
    $pos = strpos($value, '/');
    if($pos !== false)
    {
        $temp = explode('/',$value);
        $gps[$key] = $temp[0] / $temp[1];
    }
    }

    //calculate the decimal degree
    $result['latitude'] = $LatM * ($gps['LatDegree'] + ($gps['LatMinute'] / 60) + ($gps['LatgSeconds'] / 3600));
    $result['longitude'] = $LongM * ($gps['LongDegree'] + ($gps['LongMinute'] / 60) + ($gps['LongSeconds'] / 3600));

    if($assoc)
    {
    return $result;
    }

    return json_encode($result);
}

Bu Gerald Kaszuba kodunun (şu anda en yaygın kabul gören cevap) bir refactored sürümüdür. Sonuç aynı olmalı, ama ben birine iki ayrı işlevi birkaç mikro-optimizasyonlar yapılmış ve kombine ettik. Benim kriter test, bu sürüm muhtemelen çoğu uygulamalar için ihmal edilebilir çalışma, kapalı yaklaşık 5 mikrosaniye traş, ancak tekrarlanan hesaplamalar çok sayıda içeren uygulamalar için yararlı olabilir.

$exif = exif_read_data($filename);
$latitude = gps($exif["GPSLatitude"], $exif['GPSLatitudeRef']);
$longitude = gps($exif["GPSLongitude"], $exif['GPSLongitudeRef']);

function gps($coordinate, $hemisphere) {
  for ($i = 0; $i < 3; $i++) {
    $part = explode('/', $coordinate[$i]);
    if (count($part) == 1) {
      $coordinate[$i] = $part[0];
    } else if (count($part) == 2) {
      $coordinate[$i] = floatval($part[0])/floatval($part[1]);
    } else {
      $coordinate[$i] = 0;
    }
  }
  list($degrees, $minutes, $seconds) = $coordinate;
  $sign = ($hemisphere == 'W' || $hemisphere == 'S') ? -1 : 1;
  return $sign * ($degrees + $minutes/60 + $seconds/3600);
}

Ben geçmişte kullanmış olduğunuz kodu (gerçekte, o da belli belirsiz verilerin geçerli olup olmadığını kontrol eder) gibi bir şeydir:

// Latitude
$northing = -1;
if( $gpsblock['GPSLatitudeRef'] && 'N' == $gpsblock['GPSLatitudeRef'] )
{
    $northing = 1;
}

$northing *= defraction( $gpsblock['GPSLatitude'][0] ) + ( defraction($gpsblock['GPSLatitude'][1] ) / 60 ) + ( defraction( $gpsblock['GPSLatitude'][2] ) / 3600 );

// Longitude
$easting = -1;
if( $gpsblock['GPSLongitudeRef'] && 'E' == $gpsblock['GPSLongitudeRef'] )
{
    $easting = 1;
}

$easting *= defraction( $gpsblock['GPSLongitude'][0] ) + ( defraction( $gpsblock['GPSLongitude'][1] ) / 60 ) + ( defraction( $gpsblock['GPSLongitude'][2] ) / 3600 );

Ayrıca var burada:

function defraction( $fraction )
{
    list( $nominator, $denominator ) = explode( "/", $fraction );

    if( $denominator )
    {
        return ( $nominator / $denominator );
    }
    else
    {
        return $fraction;
    }
}

Eğer biraz daha sofistike bir yazılım ile EXIF ​​verilerini verebilirsiniz? Doğru çıkış bilmek size algoritma anlamaya yardımcı olur.

I'm using the modified version from Gerald Kaszuba but it's not accurate. so i change the formula a bit.

dan:

return $flip * ($degrees + $minutes / 60);

değiştirildi:

return floatval($flip * ($degrees +($minutes/60)+($seconds/3600)));

Bu benim için çalışıyor.

Bu GPS verileri ile:

    ["GPSLatitudeRef"]=>
    string(1) "N"
    ["GPSLatitude"]=>
    array(3) {
        [0]=>
        string(7) "65539/0"
        [1]=>
        string(17) "-1542717440/65539"
        [2]=>
        string(8) "196608/0"
    }
    ["GPSLongitudeRef"]=>
    string(1) "E"
    ["GPSLongitude"]=>
    array(3) {
        [0]=>
        string(20) "39321600/-1166016512"
        [1]=>
        string(21) "1111490956/1811939343"
        [2]=>
        string(22) "1111491292/-1725956081"
    }

Yukarıdaki kod (teşekkürler Gerald) kullanarak ben bu Latitude olsun & Boylam değerleri:

-392.31537456069,-0.023678137550796

Bu doğru değildir. Bu kod çalışır gibi başımı yapıyor, ama cevap bu durumda yanlış! Birçok diğer görüntüler iyi çalışır, sadece bu DAT şey karşılamak için eksik bazı mantık gibi görünüyor. IPhoto için görüntü yüklemek Örneğin, (Mac'ler olmayanlar için Apple örneğin özür dilerim) bu doğru cevabı alır; Bu EXIF ​​verileri Kızıl Denizi yakınlarındaki bir resim için.