po/src/include/exif.php

391 lines
12 KiB
PHP

<?php
// Copyright (C) 2002-2006 Balint Kis (balint@k-i-s.net)
// Copyright (C) 2005-2013 Solomon Peachy (pizza@shaftnet.org)
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
function convert_exif2sql_timestamp($timestamp) {
if (!$timestamp)
return "";
$year = substr($timestamp, 0, 4);
$month = substr($timestamp, 5, 2);
$day = substr($timestamp, 8, 2);
$hour = substr($timestamp, 11, 2);
$minute = substr($timestamp, 14, 2);
$second = substr($timestamp, 17, 2);
if ($year == 0 || $month == 0 || $day == 0 || $hour == "" || $minute == "" || $second == "") {
$today = getdate();
return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $today['year'], $today['mon'], $today['mday'], $today['hours'], $today['minutes'], $today['seconds']);
}
$sql_timestamp = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second;
return $sql_timestamp;
}
function convert_exif_shutter($database, $shutter) {
$pos = strpos($shutter, "/");
if ($pos != false) {
$effective_shutter = substr($shutter, 0, $pos);
$effective_shutter /= substr($shutter, $pos+1);
} else {
$effective_shutter = $shutter;
}
$shutter_id = "null";
$minimum_distance = 10000;
$all_speeds = pg_query($database, "select identifier, value from shutter");
for ($item = 0; $item < pg_num_rows($all_speeds); $item++) {
$current = pg_fetch_row($all_speeds, $item);
$pos = strpos($current[1], "/");
if ($pos === false) {
$distance = abs($current[1] - $effective_shutter);
}
else {
$effective_tmp_shutter = substr($current[1], 0, $pos);
$effective_tmp_shutter /= substr($current[1], $pos + 1);
$distance = abs($effective_shutter - $effective_tmp_shutter);
}
if ($minimum_distance > $distance) {
$minimum_distance = $distance;
$shutter_id = $current[0];
}
if ($minimum_distance == 0)
break;
}
return $shutter_id;
}
function convert_exif_ev_comp($database, $ev_comp) {
$ev_comp_id = "null";
$minimum_distance = 10000;
$foo = explode('/', $ev_comp);
if (count($foo) == 2)
$ev_comp = $foo[0] / $foo[1];
$all_ev_comps = pg_query($database, "select identifier, value from ev_comp");
for ($item = 0; $item < pg_num_rows($all_ev_comps); $item++) {
$current = pg_fetch_row($all_ev_comps, $item);
$distance = abs($current[1] - $ev_comp);
if ($minimum_distance > $distance) {
$minimum_distance = $distance;
$ev_comp_id = $current[0];
}
if ($minimum_distance == 0)
break;
}
return $ev_comp_id;
}
function convert_exif_iso($iso) {
/* some cameras use crap like 'Hi 3200' instead of simply '3200' ... */
if (!is_numeric($iso)) {
$row = explode(' ', $iso);
foreach ($row as $item) {
if (is_numeric($item)) {
$iso = $item;
break;
}
}
if (!is_numeric($iso)) {
return "null";
}
}
return $iso;
}
function convert_exif_camera($database, $user_id, &$image_data, $camera_make, $camera_model, $serialno) {
$camera = FALSE;
/* Try a serial number lookup first */
if ($serialno) {
$camera = pg_query($database, "
select camera.identifier, camera_type.raw_icc_profile, camera.ignore_comment
from camera, camera_type
where camera.serial_number = '$serialno'
and camera_type.identifier = camera.type
and camera.users = $user_id");
}
/* If that fails, look it up based on make/model */
if (!$camera) {
$camera = pg_query($database, "
select camera.identifier, camera_type.raw_icc_profile, camera.ignore_comment
from camera, camera_type, manufacturer
where '$camera_make' ILIKE '%'||manufacturer.name||'%'
and '$camera_model' ILIKE '%'||camera_type.model||'%'
and camera_type.identifier = camera.type
and camera_type.manufacturer = manufacturer.identifier
and camera.users = $user_id");
}
if (!$camera)
return FALSE;
if (pg_num_rows($camera) > 0) {
$this_camera = pg_fetch_row($camera, 0);
$image_data['camera'] = $this_camera[0];
$image_data['camera_input_profile'] = $this_camera[1];
if ($this_camera[2])
$image_data['IgnoreExifUserComment'] = TRUE;
return TRUE;
}
return FALSE;
}
function convert_exif_equipment($database, $user_id, &$image_data, $lens_id, $type) {
$lens = pg_query($database, "select identifier from view_equipment
where model = '$lens_id'
and type = $type
and users = $user_id");
if (!$lens)
return FALSE;
if (pg_num_rows($lens) > 0) {
$my_lens = pg_fetch_row($lens, 0);
$image_data['equipment'][] = "$my_lens[0]:$type";
return TRUE;
}
return FALSE;
}
function exif_string_helper(&$image_data, $exif_data, $image_key, $exif_key) {
$tmp = $exif_data[$exif_key];
if (strlen($tmp)) {
$image_data[$image_key] = $tmp;
}
}
function photo_parse_exif_orientation_colorspace($database, $index, $user_id, $image_data, $tag) {
$exif_data = $image_data["exiftool_data_$tag"];
/* Orientation -- Map the new to the old */
if (isset($exif_data["Orientation"])) {
switch ($exif_data["Orientation"]) {
case 'Mirror horizontal': /* 2 */
$image_data['file'][$index]["orientation"] = "Mirrored";
break;
case 'Rotate 180': /* 3 */
$image_data['file'][$index]["orientation"] = "Upsidedown";
break;
case 'Mirror vertical': /* 4 */
$image_data['file'][$index]["orientation"] = "Upsidedown Mirrored";
break;
case 'Mirror horizontal and rotate 270 CW': /* 5 */
$image_data['file'][$index]["orientation"] = "90 deg CW Mirrored";
break;
case 'Rotate 90 CW': /* 6 */
$image_data['file'][$index]["orientation"] = "90 deg CW";
break;
case 'Mirror horizontal and rotate 90 CW': /* 7 */
$image_data['file'][$index]["orientation"] = "90 deg CCW Mirrored";
break;
case 'Rotate 270 CW': /* 8 */
$image_data['file'][$index]["orientation"] = "90 deg CCW";
break;
case 'Horizontal (normal)': /* 1 */
$image_data['file'][$index]["orientation"] = "Normal (0 deg)";
break;
}
} else {
$image_data['file'][$index]["orientation"] = "Normal (0 deg)";
}
$image_data['file'][$index]["orientation_orig"] = $image_data['file'][$index]["orientation"];
/* So are Color Spaces */
if (isset($exif_data["ICC Profile"]))
$image_data['file'][$index]["colorspace"] = 99; /* Embedded Profile */
else if (isset($exif_data["Profile Class"]))
$image_data['file'][$index]["colorspace"] = 99; /* Embedded Profile */
else if (substr_compare($image_data['file'][$index]['original_name'], "_", 0, 1) === 0)
$image_data['file'][$index]["colorspace"] = 2; /* Adobe RGB */
else if (isset($exif_data["Color Space"])) {
$image_data['file'][$index]["colorspace"] = 1; /* Default to sRGB */
if ($exif_data["Color Space"] == "Adobe RGB")
$image_data['file'][$index]["colorspace"] = 2; /* Adobe RGB */
else if ($exif_data["Color Space"] != "sRGB")
$image_data['file'][$index]["colorspace"] = 1; /* Anything other than 'sRGB' is undefined, but we have to use it anway... */
}
if (isset($exif_data["Camera Model Name"]) ||
isset($exif_data["Make"]) ||
isset($exif_data["Serial Number"])) {
convert_exif_camera($database, $user_id, $image_data, $exif_data["Make"], $exif_data["Camera Model Name"], $exif_data["Serial Number"]);
}
return $image_data;
}
function photo_parse_exif($database, $index, $user_id, $image_data, &$output) {
global $strings;
$po_options = $image_data['po_options'];
$bogus_gps = FALSE;
$image_data = extract_exiftool_metadata($image_data, $index, "EXIF", $output);
$image_data["exif"] = "";
$exif_data = $image_data['exiftool_data_EXIF'];
/* Process the raw data */
foreach ($exif_data as $key => $value) {
$ignore_row = FALSE;
$value = pg_escape_string($database, $value);
switch ($key) {
case "Artist":
exif_string_helper($image_data, $exif_data, "author", $key);
break;
case "Copyright":
exif_string_helper($image_data, $exif_data, "copyright", $key);
break;
case "Date/Time Original":
$image_data["date_of_exposure"] = convert_exif2sql_timestamp($value);
break;
case "Create Date":
if ($image_data["date_of_exposure"] == "")
$image_data["date_of_exposure"] = convert_exif2sql_timestamp($value);
break;
case "Flash Exposure Compensation":
$image_data["flash_comp"] = convert_exif_ev_comp($database, $value);
break;
case "Exposure Compensation":
$image_data["exp_comp"] = convert_exif_ev_comp($database, $value);
break;
case "Exposure Difference":
$image_data["exp_diff"] = convert_exif_ev_comp($database, $value);
break;
case "F Number":
$image_data["aperture"] = $value;
break;
case "ISO":
$image_data["iso_override"] = convert_exif_iso($value);
break;
case "Shutter Speed":
$image_data["shutter"] = convert_exif_shutter($database, $value);
break;
case "Lens ID":
convert_exif_equipment($database, $user_id, $image_data, $value, PO_EQUIPMENT_LENS);
break;
case "Flash Model":
convert_exif_equipment($database, $user_id, $image_data, $value, PO_EQUIPMENT_FLASH);
break;
case "GPS Version ID":
// "normal" is 2.2.0.0
// if first value is > 2, we have a problem, and ignore rest of GPS.
// silly Bibble..
$foo = substr($value, 0, strpos($value, "."));
if ($foo > 2) {
$bogus_gps = TRUE;
}
break;
case "GPS Latitude":
if (!$bogus_gps)
$image_data['latitude'] = parse_latitude($value);
break;
case "GPS Longitude":
if (!$bogus_gps)
$image_data['longitude'] = parse_latitude($value);
break;
case "GPS Altitude":
if (!$bogus_gps) {
$regexp = "/((?=\d|\.\d)\d*(?:\.\d*)?)/";
$res = array();
if (preg_match($regexp, $value, $res)) {
$image_data['altitude'] = $res[1];
if ($exif_data['GPS Altitude Ref'] != 'Above Sea Level')
$image_data['altitude'] = - $image_data['altitude'];
}
}
break;
case "GPS Img Direction":
if (!$bogus_gps)
$image_data['direction'] = $value;
break;
case "Jpg From Raw":
if ($po_options['jpgfromraw'] == 't')
$image_data['jpgfromraw'] = TRUE;
break;
case "Minolta Camera Settings 2":
$ignore_row = TRUE;
break;
case "Color Balance Unknown":
$ignore_row = TRUE; /* binary data out.. bad */
break;
}
/* Silly Bibble, no donut. */
if ($bogus_gps && (substr($key, 0, 3) == 'GPS')) {
$ignore_row = TRUE;
}
/* Append the row to the raw table */
if (!$ignore_row) {
$image_data["exif"] .= "<key>$key</key><value>$value</value>";
}
}
/* Pull in orientation and colorspace data */
$image_data = photo_parse_exif_orientation_colorspace($database, $index, $user_id, $image_data, "EXIF");
/* Image Comment */
if (isset($exif_data["User Comment"]) && !$image_data['IgnoreExifUserComment']) {
exif_string_helper($image_data, $exif_data, "title", "User Comment");
}
/* Focal length is special */
if (isset($exif_data["Focal Length"])) {
$tmp = $exif_data["Focal Length"];
if(strpos($tmp, 'mm')) {
$tmp = substr($tmp, 0, strpos($tmp, 'mm'));
}
if (isset($exif_data["Scale Factor To 35 mm Equivalent"]) && $exif_data["Scale Factor To 35 mm Equivalent"] > 2) {
if (isset($exif_data["Focal Length In 35mm Format"]) && $exif_data["Focal Length In 35mm Format"]) {
$tmp = $exif_data["Focal Length In 35mm Format"];
if(strpos($tmp, 'mm')) {
$tmp = substr($tmp, 0, strpos($tmp, 'mm'));
}
} else {
$tmp = $tmp * $exif_data["Scale Factor To 35 mm Equivalent"];
}
}
$image_data["focal_length"] = $tmp;
}
// New: "metering" "program" "flash" and "flash mode"
return $image_data;
}
?>