website/content/blog/gps-exif-data-from-photos-decimal-format.md

2.8 KiB

date draft math medium_enabled medium_post_id tags title
2022-06-19 19:01:35-04:00 false false true 45193055c22d
GPS
Retreiving GPS data in decimal format from EXIF data in photos

For a new feature that I'm cooking up for my website, I need to grab the GPS information from the EXIF data stored in my images. Luckily, imagemagick comes to our rescue.

identify -verbose $IMAGE_FILE | grep GPS

This will return something like the following:

exif:GPSAltitude: 1250/100
exif:GPSAltitudeRef: .
exif:GPSDateStamp: 2022:06:12
exif:GPSImgDirection: 137/1
exif:GPSImgDirectionRef: M
exif:GPSInfo: 1004
exif:GPSLatitude: 40/1, 50/1, 1815/100
exif:GPSLatitudeRef: N
exif:GPSLongitude: 73/1, 53/1, 3625/100
exif:GPSLongitudeRef: W
exif:GPSTimeStamp: 17/1, 32/1, 30/1
exif:GPSVersionID: ....

To request a specific field, for example Latitude:

identify -format "%[EXIF:GPSLatitude]\n" "$IMAGE_FILE"

As with the verbose flag, it will return the information in degrees format

40/1, 50/1, 1815/100

The following bash function will take the degrees format and convert it to the more common decmial format:

DegreesToDecimal() {
        L0=$(echo "$1" | cut -d "," -f 1)
        L1=$(echo "$1" | cut -d "," -f 2)
        L2=$(echo "$1" | cut -d "," -f 3)
        echo "scale=6;$L0 + $L1/60 + $L2/3600" | bc
}

For example:

LAT=$(identify -format "%[EXIF:GPSLatitude]\n" "$IMAGE_FILE")
LAT_DEC=$(DegreesToDecimal "$LAT")
echo "$LAT_DEC"

will output:

40.838374

We can then package this into a script which will output the latitude, longitude, and altitude (m) of an image in decmial format.

#!/bin/sh

set -o errexit
set -o nounset
set -o pipefail

show_usage() {
    echo "Usage: getLLA.sh [imagefile]"
    exit 1
}

# Check argument count
if [ "$#" -ne 1 ]; then
    show_usage
fi

# Check that relevant command exist
if ! command -v identify > /dev/null; then
    echo "Command identify from imagemagick not found. Exiting..."
fi

IMAGE_FILE="$1"
LAT=$(identify -format "%[EXIF:GPSLatitude]\n" "$IMAGE_FILE")
LAT_DIR=$(identify -format "%[EXIF:GPSLatitudeRef]\n" "$IMAGE_FILE")
LON=$(identify -format "%[EXIF:GPSLongitude]\n" "$IMAGE_FILE")
LON_DIR=$(identify -format "%[EXIF:GPSLongitudeRef]\n" "$IMAGE_FILE")
ALT=$(identify -format "%[EXIF:GPSAltitude]\n" "$IMAGE_FILE")

DegreesToDecimal() {
        L0=$(echo "$1" | cut -d "," -f 1)
        L1=$(echo "$1" | cut -d "," -f 2)
        L2=$(echo "$1" | cut -d "," -f 3)
        echo "scale=6;$L0 + $L1/60 + $L2/3600" | bc
}

LAT_DEC=$(DegreesToDecimal "$LAT")
LON_DEC=$(DegreesToDecimal "$LON")
ALT_DEC=$(echo "scale=6;$ALT" | bc)

LAT_PREFIX=$([ $LAT_DIR == "S" ] && echo "-" || echo "")
LON_PREFIX=$([ $LON_DIR == "W" ] && echo "-" || echo "")

echo "$LAT_PREFIX$LAT_DEC"
echo "$LON_PREFIX$LON_DEC"
echo "$ALT_DEC"