391 lines
12 KiB
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;
|
|
}
|
|
|
|
?>
|