iPhone Image Data Processing

Photos taken by iPhone (3G or more) embed the GPS location if the location service was turned on then. Thus let us extract all information including GPS. See the below PHP that I wrote.


    <?PHP
    // Utility to read data from SenseCam and put them into
    // the MySQL Database.
    //
    // Developed by Pil Ho Kim, PhD, UNITN.
    // Last update: November 9th, 2010
    //

    // Below two functions are from http://stackoverflow.com/questions/2526304/php-extract-gps-exif-data
    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 floatval($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]);
    }

    // Set time zone
    date_default_timezone_set("UTC");

    $path = "";
    $set_timeadjust = 0;

    // Set up the path to read
    // $path = $_GET["path"];
    // Read the path variable from the commandline
    while(count($argv) > 0) {
        $arg = array_shift($argv);
        switch($arg) {
            case '-p':
                $path = array_shift($argv);
                break;
        }
    }

    if ($path== "") {
     $path= "/your_data_path/";
    }
    else {
        echo "Reading data in $path\n";
    }

    // Set up the MySQL connection
    $mysqli = new mysqli(you_db_address, your_id, your_passowrd, your_db_name, your_db_port);

    /* check connection */
    if (mysqli_connect_errno()) {
        printf("Connect failed: %s\n", mysqli_connect_error());
        exit();
    }

    // Recursively read all files in the selected directory
    $ite=new RecursiveDirectoryIterator($path);
    $bytestotal=0;
    $nbfiles=0;
    $imagepath = $path;

    $ite_image = new RecursiveDirectoryIterator($imagepath);
    foreach (new RecursiveIteratorIterator($ite_image) as $imagefilename=>$imagecur) {
        if (strstr($imagecur, ".JPG") != "") {
            $filesize=$imagecur->getSize();
            $modified_time = $imagecur->getMTime();
            $bytestotal+=$filesize;
            $nbfiles++;
            echo "$imagefilename => $filesize\n";

            $image = addslashes(file_get_contents($imagecur));
            $imagefilename = $imagecur->getFileName();
            $query = "INSERT IGNORE INTO iphone_photos(filename, content, iphone_unix_timestamp, iphone_timestamp)";
            $query = $query."   SELECT ";
            $query = $query."'$imagefilename', '$image', ";
            $query = $query." $modified_time, ";
            $query = $query." FROM_UNIXTIME($modified_time) ";

            if (!($result = $mysqli->query($query))) {
                printf("Image insertion error: %s\n", $mysqli->error);
            }

            // Read EXIF information
            echo "imagefilename: $imagecur\n";
            $hasGPS = 0;
            $exif = exif_read_data($imagecur, 0, true);
            if ($exif) {
                $query = "INSERT IGNORE INTO iphone_photos_exif(filename, iphone_unix_timestamp, section, section_key, key_value) ";
                $query = $query."   VALUES ";

                $insert_count = 0;
                foreach ($exif as $key => $section) {
                    $exif_section = "$key";
                    foreach ($section as $name => $val) {
                        $exif_key = "$name";

                        if ($name == "GPSLatitude") {
                            $hasGPS = 1;
                        }

                        if (is_array($val)) {
                            $exif_value = "";
                            $count = 0;
                            foreach ($val as $single_val) {
                                if ($count == 0) {
                                    $exif_value = $exif_value."$single_val";
                                }
                                else {
                                    $exif_value = $exif_value."\t$single_val";
                                }
                                $count = $count + 1;
                            }
                        }
                        else {
                            $exif_value = "$val";
                        }

                        $exif_value = addslashes($exif_value);

                        if ($insert_count == 0) {
                            $query = $query." ('$imagefilename', $modified_time, '$exif_section', '$exif_key', '$exif_value') ";
                        }
                        else {
                            $query = $query.", ('$imagefilename', $modified_time, '$exif_section', '$exif_key', '$exif_value') ";
                        }
                        $insert_count = $insert_count + 1;
                    }
                }

                // Check GPS info
                if ($hasGPS) {
                    $longitude = $exif["GPS"]["GPSLongitude"];
                    $longituderef = $exif["GPS"]["GPSLongitudeRef"];
                    $latitude = $exif["GPS"]["GPSLatitude"];
                    $latituderef = $exif["GPS"]["GPSLatitudeRef"];

                    $lon = getGps($longitude, $longituderef);
                    $lat = getGps($latitude, $latituderef);

                    if ($lon) {
                        $query = $query.", ('$imagefilename', $modified_time, 'GPS', 'Longitude', '$lon') ";
                    }
                    if ($lat) {
                        $query = $query.", ('$imagefilename', $modified_time, 'GPS', 'Latitude', '$lat') ";
                    }
                }

                if (!($result = $mysqli->query($query))) {
                    printf("Image exif insertion error: %s\n", $mysqli->error);
                }
            }
        }
    }

    unset($image, $imagefilename, $query);

    /* Update the photo timestamp by the location */

    $query = "CALL update_iphone_images_utc_time()";
    if (!($result = $mysqli->query($query))) {
        printf("iPhone images timestamp update failure: %s\n", $mysqli->error);
    }

    $mysqli->close();

    $bytestotal=number_format($bytestotal);
    echo "Total: $nbfiles files, $bytestotal bytes\n";

    ?>

In the code, you will see two tables (iphone_photos and iphone_photos_exif) and one server-side stored procedures (update_iphone_images_utc_time). Check Data structure page to see the SQL definition of two tables.

CREATE DEFINER=`povi`@`%` PROCEDURE `update_iphone_images_utc_time`()
BEGIN

/*
    Update the iPhone_photos table UTC time by the EXIF GPS location
*/

UPDATE
    iphone_photos AS ip,
    iphone_photos_exif AS ie,
    (SELECT
        if_lat.filename,
        if_lat.iphone_unix_timestamp,
        get_timezone(if_lat.key_value, if_lon.key_value) AS iphone_timezone
    FROM
        iphone_photos_exif AS if_lat,
        iphone_photos_exif AS if_lon
    WHERE
        if_lat.section_key = "Latitude" AND
        if_lon.section_key = "Longitude" AND
        if_lat.filename = if_lon.filename AND
        if_lat.iphone_unix_timestamp = if_lon.iphone_unix_timestamp
    ) AS iz
SET
    ip.iphone_UTC_timestamp = CONVERT_TZ(ip.iphone_timestamp, iz.iphone_timezone, "UTC")
WHERE
    ip.filename = ie.filename AND
    ie.filename = iz.filename AND
    ip.iphone_unix_timestamp = ie.iphone_unix_timestamp AND
    ie.iphone_unix_timestamp = iz.iphone_unix_timestamp;

END;

This stored procedure calls get_timezone() function to determine the local timezone from the EXIF GPS location. See UTC timezone page for details.