macocci7 / php-photo-gps
Retrieves EXIF GPS data from a photo.
Requires
- intervention/image: ^3.7
- nette/neon: ^3.4
Requires (Dev)
- php-parallel-lint/php-parallel-lint: 1.4
- phpmd/phpmd: ^2.15
- phpstan/phpstan: ^1.11
- phpunit/phpunit: ^10.5
- squizlabs/php_codesniffer: ^3.7
README
1. Features
PHP-PhotoGps
is a simple library to get GPS data from a photo.
This library reads EXIF data of a jpeg file,
and can convert latitude/longitude into sexagesimal(English/Japanese) or decimal formats,
converts directions into degree with arrow images ,
converts speeds, date stamps and time stamps into human-readable strings.
Remote files (via http: or https:) are supported.
Supported Exif Versions:
- 3.0
- 2.32
- 2.31
- 2.3
- 2.21
- 2.2
- 2.1
2. Contents
- 1. Features
- 2. Contents
- 3. Requirements
- 4. Installation
- 5. Usage
- 6. Examples
- 7. LICENSE
- 8. Changelog
3. Requirements
-
PHP 8.1 or later
-
GD library enabled
check with commands:
(php -m; php -i) | grep gd
-
Exif enabled
check with commands:
(php -m; php -i) | grep exif
4. Installation
composer require macocci7/php-photo-gps
5. Usage
- 5.1. Usage: Basic
- 5.2. Usage: Format Configuration
- 5.3. Usage: Photo List with Checking Geo Data
- 5.4. Usage: Read All GPS Tags
- 5.5. Usage: GPS Attribute Information
5.1. Usage: Basic
5.1.1. PHP
-
<?php require_once __DIR__ . '/../vendor/autoload.php'; use Macocci7\PhpPhotoGps\PhotoGps; $filename = 'img/with_gps.jpg'; // includes GPS tags $pg = new PhotoGps($filename); echo "[" . $filename . "]--------------------\n"; // Latitude in sexagesimal format echo "Latitude: " . $pg->latitudeS() . "\n"; echo "緯度: " . $pg->lang('ja')->latitudeS() . "\n"; // Longitude in sexagesimal format echo "Longitude: " . $pg->lang('eng')->longitudeS() . "\n"; echo "経度: " . $pg->lang('ja')->longitudeS() . "\n"; // Altitude as strings echo "Altitude: " . $pg->lang('eng')->altitudeS() . "\n"; echo "高度: " . $pg->lang('ja')->altitudeS() . "\n"; // Coord in decimal format ('S' and 'W' results in negative value.) echo "Coord: " . $pg->latitudeD() . ", " . $pg->longitudeD() . "\n";
5.1.2. Output
-
[img/with_gps.jpg]-------------------- Latitude: 37°3'26.2"N 緯度: 北緯37度3分26.2秒 Longitude: 140°53'32.8"E 経度: 東経140度53分32.8秒 Altitude: (Above Ellipsoidal Surface) 13.00 m 高度: (正値楕円体高) 13.00 メートル Coord: 37.057274166667, 140.89244166667
5.1.3. Details
-
Import autoloader:
require_once __DIR__ . '/../vendor/autoload.php'
-
use
declaration:use Macocci7\PhpPhotoGps\PhotoGps;
-
Instantiation:
new PhotoGps()
ornew PhotoGps($path)
- Note: If HTTP or HTTPS url is specified as
$path
,download
directory will be created in current directory, and the image will be downloaded in it.
- Note: If HTTP or HTTPS url is specified as
-
Language:
eng
as default.- Get Current:
lang()
- Set as English:
lang('eng')
- Set as Japanese:
lang('ja')
Language Names are defined in
config/PhotoGps.neon
. - Get Current:
-
Latitude:
- Decimal:
latitudeD()
- Sexagesimal:
latitudeS()
- Decimal:
-
Longitude:
- Decimal:
longitudeD()
- Sexagesimal:
longitudeS()
- Decimal:
-
Altitude:
- Decimal:
altitude()
- Strings with prefix & unit:
altitudeS()
- Decimal:
5.2. Usage: Format Configuration
- 5.2.1. Geo Data Format
- 5.2.2. Direction Data Format
- 5.2.3. Speed Data Format
- 5.2.4. Datestamp Data Fromat
- 5.2.5. Timestamp Data Format
5.2.1. Geo Data Format
for latitudeS()
and longitudeS()
.
5.2.1.1. PHP
-
<?php require_once __DIR__ . '/../vendor/autoload.php'; use Macocci7\PhpPhotoGps\PhotoGps; $filename = 'img/with_gps.jpg'; // includes GPS tags $pg = new PhotoGps($filename); echo "[" . $filename . "]--------------------\n"; // Format: default echo "Current format [eng]: " . $pg->lang('eng')->format() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->format() . "\n\n"; // Latitude in sexagesimal format echo "Latitude: " . $pg->lang('eng')->latitudeS() . "\n"; echo "緯度: " . $pg->lang('ja')->latitudeS() . "\n"; // Longitude in sexagesimal format echo "Longitude: " . $pg->lang('eng')->longitudeS() . "\n"; echo "経度: " . $pg->lang('ja')->longitudeS() . "\n\n"; echo "[Chang format:eng]---------------------------------\n"; // Configure format $pg->lang('eng')->format('{ref:u}: {seconds:v}{seconds:u}, {minutes:v}{minutes:u}, {degrees:v}{degrees:u}'); // Current format echo "Current format [eng]: " . $pg->lang('eng')->format() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->format() . "\n\n"; // Latitude in sexagesimal format echo "Latitude: " . $pg->lang('eng')->latitudeS() . "\n"; echo "緯度: " . $pg->lang('ja')->latitudeS() . "\n"; // Longitude in sexagesimal format echo "Longitude: " . $pg->lang('eng')->longitudeS() . "\n"; echo "経度: " . $pg->lang('ja')->longitudeS() . "\n\n"; echo "[Change format:ja]---------------------------------\n"; // Configure format $pg->lang('ja')->format('{seconds:v}{seconds:u}, {minutes:v}{minutes:u}, {degrees:v}{degrees:u} ({ref:u})'); // Current format echo "Current format [eng]: " . $pg->lang('eng')->format() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->format() . "\n\n"; // Latitude in sexagesimal format echo "Latitude: " . $pg->lang('eng')->latitudeS() . "\n"; echo "緯度: " . $pg->lang('ja')->latitudeS() . "\n"; // Longitude in sexagesimal format echo "Longitude: " . $pg->lang('eng')->longitudeS() . "\n"; echo "経度: " . $pg->lang('ja')->longitudeS() . "\n\n"; echo "[Reset format:ja]---------------------------------\n"; // Reset format $pg->lang('ja')->resetFormat(); // Current format echo "Current format [eng]: " . $pg->lang('eng')->format() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->format() . "\n\n"; // Latitude in sexagesimal format echo "Latitude: " . $pg->lang('eng')->latitudeS() . "\n"; echo "緯度: " . $pg->lang('ja')->latitudeS() . "\n"; // Longitude in sexagesimal format echo "Longitude: " . $pg->lang('eng')->longitudeS() . "\n"; echo "経度: " . $pg->lang('ja')->longitudeS() . "\n\n";
5.2.1.2. Output
-
[img/with_gps.jpg]-------------------- Current format [eng]: {degrees:v}{degrees:u}{minutes:v}{minutes:u}{seconds:v}{seconds:u}{ref:u} Current format [ja]: {ref:u}{degrees:v}{degrees:u}{minutes:v}{minutes:u}{seconds:v}{seconds:u} Latitude: 37°3'26.2"N 緯度: 北緯37度3分26.2秒 Longitude: 140°53'32.8"E 経度: 東経140度53分32.8秒 [Chang format:eng]--------------------------------- Current format [eng]: {ref:u}: {seconds:v}{seconds:u}, {minutes:v}{minutes:u}, {degrees:v}{degrees:u} Current format [ja]: {ref:u}{degrees:v}{degrees:u}{minutes:v}{minutes:u}{seconds:v}{seconds:u} Latitude: N: 26.2", 3', 37° 緯度: 北緯37度3分26.2秒 Longitude: E: 32.8", 53', 140° 経度: 東経140度53分32.8秒 [Change format:ja]--------------------------------- Current format [eng]: {ref:u}: {seconds:v}{seconds:u}, {minutes:v}{minutes:u}, {degrees:v}{degrees:u} Current format [ja]: {seconds:v}{seconds:u}, {minutes:v}{minutes:u}, {degrees:v}{degrees:u} ({ref:u}) Latitude: N: 26.2", 3', 37° 緯度: 26.2秒, 3分, 37度 (北緯) Longitude: E: 32.8", 53', 140° 経度: 32.8秒, 53分, 140度 (東経) [Reset format:ja]--------------------------------- Current format [eng]: {ref:u}: {seconds:v}{seconds:u}, {minutes:v}{minutes:u}, {degrees:v}{degrees:u} Current format [ja]: {ref:u}{degrees:v}{degrees:u}{minutes:v}{minutes:u}{seconds:v}{seconds:u} Latitude: N: 26.2", 3', 37° 緯度: 北緯37度3分26.2秒 Longitude: E: 32.8", 53', 140° 経度: 東経140度53分32.8秒
5.2.1.3. Details
-
Get Format:
format()
-
Set Format:
format($format)
-
Reset Format:
resetFormat()
-
Default Format:
{ref:u}{degrees:v}{degrees:u}{minutes:v}{minutes:u}{seconds:v}{seconds:u}
-
Format-Tags:
-
latitudeS()
andlongitudeS()
use common format.
5.2.2. Direction Data Format
for directionS()
, destBearingS()
and TrackS()
.
5.2.2.1. PHP
-
<?php require_once __DIR__ . '/../vendor/autoload.php'; use Macocci7\PhpPhotoGps\PhotoGps; $filename = 'img/with_gps.jpg'; $pg = new PhotoGps($filename); echo "[" . $filename . "]--------------------\n"; // Format: default echo "Current format [eng]: " . $pg->lang('eng')->directionFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->directionFormat() . "\n\n"; // Image Direction: default format echo "Image Direction [eng]: " . $pg->lang('eng')->directionS() . "\n"; echo "Image Direction [ja]: " . $pg->lang('ja')->directionS() . "\n\n"; // Configure Format: eng $pg->lang('eng')->directionFormat('{degrees:v}{degrees:u}({ref})'); // Current Format echo "Current format [eng]: " . $pg->lang('eng')->directionFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->directionFormat() . "\n\n"; // Image Direction: Current Format echo "Image Direction [eng]: " . $pg->lang('eng')->directionS() . "\n"; echo "Image Direction [ja]: " . $pg->lang('ja')->directionS() . "\n\n"; // Configure Format: ja $pg->lang('ja')->directionFormat('{degrees:v}{degrees:u}'); // Reset Format: eng $pg->lang('eng')->resetDirectionFormat(); // Current Format echo "Current format [eng]: " . $pg->lang('eng')->directionFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->directionFormat() . "\n\n"; // Image Direction: Current Format echo "Image Direction [eng]: " . $pg->lang('eng')->directionS() . "\n"; echo "Image Direction [ja]: " . $pg->lang('ja')->directionS() . "\n\n";
5.2.2.2. Output
-
[img/with_gps.jpg]-------------------- Current format [eng]: {ref} {degrees:v}{degrees:u} Current format [ja]: {ref} {degrees:v}{degrees:u} Image Direction [eng]: T 306.25° Image Direction [ja]: 真北 306.25度 Current format [eng]: {degrees:v}{degrees:u}({ref}) Current format [ja]: {ref} {degrees:v}{degrees:u} Image Direction [eng]: 306.25°(T) Image Direction [ja]: 真北 306.25度 Current format [eng]: {ref} {degrees:v}{degrees:u} Current format [ja]: {degrees:v}{degrees:u} Image Direction [eng]: T 306.25° Image Direction [ja]: 306.25度
5.2.2.3. Details
-
Get Format:
directionFormat()
-
Set Format:
directionFormat($format)
-
Reset Format:
resetDirectionFormat()
-
Default Format:
{ref} {degrees:v}{degrees:u}
-
Format-Tags:
-
directionS()
,destBearingS()
andTrackS()
use common format.
5.2.3. Speed Data Format
for speedS()
5.2.3.1. PHP
-
<?php require_once __DIR__ . '/../vendor/autoload.php'; use Macocci7\PhpPhotoGps\PhotoGps; $filename = 'img/with_gps.jpg'; $pg = new PhotoGps($filename); echo "[" . $filename . "]--------------------\n"; // Format: default echo "Current format [eng]: " . $pg->lang('eng')->speedFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->speedFormat() . "\n\n"; // Speed: default format echo "Speed [eng]: " . $pg->lang('eng')->speedS() . "\n"; echo "Speed [ja]: " . $pg->lang('ja')->speedS() . "\n\n"; // Configure Format: eng $pg->lang('eng')->speedFormat('{speed:v}({speed:u})'); // Current Format echo "Current format [eng]: " . $pg->lang('eng')->speedFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->speedFormat() . "\n\n"; // Speed: Current Format echo "Speed [eng]: " . $pg->lang('eng')->speedS() . "\n"; echo "Speed [ja]: " . $pg->lang('ja')->speedS() . "\n\n"; // Configure Format: ja $pg->lang('ja')->speedFormat('時速{speed:v}マイル'); // Reset Format: eng $pg->lang('eng')->resetSpeedFormat(); // Current Format echo "Current format [eng]: " . $pg->lang('eng')->speedFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->speedFormat() . "\n\n"; // Speed: Current Format echo "Speed [eng]: " . $pg->lang('eng')->speedS() . "\n"; echo "Speed [ja]: " . $pg->lang('ja')->speedS() . "\n\n";
5.2.3.2. Output
-
[img/with_gps.jpg]-------------------- Current format [eng]: {speed:v}{speed:u} Current format [ja]: {speed:v}{speed:u} Speed [eng]: 1.60mph Speed [ja]: 1.60マイル/時 Current format [eng]: {speed:v}({speed:u}) Current format [ja]: {speed:v}{speed:u} Speed [eng]: 1.60(mph) Speed [ja]: 1.60マイル/時 Current format [eng]: {speed:v}{speed:u} Current format [ja]: 時速{speed:v}マイル Speed [eng]: 1.60mph Speed [ja]: 時速1.60マイル
5.2.3.3. Details
-
Get Format:
speedFormat()
-
Set Format:
speedFormat($format)
-
Reset Format:
resetSpeedFormat()
-
Default Format:
{speed:v}{speed:u}
-
Format-Tags:
5.2.4. Datestamp Data Format
for datestamp()
5.2.4.1. PHP
-
<?php require_once __DIR__ . '/../vendor/autoload.php'; use Macocci7\PhpPhotoGps\PhotoGps; $filename = 'img/with_gps.jpg'; $pg = new PhotoGps($filename); echo "[" . $filename . "]--------------------\n"; // Format: default echo "Current format [eng]: " . $pg->lang('eng')->datestampFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->datestampFormat() . "\n\n"; // Datestamp: default format echo "Datestamp [eng]: " . $pg->lang('eng')->datestamp() . "\n"; echo "Datestamp [ja]: " . $pg->lang('ja')->datestamp() . "\n\n"; // Configure Format: eng $pg->lang('eng')->datestampFormat('l jS \of F Y'); // Current Format echo "Current format [eng]: " . $pg->lang('eng')->datestampFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->datestampFormat() . "\n\n"; // Datestamp: Current Format echo "Datestamp [eng]: " . $pg->lang('eng')->datestamp() . "\n"; echo "Datestamp [ja]: " . $pg->lang('ja')->datestamp() . "\n\n"; // Configure Format: ja $pg->lang('ja')->datestampFormat('n月j日(\'y)'); // Reset Format: eng $pg->lang('eng')->resetDatestampFormat(); // Current Format echo "Current format [eng]: " . $pg->lang('eng')->datestampFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->datestampFormat() . "\n\n"; // Datestamp: Current Format echo "Datestamp [eng]: " . $pg->lang('eng')->datestamp() . "\n"; echo "Datestamp [ja]: " . $pg->lang('ja')->datestamp() . "\n\n";
5.2.4.2. Output
-
[img/with_gps.jpg]-------------------- Current format [eng]: Y/m/d Current format [ja]: Y年m月d日 Datestamp [eng]: 2023/09/18 Datestamp [ja]: 2023年09月18日 Current format [eng]: l jS \of F Y Current format [ja]: Y年m月d日 Datestamp [eng]: Monday 18th of September 2023 Datestamp [ja]: 2023年09月18日 Current format [eng]: Y/m/d Current format [ja]: n月j日('y) Datestamp [eng]: 2023/09/18 Datestamp [ja]: 9月18日('23)
5.2.4.3. Details
- Get Format:
datestampFormat()
- Set Format:
datestampFormat($format)
- Reset Format:
resetDatestampFormat()
- Default Format:
eng
:Y/m/d
ja
:Y年m月d日
- Format parameter strings: See PHP Official
5.2.5. Timestamp Data Format
for timestamp()
5.2.5.1. PHP
-
<?php require_once __DIR__ . '/../vendor/autoload.php'; use Macocci7\PhpPhotoGps\PhotoGps; $filename = 'img/with_gps.jpg'; $pg = new PhotoGps($filename); echo "[" . $filename . "]--------------------\n"; // Format: default echo "Current format [eng]: " . $pg->lang('eng')->timestampFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->timestampFormat() . "\n\n"; // Timestamp: default format echo "Timestamp [eng]: " . $pg->lang('eng')->timestamp() . "\n"; echo "Timestamp [ja]: " . $pg->lang('ja')->timestamp() . "\n\n"; // Configure Format: eng $pg->lang('eng')->timestampFormat('g:i a'); // Current Format echo "Current format [eng]: " . $pg->lang('eng')->timestampFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->timestampFormat() . "\n\n"; // Timestamp: Current Format echo "Timestamp [eng]: " . $pg->lang('eng')->timestamp() . "\n"; echo "Timestamp [ja]: " . $pg->lang('ja')->timestamp() . "\n\n"; // Configure Format: ja $pg->lang('ja')->timestampFormat('G時i分s秒'); // Reset Format: eng $pg->lang('eng')->resetTimestampFormat(); // Current Format echo "Current format [eng]: " . $pg->lang('eng')->timestampFormat() . "\n"; echo "Current format [ja]: " . $pg->lang('ja')->timestampFormat() . "\n\n"; // Timestamp: Current Format echo "Timestamp [eng]: " . $pg->lang('eng')->timestamp() . "\n"; echo "Timestamp [ja]: " . $pg->lang('ja')->timestamp() . "\n\n";
5.2.5.2. Output
-
[img/with_gps.jpg]-------------------- Current format [eng]: H:i:s Current format [ja]: H時i分s秒 Timestamp [eng]: 03:43:32 Timestamp [ja]: 03時43分32秒 Current format [eng]: g:i a Current format [ja]: H時i分s秒 Timestamp [eng]: 3:43 am Timestamp [ja]: 03時43分32秒 Current format [eng]: H:i:s Current format [ja]: G時i分s秒 Timestamp [eng]: 03:43:32 Timestamp [ja]: 3時43分32秒
5.2.5.3. Details
- Get Format:
timestampFormat()
- Set Format:
timestampFormat($format)
- Reset Format:
resetTimestampFormat()
- Default Format:
eng
:H:i:s
ja
:H時i分s秒
- Format parameter strings: See PHP Official
5.3. Usage: Photo List with Checking Geo Data
Geo Data means latitude and longitude here.
The code below creates a list of photos in the dir img/
.
5.3.1. PHP
-
<?php require_once __DIR__ . '/../vendor/autoload.php'; use Macocci7\PhpPhotoGps\PhotoGps; $pg = new PhotoGps(); $images = glob('img/*.{jp*g,JP*G}', GLOB_BRACE); sort($images); echo "# Photo List: Geo Data\n\n"; echo "<table>\n"; echo "<tr><th>Image</th><th>Geo</th><th>Coordinate</th></tr>\n"; foreach ($images as $file) { $link = sprintf("<a href='%s'><img src='%s' width=100 /></a>", $file, $file); $pg->load($file); $hasGps = $pg->hasGps(); $hasGeo = $pg->hasGeo(); $hasAltitude = $pg->hasAltitude(); echo sprintf("<td>%s</td>", $link); echo sprintf("<td>%s</td>", $hasGps ? 'o' : 'x'); echo "<td>\n"; if ($hasGeo) { echo sprintf( "<a href='%s'>%s, %s</a><br />\n", sprintf( "https://www.google.com/maps/place/%s+%s/@%.7f,%.7f,17z/?authuser=0&entry=ttu", urlencode($pg->lang('eng')->latitudeS()), urlencode($pg->lang('eng')->longitudeS()), $pg->latitudeD(), $pg->longitudeD() ), sprintf("%.14f", $pg->latitudeD()), sprintf("%.14f", $pg->longitudeD()) ); foreach ($pg->langs() as $lang) { echo sprintf( "%s, %s<br />\n", $pg->lang($lang)->latitudeS(), $pg->lang($lang)->longitudeS() ); } } else { echo "No Geo Data\n\n"; } if ($hasAltitude) { foreach ($pg->langs() as $lang) { echo sprintf("%s\n\n", $pg->lang($lang)->altitudeS()); } } else { echo "No Altitude Data\n\n"; } echo "</td></tr>\n"; } echo "</table>\n";
5.3.2. Result
5.3.3. Details
- Load GPS Data from a photo:
load($path)
- Check If GPS Data Exists:
hasGps()
- Check If Geo Data Exists:
hasGeo()
- Check If Altitude Exists:
hasAltitude()
5.4. Usage: Read All GPS Tags
gps()
method returns all Exif tags which has GPS
prefix.
5.4.1. PHP
-
<?php require_once __DIR__ . '/../vendor/autoload.php'; use Macocci7\PhpPhotoGps\PhotoGps; use Macocci7\PhpPhotoGps\Helpers\Dir; use Macocci7\PhpPhotoGps\Helpers\Arrow; use Macocci7\PhpPhotoGps\Helpers\Exif; $pg = new PhotoGps(); $images = [ 'File with Fake GPS via HTTP' => 'http://macocci7.net/photo/gps/remote_fake_gps_001.jpg', 'File with Fake GPS via HTTPS' => 'https://macocci7.net/photo/gps/remote_fake_gps_002.jpg', 'Local File with GPS' => 'img/with_gps.jpg', 'No GPS tags' => 'img/without_gps.jpg', ]; $arrowSize = 30; Dir::clear('./download/'); echo "# Exif: GPS Tags\n\n"; // Loop for images foreach ($images as $title => $image) { echo "## $title\n\n"; // Start Table echo "<table>\n"; $style = 'display: flex; align-items: top;'; echo sprintf("<tr style='%s'>\n<td>\n", $style); // Thumbnail echo "<img src='$image' alt='$title' width='200'>\n\n"; // Load GPS Data $pg->load($image); // Show Attributes Converted from GPS Data $style = 'display: flex; justify-content: right; align-items: center;'; $direction = $pg->direction(); $speedS = $pg->speedS(); $track = $pg->track(); $destBearing = $pg->destBearing(); $datestamp = $pg->datestamp(); $timestamp = $pg->timestamp(); echo "|Attribute|Value|\n"; echo "|:---|---:|\n"; echo sprintf("|ExifVersion|%s|\n", Exif::version()); // Image Direction if (!is_null($direction)) { $pathArrow = sprintf('img/arrow%.2f.png', $direction); Arrow::make($direction)->save($pathArrow); echo sprintf( "|Image Direction|<div style='%s'><img src='%s' width=%d height=%d />%s</div>|\n", $style, $pathArrow, $arrowSize, $arrowSize, $pg->directionS() ); } // Speed if (!is_null($speedS)) { echo sprintf("|Speed|%s|\n", $speedS); } // Track if (!is_null($track)) { $pathArrow = sprintf('img/arrow%.2f.png', $track); Arrow::make($track)->save($pathArrow); echo sprintf( "|Track|<div style='%s'><img src='%s' width=%d height=%d />%s</div>|\n", $style, $pathArrow, $arrowSize, $arrowSize, $pg->trackS() ); } // Dest Bearing if (!is_null($destBearing)) { $pathArrow = sprintf('img/arrow%.2f.png', $destBearing); Arrow::make($destBearing)->save($pathArrow); echo sprintf( "|Destination Bearing|<div style='%s'><img src='%s' width=%d height=%d />%s</div>|\n", $style, $pathArrow, $arrowSize, $arrowSize, $pg->destBearingS() ); } // Date Stamp echo $datestamp ? sprintf("|Datestamp|%s (UTC)|\n", $datestamp) : ''; // Time Stamp echo $timestamp ? sprintf("|Timestamp|%s (UTC)|\n", $timestamp) : ''; echo "</td>\n<td>\n\n"; // Check If GPS Data Exists if ($pg->hasGps()) { // Show GPS Data echo "|Tag|Value|\n"; echo "|:---|---:|\n"; foreach ($pg->gps() as $tag => $value) { echo sprintf( "|%s|%s|\n", $tag, is_array($value) ? implode('<br />', $value) : $value ); } } else { echo "No GPS data.\n\n"; } // Close Table echo "</td>\n</tr>\n</table>\n\n"; }
5.4.2. Result
-
Exif: GPS Tags
File with Fake GPS via HTTP
File with Fake GPS via HTTPS
Local File with GPS
No GPS tags
5.4.3. Details
-
use
declaration:use Macocci7\PhpPhotoGps\Helpers\Dir;
to clear entries in
download
directory. -
use
declaration:use Macocci7\PhpPhotoGps\Helpers\Arrow;
to create arrow images.
-
Clear entries in a directory:
Dir::clear($dir)
-
Get Image Direction:
- As Float:
direction()
returnsnull
if not found. - As String:
directionS()
returnnull
if not found.
- As Float:
-
Get Speed:
- As Float:
speed()
returnsnull
if not found. - As String:
speedS()
returnsnull
if not found.
- As Float:
-
Get Track (Direction of Movement):
- As Float:
track()
returnsnull
if not found. - As String:
trackS()
returnsnull
if not found.
- As Float:
-
Get Destination Bearing:
- As Float:
destBearing()
returnsnull
if not found. - As String:
destBearingS()
returnsnull
if not found.
- As Float:
-
Get Date Stamp:
datestamp()
returnsnull
if not found. -
Get Time Stamp:
timestamp()
returnsnull
if not found. -
Create Arrow Image:
Arrow::make($degree)->save($pathArrow)
-
$degree
: must be in clockwise degrees. (0° ~ 360°) -
Arrow:make()
: returns the instance ofIntervention\Image\Interfaces\ImageInterface
(v3.3) -
response()
has removed since v3. -
Note:
- If the reference is 'M' (Magnetic North), the arrow image shows the relative direction from Magnetic North(Magnetic North upward).
- Magnetic North pole moves over time. See more.
-
-
Note:
- All photos in this repository were taken by macocci7 with mobile phone, and free to use.
- Some of GPS data was manually injected with some tools.
-
GIMP v2.10.34 used for:
GPSLatitudeRef
GPSLatitude
GPSLongitudeRef
GPSLongitude
GPSAltitudeRef
GPSAltitude
GIMP can edit only geo tags.
-
Exif Tool by Phil Harvey v12.72 used for:
- All other GPS tags
Exif Tool can edit all writable GPS tags.
However, Exif Tool currently cannot set
GPSSpeedRef
asK
(maybe a bug).
-
5.5. Usage: GPS Attribute Information
5.5.1. PHP
-
<?php require_once __DIR__ . '/../vendor/autoload.php'; use Macocci7\PhpPhotoGps\Helpers\Gps; //$exifVersion = "0210"; //$exifVersion = "0220"; //$exifVersion = "0221"; //$exifVersion = "0230"; //$exifVersion = "0231"; //$exifVersion = "0232"; $exifVersion = "0300"; echo "# Exif" . $exifVersion . ": GPS Attribute Information\n\n"; echo "|Field Name|Type|Count|Values|Default|Separator|\n"; echo "|:---|:---|---:|:---|:---:|:---:|\n"; foreach (Gps::def('exif' . $exifVersion . '.fields') as $key => $value) { echo sprintf( "|%s|%s|%d|%s|%s|%s|\n", $key, $value['type'], $value['count'], isset($value['values']) ? implode( '<br />', array_map( fn ($k, $v) => '* ' . $k . ': ' . $v, array_keys($value['values']), $value['values'] ) ) : '---', $value['default'] ?? '---', $value['separator'] ?? '---' ); }
5.5.2. Result
5.5.3. Details
-
use
declaration:use Macocci7\PhpPhotoGps\Helpers\Gps;
to use GPS Data Interface.
-
Get GPS Tag Attributes:
Gps::def()
orGps::def($tagName)
it returns
null
if not found.GPS Tag Attributes are defined in
config/Gps.neon
.The structure of Hash array returned by
Gps::def()
is as below:exifXXXX
:XXXX
is replaced with Exif Version number.fields
:- TagName: like
GPSVersionID
orGPSAltitude
type
: based on Exif Standardcount
: based on Exif Standarddefault
: based on Exif Standardvalues
: based on Exif Standardseparator
: originaly added
- TagName: like
Object-like dot-separated specifiers are available for
$tagName
.For example,
Gps::def('exif0300.fields.GPSLatitudeRef')
returns:[ 'type' => 'ASCII', 'count' => 2, 'default' => 'None' 'values' => [ 'N' => 'North latitude', 'S' => 'South latitude', ], ];
6. Examples
- BasicUsage.php >> results in BasicUsage.txt
- CheckGeoData.php >> results in CheckGeoData.md
- ConfigFormat.php >> results in ConfigFormat.txt
- ConfigDirectionFormat.php >> results in ConfigDirectionFormat.txt
- ConfigSpeedFormat.php >> results in ConfigSpeedFormat.txt
- ReadAllGpsTags.php >> results in ReadAllGpsTags.md
- GpsAttrInfo.php >> results in GpsAttrInfo.md
7. LICENSE
8. Changelog
Document created: 2023/09/30
Document updated: 2024/10/02
Copyright 2023 - 2024 macocci7