Adding EXIF Data Through Command Line

It is also possible to add EXIF data to an image through the command line. exiftool is a command line perl utility for manipulating EXIF data.

Usage Examples

$ exiftool -list
Available tags:
  3DRenderingType A100DataOffset AAFManufacturerID ACoordOfBottomRightCorner
  ACoordOfTopRightCorner AEAperture AEBAutoCancel AEBBracketValue AEBSequence
  AEBSequenceAutoCancel AEBShotCount AEBXv AEExposureTime AEFlags AELButton
  ...
  ...
  ...

Print a (very long) list of EXIF tags that can be read or written using the tool.

$ exiftool filename.jpg
ExifTool Version Number         : 8.60
File Name                       : filename.jpg
Directory                       : .
File Size                       : 357 kB
File Modification Date/Time     : 2013:08:23 23:43:42+08:00
...

View all the EXIF tags for an image file (in this case, filename.jpg).

$ exiftool -Title="Photo Title" filename.jpg 
    1 image files updated

Add the title (“Photo Title“) to the image file filename.jpg.

$ exiftool -Description="This is a description of the photo." filename.jpg 
    1 image files updated

Add the description (“This is a description of the photo.“) to the image file filename.jpg.

$ exiftool -XPKeywords="First Tag;Second Tag" filename.jpg
    1 image files updated

Add the tags (“First Tag” and “Second Tag“) to the image file filename.jpg.

$ exiftool -GPSLatitude=13.37 -GPSLatitudeRef=N -GPSLongitude=1.337 -GPSLongitudeRef=E filename.jpg
    1 image files updated

Add geolocation information (latitude 13.37 degree north and longitude 1.337 degree east) to the image file filename.jpg.

$ exiftool -Title -Description -XPKeywords -GPSLatitude -GPSLatitudeRef -GPSLongitude -GPSLongitudeRef filename.jpg
Title                           : Photo Title
Description                     : This is a description of the photo.
XP Keywords                     : First Tag;Second Tag
GPS Latitude                    : 13 deg 22' 12.00" N
GPS Latitude Ref                : North
GPS Longitude                   : 1 deg 20' 13.20" E
GPS Longitude Ref               : East

View the previously added EXIF information (title, description, tags and geolocation) from the image file filename.jpg.

Note: libimage-exiftool-perl is the package that contains the exiftool utility, and may not be present in a default installation. It can be installed through the package manager.

References

[1] http://linux.die.net/man/1/exiftool
[2] http://www.wikipedia.org/wiki/Exchangeable_image_file_format

Advertisements

Adding EXIF Data Using PHP

A simple PHP script to add image description and geolocation EXIF data to an image. The script makes use of the PHP EXIF Library (PEL) by Isolesen, which can be obtained from http://lsolesen.github.io/pel/.

PHP Code

<?php
set_include_path('lsolesen-pel-9f52634' . PATH_SEPARATOR . get_include_path());
require_once('src/PelJpeg.php');

$pelJpeg = new PelJpeg('in_filename.jpg');

$pelExif = $pelJpeg->getExif();
if ($pelExif == null) {
    $pelExif = new PelExif();
    $pelJpeg->setExif($pelExif);
}

$pelTiff = $pelExif->getTiff();
if ($pelTiff == null) {
    $pelTiff = new PelTiff();
    $pelExif->setTiff($pelTiff);
}

$pelIfd0 = $pelTiff->getIfd();
if ($pelIfd0 == null) {
    $pelIfd0 = new PelIfd(PelIfd::IFD0);
    $pelTiff->setIfd($pelIfd0);
}

$pelIfd0->addEntry(new PelEntryAscii(
        PelTag::IMAGE_DESCRIPTION, 'This is the image description'));

$pelSubIfdGps = new PelIfd(PelIfd::GPS);
$pelIfd0->addSubIfd($pelSubIfdGps);

setGeolocation($pelSubIfdGps, 13.37, 1.337);

$pelJpeg->saveFile('out_filename.jpg');

function setGeolocation(
        $pelSubIfdGps, $latitudeDegreeDecimal, $longitudeDegreeDecimal) {
    $latitudeRef = ($latitudeDegreeDecimal >= 0) ? 'N' : 'S';
    $latitudeDegreeMinuteSecond
            = degreeDecimalToDegreeMinuteSecond(abs($latitudeDegreeDecimal));
    $longitudeRef= ($longitudeDegreeDecimal >= 0) ? 'E' : 'W';
    $longitudeDegreeMinuteSecond
            = degreeDecimalToDegreeMinuteSecond(abs($longitudeDegreeDecimal));

    $pelSubIfdGps->addEntry(new PelEntryAscii(
            PelTag::GPS_LATITUDE_REF, $latitudeRef));
    $pelSubIfdGps->addEntry(new PelEntryRational(
            PelTag::GPS_LATITUDE, 
            array($latitudeDegreeMinuteSecond['degree'], 1), 
            array($latitudeDegreeMinuteSecond['minute'], 1), 
            array(round($latitudeDegreeMinuteSecond['second'] * 1000), 1000)));
    $pelSubIfdGps->addEntry(new PelEntryAscii(
            PelTag::GPS_LONGITUDE_REF, $longitudeRef));
    $pelSubIfdGps->addEntry(new PelEntryRational(
            PelTag::GPS_LONGITUDE, 
            array($longitudeDegreeMinuteSecond['degree'], 1), 
            array($longitudeDegreeMinuteSecond['minute'], 1), 
            array(round($longitudeDegreeMinuteSecond['second'] * 1000), 1000)));
}

function degreeDecimalToDegreeMinuteSecond($degreeDecimal) {
    $degree = floor($degreeDecimal);
    $remainder = $degreeDecimal - $degree;
    $minute = floor($remainder * 60);
    $remainder = ($remainder * 60) - $minute;
    $second = $remainder * 60;
    return array('degree' => $degree, 'minute' => $minute, 'second' => $second);
}
?>

Explanations

set_include_path('lsolesen-pel-9f52634' . PATH_SEPARATOR . get_include_path());
require_once('src/PelJpeg.php');

Import the necessary code. For this script, only PelJpeg.php from the Isolesen PEL library is needed.

$pelJpeg = new PelJpeg('in_filename.jpg');

Load the image file to be editied, in this case, in_filename.jpg.

$pelExif = $pelJpeg->getExif();
if ($pelExif == null) {
    $pelExif = new PelExif();
    $pelJpeg->setExif($pelExif);
}

$pelTiff = $pelExif->getTiff();
if ($pelTiff == null) {
    $pelTiff = new PelTiff();
    $pelExif->setTiff($pelTiff);
}

$pelIfd0 = $pelTiff->getIfd();
if ($pelIfd0 == null) {
    $pelIfd0 = new PelIfd(PelIfd::IFD0);
    $pelTiff->setIfd($pelIfd0);
}

Get the EXIF and the root image file directory (IFD) from the image.

$pelIfd0->addEntry(new PelEntryAscii(
        PelTag::IMAGE_DESCRIPTION, 'This is the image description'));

Add the description (in this case, the description is “This is the image description“.)

$pelSubIfdGps = new PelIfd(PelIfd::GPS);
$pelIfd0->addSubIfd($pelSubIfdGps);

Add a sub-IFD for the geolocation data.

setGeolocation($pelSubIfdGps, 13.37, 1.337);

Set the geolocation data (in this case, with a latitude of 13.37 and a longitude of 1.337). The setGeolocation function is explained below.

$pelJpeg->saveFile('out_filename.jpg');

Save the image which contains the additional EXIF data. In this case, the image is saved to out_filename.jpg.

function setGeolocation(
        $pelSubIfdGps, $latitudeDegreeDecimal, $longitudeDegreeDecimal) {
    $latitudeRef = ($latitudeDegreeDecimal >= 0) ? 'N' : 'S';
    $latitudeDegreeMinuteSecond
            = degreeDecimalToDegreeMinuteSecond(abs($latitudeDegreeDecimal));
    $longitudeRef= ($longitudeDegreeDecimal >= 0) ? 'E' : 'W';
    $longitudeDegreeMinuteSecond
            = degreeDecimalToDegreeMinuteSecond(abs($longitudeDegreeDecimal));

    $pelSubIfdGps->addEntry(new PelEntryAscii(
            PelTag::GPS_LATITUDE_REF, $latitudeRef));
    $pelSubIfdGps->addEntry(new PelEntryRational(
            PelTag::GPS_LATITUDE, 
            array($latitudeDegreeMinuteSecond['degree'], 1), 
            array($latitudeDegreeMinuteSecond['minute'], 1), 
            array(round($latitudeDegreeMinuteSecond['second'] * 1000), 1000)));
    $pelSubIfdGps->addEntry(new PelEntryAscii(
            PelTag::GPS_LONGITUDE_REF, $longitudeRef));
    $pelSubIfdGps->addEntry(new PelEntryRational(
            PelTag::GPS_LONGITUDE, 
            array($longitudeDegreeMinuteSecond['degree'], 1), 
            array($longitudeDegreeMinuteSecond['minute'], 1), 
            array(round($longitudeDegreeMinuteSecond['second'] * 1000), 1000)));
}

The function for setting the geolocation data. This function is needed because the library uses the degree-minute-second format for the latitude and longitude values, so the input decimal values have to be converted beforehand. Also, the library uses positive latitude and longitude values with a direction reference (N or S for latitude, and E or W for longitude), instead of positive and negative values.

function degreeDecimalToDegreeMinuteSecond($degreeDecimal) {
    $degree = floor($degreeDecimal);
    $remainder = $degreeDecimal - $degree;
    $minute = floor($remainder * 60);
    $remainder = ($remainder * 60) - $minute;
    $second = $remainder * 60;
}

The function for converting a decimal degree value to the degree-minute-second format.

Note: php is needed to run the script, and it may not  be present in a default installation. It can be installed through the package manager.

References

[1] http://lsolesen.github.io/pel/
[2] http://www.wikipedia.org/wiki/Exchangeable_image_file_format