From 4943103700332a11f16319496e485cfd7fd9e36a Mon Sep 17 00:00:00 2001 From: Tim Almdal Date: Tue, 30 Jun 2009 07:22:03 -0700 Subject: Fix for #437. Use Exposure Time instead of Shutter Speed as suggested by hiwilson. --- modules/exif/helpers/exif.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/exif') diff --git a/modules/exif/helpers/exif.php b/modules/exif/helpers/exif.php index 970be5ac..747c3171 100644 --- a/modules/exif/helpers/exif.php +++ b/modules/exif/helpers/exif.php @@ -110,11 +110,11 @@ class exif_Core { "ColorSpace" => array("SubIFD", "ColorSpace", t("Color Space"), true), "ExposureBias" => array("SubIFD", "ExposureBiasValue", t("Exposure Value"), true), "ExposureProgram" => array("SubIFD", "ExposureProgram", t("Exposure Program"), true), + "ExposureTime" => array("SubIFD", "ExposureTime", t("Exposure Time"), true), "Flash" => array("SubIFD", "Flash", t("Flash"), true), "FocalLength" => array("SubIFD", "FocalLength", t("Focal Length"), true), "ISO" => array("SubIFD", "ISOSpeedRatings", t("ISO"), true), "MeteringMode" => array("SubIFD", "MeteringMode", t("Metering Mode"), true), - "ShutterSpeed" => array("SubIFD", "ShutterSpeedValue", t("Shutter Speed"), true), "DateTime" => array("SubIFD", "DateTimeOriginal", t("Date/Time"), true), "Copyright" => array("IFD0", "Copyright", t("Copyright"), false), "ImageType" => array("IFD0", "ImageType", t("Image Type"), false), -- cgit v1.2.3 From 3ef39d457693a6744d468876aa7316b65cd3c9cd Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Tue, 30 Jun 2009 19:17:45 -0700 Subject: Update Exif_test to match change made in 4943103700332a11f16319496e485cfd7fd9e36a Get rid of vestigial third column in exif::_keys(). --- modules/exif/helpers/exif.php | 58 ++++++++++++++++++++-------------------- modules/exif/tests/Exif_Test.php | 2 +- 2 files changed, 30 insertions(+), 30 deletions(-) (limited to 'modules/exif') diff --git a/modules/exif/helpers/exif.php b/modules/exif/helpers/exif.php index 747c3171..b0e7e93f 100644 --- a/modules/exif/helpers/exif.php +++ b/modules/exif/helpers/exif.php @@ -104,35 +104,35 @@ class exif_Core { private static function _keys() { if (!isset(self::$exif_keys)) { self::$exif_keys = array( - "Make" => array("IFD0", "Make", t("Camera Maker"), true), - "Model" => array("IFD0", "Model", t("Camera Model"), true), - "Aperture" => array("SubIFD", "FNumber", t("Aperture"), true), - "ColorSpace" => array("SubIFD", "ColorSpace", t("Color Space"), true), - "ExposureBias" => array("SubIFD", "ExposureBiasValue", t("Exposure Value"), true), - "ExposureProgram" => array("SubIFD", "ExposureProgram", t("Exposure Program"), true), - "ExposureTime" => array("SubIFD", "ExposureTime", t("Exposure Time"), true), - "Flash" => array("SubIFD", "Flash", t("Flash"), true), - "FocalLength" => array("SubIFD", "FocalLength", t("Focal Length"), true), - "ISO" => array("SubIFD", "ISOSpeedRatings", t("ISO"), true), - "MeteringMode" => array("SubIFD", "MeteringMode", t("Metering Mode"), true), - "DateTime" => array("SubIFD", "DateTimeOriginal", t("Date/Time"), true), - "Copyright" => array("IFD0", "Copyright", t("Copyright"), false), - "ImageType" => array("IFD0", "ImageType", t("Image Type"), false), - "Orientation" => array("IFD0", "Orientation", t("Orientation"), false), - "ResolutionUnit" => array("IFD0", "ResolutionUnit", t("Resolution Unit"), false), - "xResolution" => array("IFD0", "xResolution", t("X Resolution"), false), - "yResolution" => array("IFD0", "yResolution", t("Y Resolution"), false), - "Compression" => array("IFD1", "Compression", t("Compression"), false), - "BrightnessValue" => array("SubIFD", "BrightnessValue", t("Brightness Value"), false), - "Contrast" => array("SubIFD", "Contrast", t("Contrast"), false), - "ExposureMode" => array("SubIFD", "ExposureMode", t("Exposure Mode"), false), - "FlashEnergy" => array("SubIFD", "FlashEnergy", t("Flash Energy"), false), - "Saturation" => array("SubIFD", "Saturation", t("Saturation"), false), - "SceneType" => array("SubIFD", "SceneType", t("Scene Type"), false), - "Sharpness" => array("SubIFD", "Sharpness", t("Sharpness"), false), - "SubjectDistance" => array("SubIFD", "SubjectDistance", t("Subject Distance"), false), - "Caption" => array("IPTC", "Caption", t("Caption"), false), - "Keywords" => array("IPTC", "Keywords", t("Keywords"), false) + "Make" => array("IFD0", "Make", t("Camera Maker"), ), + "Model" => array("IFD0", "Model", t("Camera Model"), ), + "Aperture" => array("SubIFD", "FNumber", t("Aperture"), ), + "ColorSpace" => array("SubIFD", "ColorSpace", t("Color Space"), ), + "ExposureBias" => array("SubIFD", "ExposureBiasValue", t("Exposure Value"), ), + "ExposureProgram" => array("SubIFD", "ExposureProgram", t("Exposure Program"), ), + "ExposureTime" => array("SubIFD", "ExposureTime", t("Exposure Time"), ), + "Flash" => array("SubIFD", "Flash", t("Flash"), ), + "FocalLength" => array("SubIFD", "FocalLength", t("Focal Length"), ), + "ISO" => array("SubIFD", "ISOSpeedRatings", t("ISO"), ), + "MeteringMode" => array("SubIFD", "MeteringMode", t("Metering Mode"), ), + "DateTime" => array("SubIFD", "DateTimeOriginal", t("Date/Time"), ), + "Copyright" => array("IFD0", "Copyright", t("Copyright"), ), + "ImageType" => array("IFD0", "ImageType", t("Image Type"), ), + "Orientation" => array("IFD0", "Orientation", t("Orientation"), ), + "ResolutionUnit" => array("IFD0", "ResolutionUnit", t("Resolution Unit"), ), + "xResolution" => array("IFD0", "xResolution", t("X Resolution"), ), + "yResolution" => array("IFD0", "yResolution", t("Y Resolution"), ), + "Compression" => array("IFD1", "Compression", t("Compression"), ), + "BrightnessValue" => array("SubIFD", "BrightnessValue", t("Brightness Value"), ), + "Contrast" => array("SubIFD", "Contrast", t("Contrast"), ), + "ExposureMode" => array("SubIFD", "ExposureMode", t("Exposure Mode"), ), + "FlashEnergy" => array("SubIFD", "FlashEnergy", t("Flash Energy"), ), + "Saturation" => array("SubIFD", "Saturation", t("Saturation"), ), + "SceneType" => array("SubIFD", "SceneType", t("Scene Type"), ), + "Sharpness" => array("SubIFD", "Sharpness", t("Sharpness"), ), + "SubjectDistance" => array("SubIFD", "SubjectDistance", t("Subject Distance"), ), + "Caption" => array("IPTC", "Caption", t("Caption"), ), + "Keywords" => array("IPTC", "Keywords", t("Keywords"), ) ); } return self::$exif_keys; diff --git a/modules/exif/tests/Exif_Test.php b/modules/exif/tests/Exif_Test.php index 312ed535..f94d0357 100644 --- a/modules/exif/tests/Exif_Test.php +++ b/modules/exif/tests/Exif_Test.php @@ -31,11 +31,11 @@ class Exif_Test extends Unit_Test_Case { array("caption" => "Color Space", "value" => "Uncalibrated"), array("caption" => "Exposure Value", "value" => "4294.67 EV"), array("caption" => "Exposure Program", "value" => "Program"), + array("caption" => "Exposure Time", "value" => "833/49979 sec"), array("caption" => "Flash", "value" => "No Flash"), array("caption" => "Focal Length", "value" => "50 mm"), array("caption" => "ISO", "value" => "6553700"), array("caption" => "Metering Mode", "value" => "Multi-Segment"), - array("caption" => "Shutter Speed", "value" => "1/60 sec"), array("caption" => "Date/Time", "value" => "2008:03:17 17:41:25"), array("caption" => "Copyright", "value" => "(C) 2008 - T. Almdal"), array("caption" => "Orientation", "value" => "1: Normal (0 deg)"), -- cgit v1.2.3 From c65bfb5a10b125b2cf04ebd5c5d1b58051281f8c Mon Sep 17 00:00:00 2001 From: Tim Almdal Date: Wed, 1 Jul 2009 10:45:37 -0700 Subject: Fix for ticket #437 Tracking vendor ticket: http://bit.ly/16b7Zj --- modules/exif/lib/exif.php | 302 ++++++++++++++++++--------------------- modules/exif/tests/Exif_Test.php | 2 +- 2 files changed, 138 insertions(+), 166 deletions(-) (limited to 'modules/exif') diff --git a/modules/exif/lib/exif.php b/modules/exif/lib/exif.php index f335dad4..a5dc3c74 100644 --- a/modules/exif/lib/exif.php +++ b/modules/exif/lib/exif.php @@ -2,30 +2,30 @@ /* Exifer 1.6 Extracts EXIF information from digital photos. - + Originally created by: Copyright © 2005 Jake Olefsky http:// www.offsky.com/software/exif/index.php jake@olefsky.com - - 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 2 + + 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 2 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. + 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. http:// www.gnu.org/copyleft/gpl.html - + SUMMARY: This script will correctly parse all of the EXIF data included in images taken with digital cameras. It will read the IDF0, IDF1, SubIDF and InteroperabilityIFD fields as well as parsing some of the MakerNote fields that vary depending on camera make and model. This script parses more tags than the internal PHP exif implementation and it will correctly identify and decode what all the values mean. - - This version will correctly parse the MakerNote field for Nikon, Olympus, and Canon + + This version will correctly parse the MakerNote field for Nikon, Olympus, and Canon digital cameras. Others will follow. - + TESTED WITH: Nikon CoolPix 700 Nikon CoolPix E3200 @@ -34,7 +34,7 @@ Nikon Coolpix 5700 Canon PowerShot S200 Canon PowerShot S110 - Olympus C2040Z + Olympus C2040Z Olympus C960 Olumpus E-300 Olympus E-410 @@ -58,20 +58,20 @@ Kodak DC240 Kodak DC4800 Kodak DX3215 - Ricoh RDC-5300 + Ricoh RDC-5300 Sanyo VPC-G250 Sanyo VPC-SX550 Epson 3100z - + VERSION HISTORY: - - 1.0 September 23, 2002 - + + 1.0 September 23, 2002 + + First Public Release - + 1.1 January 25, 2003 - + + Gracefully handled the error case where you pass an empty string to this library + Fixed an inconsistency in the Olympus Camera parsing module + Added support for parsing the MakerNote of Canon images. @@ -80,12 +80,12 @@ + Negative rational numbers are properly displayed + Strange old cameras that use Motorola endineness are now properly supported + Tested with several more cameras - + Potential Problem: Negative Shorts and Negative Longs may not be correctly displayed, but I have not yet found an example of negative shorts or longs being used. - + 1.2 March 30, 2003 - + + Fixed an error that was displayed if you edited your image with WinXP's image viewer + Fixed a bug that caused some images saved from 3rd party software to not parse correctly + Changed the ExposureTime tag to display in fractional seconds rather than decimal @@ -94,9 +94,9 @@ + Added support for parsing the MakeNote of Sanyo images + Fixed a bug with parsing some Olympus MakerNote tags + Tested with several more cameras - + 1.3 June 15, 2003 - + + Fixed Canon MakerNote support for some models (Canon has very difficult and inconsistent MakerNote syntax) + Negative signed shorts and negative signed longs are properly displayed @@ -104,17 +104,17 @@ + More information in my comments about what each tag is + Parses and Displays GPS information if available + Tested with several more cameras - + 1.4 September 14, 2003 - + + This software is now licensed under the GNU General Public License + Exposure time is now correctly displayed when the numerator is 10 - + Fixed the calculation and display of ShutterSpeedValue, ApertureValue and MaxApertureValue + + Fixed the calculation and display of ShutterSpeedValue, ApertureValue and MaxApertureValue + Fixed a bug with the GPS code + Tested with several more cameras - + 1.5 February 18, 2005 - + + It now gracefully deals with a passed in file that cannot be found. + Fixed a GPS bug for the parsing of Altitude and other signed rational numbers + Defined more values for Canon cameras. @@ -127,25 +127,25 @@ + Now reads exif information when the jpeg markers are out of order + Gives raw data output for IPTC, COM and APP2 fields which are sometimes set by other applications + Improvements to Nikon Makernote parsing - + 1.6 March 25th, 2007 [Zenphoto] - + + Adopted into the Zenphoto gallery project, at http://www.zenphoto.org + Fixed a bug where strings had trailing null bytes. + Formatted selected strings better. + Added calculation of 35mm-equivalent focal length when possible. + Cleaned up code for readability and efficiency. - + 1.7 April 11th, 2008 [Zenphoto] - + + Fixed bug with newer Olympus cameras where number of fields was miscalculated leading to bad performance. + More logical fraction calculation for shutter speed. - + */ - + //================================================================================================ @@ -195,11 +195,11 @@ function lookup_tag($tag) { case '0213': $tag = 'YCbCrPositioning'; break; // integer values 1-2 case '0214': $tag = 'ReferenceBlackWhite'; break; // six positive rational numbers case '8298': $tag = 'Copyright'; break; // text string up to 999 bytes long - case '8649': $tag = 'PhotoshopSettings'; break; // ?? + case '8649': $tag = 'PhotoshopSettings'; break; // ?? case '8769': $tag = 'ExifOffset'; break; // positive integer - case '8825': $tag = 'GPSInfoOffset'; break; + case '8825': $tag = 'GPSInfoOffset'; break; case '9286': $tag = 'UserCommentOld'; break; // ?? - // used by Exif SubIFD 'Image Tags' + // used by Exif SubIFD 'Image Tags' case '829a': $tag = 'ExposureTime'; break; // seconds or fraction of seconds 1/x case '829d': $tag = 'FNumber'; break; // positive rational number case '8822': $tag = 'ExposureProgram'; break; // integer value 1-9 @@ -260,7 +260,7 @@ function lookup_tag($tag) { case '1000': $tag = 'RelatedImageFileFormat'; break; // text string up to 999 bytes long case '1001': $tag = 'RelatedImageWidth'; break; // integer in range 0-65535 case '1002': $tag = 'RelatedImageLength'; break; // integer in range 0-65535 - + // used by IFD1 'Thumbnail' case '0100': $tag = 'ImageWidth'; break; // integer in range 0-65535 case '0101': $tag = 'ImageLength'; break; // integer in range 0-65535 @@ -278,11 +278,11 @@ function lookup_tag($tag) { case '011a': $tag = 'ThumbnailXResolution'; break; // positive rational number case '011b': $tag = 'ThumbnailYResolution'; break; // positive rational number case '011c': $tag = 'PlanarConfiguration'; break; // values 1 or 2 - case '0128': $tag = 'ThumbnailResolutionUnit'; break; // values 1-3 - case '0201': $tag = 'JpegIFOffset'; break; + case '0128': $tag = 'ThumbnailResolutionUnit'; break; // values 1-3 + case '0201': $tag = 'JpegIFOffset'; break; case '0202': $tag = 'JpegIFByteCount'; break; case '0212': $tag = 'YCbCrSubSampling'; break; - + // misc case '00ff': $tag = 'SubfileType'; break; case '012d': $tag = 'TransferFunction'; break; @@ -298,7 +298,7 @@ function lookup_tag($tag) { case '828f': $tag = 'BatteryLevel'; break; case '83bb': $tag = 'IPTC/NAA'; break; case '8773': $tag = 'InterColorProfile'; break; - + case '8828': $tag = 'OECF'; break; case '8829': $tag = 'Interlace'; break; case '882a': $tag = 'TimeZoneOffset'; break; @@ -312,7 +312,7 @@ function lookup_tag($tag) { case '9215': $tag = 'ExposureIndex'; break; case '9216': $tag = 'TIFF/EPStandardID'; break; case 'a20b': $tag = 'FlashEnergy'; break; - + default: $tag = 'unknown:'.$tag; break; } return $tag; @@ -358,18 +358,18 @@ function formatData($type,$tag,$intel,$data) { } else if ($type == 'URATIONAL' || $type == 'SRATIONAL') { $data = bin2hex($data); if ($intel == 1) $data = intel2Moto($data); - + if ($intel == 1) $top = hexdec(substr($data,8,8)); // intel stores them bottom-top else $top = hexdec(substr($data,0,8)); // motorola stores them top-bottom - + if ($intel == 1) $bottom = hexdec(substr($data,0,8)); // intel stores them bottom-top else $bottom = hexdec(substr($data,8,8)); // motorola stores them top-bottom - + if ($type == 'SRATIONAL' && $top > 2147483647) $top = $top - 4294967296; // this makes the number signed instead of unsigned if ($bottom != 0) $data=$top/$bottom; else if ($top == 0) $data = 0; else $data = $top.'/'.$bottom; - + if (($tag == '011a' || $tag == '011b') && $bottom == 1) { // XResolution YResolution $data = $top.' dots per ResolutionUnit'; } else if ($tag == '829a') { // Exposure Time @@ -388,7 +388,7 @@ function formatData($type,$tag,$intel,$data) { // The formula is : Aperture = 2*log2(FNumber) <=> FNumber = e((Aperture.ln(2))/2) $data = exp(($data*log(2))/2); $data = round($data, 1);// Focal is given with a precision of 1 digit. - $data='f/'.$data; + $data='f/'.$data; } else if ($tag == '920a') { // FocalLength $data = $data.' mm'; } else if ($tag == '9201') { // ShutterSpeedValue @@ -400,17 +400,17 @@ function formatData($type,$tag,$intel,$data) { $data = exp($data * log(2)); if ($data != 0) $data = 1/$data; $data = formatExposure($data); - } - + } + } else if ($type == 'USHORT' || $type == 'SSHORT' || $type == 'ULONG' || $type == 'SLONG' || $type == 'FLOAT' || $type == 'DOUBLE') { $data = bin2hex($data); if ($intel == 1) $data = intel2Moto($data); if ($intel == 0 && ($type == 'USHORT' || $type == 'SSHORT')) $data = substr($data,0,4); $data = hexdec($data); - + if ($type == 'SSHORT' && $data > 32767) $data = $data - 65536; // this makes the number signed instead of unsigned if ($type == 'SLONG' && $data > 2147483647) $data = $data - 4294967296; // this makes the number signed instead of unsigned - + if ($tag == '0112') { // Orientation // Example of how all of these tag formatters should be... switch ($data) { @@ -424,16 +424,16 @@ function formatData($type,$tag,$intel,$data) { case 8 : $data = gettext('8: 90 deg CW'); break; default : $data = gettext('Unknown').': '.$data; } - + } else if ($tag == '0128' || $tag == 'a210' || $tag == '0128') { // ResolutionUnit and FocalPlaneResolutionUnit and ThumbnailResolutionUnit if ($data == 1) $data = gettext('No Unit'); else if ($data == 2) $data = gettext('Inch'); else if ($data == 3) $data = gettext('Centimeter'); - + } else if ($tag == '0213') { // YCbCrPositioning if ($data == 1) $data = gettext('Center of Pixel Array'); else if ($data == 2) $data = gettext('Datum Point'); - + } else if ($tag == '8822') { // ExposureProgram if ($data == 1) $data = gettext('Manual'); else if ($data == 2) $data = gettext('Program'); @@ -444,7 +444,7 @@ function formatData($type,$tag,$intel,$data) { else if ($data == 7) $data = gettext('Portrat'); else if ($data == 8) $data = gettext('Landscape'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == '9207') { // MeteringMode if ($data == 0) $data = gettext('Unknown'); else if ($data == 1) $data = gettext('Average'); @@ -455,7 +455,7 @@ function formatData($type,$tag,$intel,$data) { else if ($data == 6) $data = gettext('Partial'); else if ($data == 255) $data = gettext('Other'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == '9208') { // LightSource if ($data == 0) $data = gettext('Unknown or Auto'); else if ($data == 1) $data = gettext('Daylight'); @@ -480,7 +480,7 @@ function formatData($type,$tag,$intel,$data) { else if ($data == 24) $data = gettext('ISO Studio Tungsten'); else if ($data == 255) $data = gettext('Other'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == '9209') { // Flash if ($data == 0) $data = gettext('No Flash'); else if ($data == 1) $data = gettext('Flash'); @@ -505,19 +505,19 @@ function formatData($type,$tag,$intel,$data) { else if ($data == 93) $data = gettext('Red Eye, Auto-Mode, Return light not detected'); else if ($data == 95) $data = gettext('Red Eye, Auto-Mode, Return light detected'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == 'a001') { // ColorSpace if ($data == 1) $data = gettext('sRGB'); else $data = gettext('Uncalibrated'); - + } else if ($tag == 'a002' || $tag == 'a003') { // ExifImageWidth/Height $data = $data. ' '.gettext('pixels'); - + } else if ($tag == '0103') { // Compression if ($data == 1) $data = gettext('No Compression'); else if ($data == 6) $data = gettext('Jpeg Compression'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == 'a217') { // SensingMethod if ($data == 1) $data = gettext('Not defined'); if ($data == 2) $data = gettext('One Chip Color Area Sensor'); @@ -527,7 +527,7 @@ function formatData($type,$tag,$intel,$data) { if ($data == 7) $data = gettext('Trilinear Sensor'); if ($data == 8) $data = gettext('Color Sequential Linear Sensor'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == '0106') { // PhotometricInterpretation if ($data == 1) $data = gettext('Monochrome'); else if ($data == 2) $data = gettext('RGB'); @@ -555,9 +555,9 @@ function formatData($type,$tag,$intel,$data) { // case 2: $data="Auto bracket"; break; // default: $data="Unknown"; break; // } - + } else if ($type == 'UNDEFINED') { - + if ($tag == '9000' || $tag == 'a000' || $tag == '0002') { // ExifVersion,FlashPixVersion,InteroperabilityVersion $data=gettext('version').' '.$data/100; } @@ -589,7 +589,7 @@ function formatData($type,$tag,$intel,$data) { $data = bin2hex($data); if ($intel == 1) $data = intel2Moto($data); } - + return $data; } @@ -611,35 +611,35 @@ function formatExposure($data) { // Reads one standard IFD entry //================================================================================================ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) { - + if (feof($in)) { // test to make sure we can still read. $result['Errors'] = $result['Errors']+1; return; } - + // 2 byte tag $tag = bin2hex(fread($in, 2)); if ($intel == 1) $tag = intel2Moto($tag); $tag_name = lookup_tag($tag); - + // 2 byte datatype $type = bin2hex(fread($in, 2)); if ($intel == 1) $type = intel2Moto($type); lookup_type($type, $size); - + if (strpos($tag_name, 'unknown:') !== false && strpos($type, 'error:') !== false) { // we have an error $result['Errors'] = $result['Errors']+1; return; } - + // 4 byte number of elements $count = bin2hex(fread($in, 4)); if ($intel == 1) $count = intel2Moto($count); $bytesofdata = $size*hexdec($count); - + // 4 byte value or pointer to value if larger than 4 bytes $value = fread( $in, 4 ); - + if ($bytesofdata <= 4) { // if datatype is 4 bytes or less, its the value $data = $value; } else if ($bytesofdata < 100000) { // otherwise its a pointer to the value, so lets go get it @@ -657,7 +657,7 @@ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) { } if ($tag_name == 'MakerNote') { // if its a maker tag, we need to parse this specially $make = $result['IFD0']['Make']; - + if ($result['VerboseOutput'] == 1) { $result[$ifd_name]['MakerNote']['RawData'] = $data; } @@ -681,10 +681,10 @@ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) { require_once(dirname(__FILE__).'/makers/sanyo.php'); parseSanyo($data,$result,$seek,$globalOffset); $result[$ifd_name]['KnownMaker'] = 1; - } else if (eregi('Panasonic',$make)) { - require_once(dirname(__FILE__).'/makers/panasonic.php'); - parsePanasonic($data,$result,$seek,$globalOffset); - $result[$ifd_name]['KnownMaker'] = 1; + } else if (eregi('Panasonic',$make)) { + require_once(dirname(__FILE__).'/makers/panasonic.php'); + parsePanasonic($data,$result,$seek,$globalOffset); + $result[$ifd_name]['KnownMaker'] = 1; } else { $result[$ifd_name]['KnownMaker'] = 0; } @@ -696,9 +696,9 @@ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) { } else { // Format the data depending on the type and tag $formated_data = formatData($type,$tag,$intel,$data); - + $result[$ifd_name][$tag_name] = $formated_data; - + if ($result['VerboseOutput'] == 1) { if ($type == 'URATIONAL' || $type == 'SRATIONAL' || $type == 'USHORT' || $type == 'SSHORT' || $type == 'ULONG' || $type == 'SLONG' || $type == 'FLOAT' || $type == 'DOUBLE') { $data = bin2hex($data); @@ -725,19 +725,19 @@ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) { // http:// us2.php.net/manual/en/function.exif-read-data.php //================================================================================================ function read_exif_data_raw($path,$verbose) { - + if ($path == '' || $path == 'none') return; - + $in = @fopen($path, 'rb'); // the b is for windows machines to open in binary mode $seek = @fopen($path, 'rb'); // There may be an elegant way to do this with one file handle. - + $globalOffset = 0; - + if (!isset($verbose)) $verbose=0; - + $result['VerboseOutput'] = $verbose; $result['Errors'] = 0; - + if (!$in || !$seek) { // if the path was invalid, this error will catch it $result['Errors'] = 1; $result['Error'][$result['Errors']] = gettext('The file could not be found.'); @@ -745,22 +745,22 @@ function read_exif_data_raw($path,$verbose) { } $GLOBALS['exiferFileSize'] = filesize($path); - - // First 2 bytes of JPEG are 0xFFD8 + + // First 2 bytes of JPEG are 0xFFD8 $data = bin2hex(fread( $in, 2 )); if ($data == 'ffd8') { $result['ValidJpeg'] = 1; } else { $result['ValidJpeg'] = 0; fseek($in, 0); - } - + } + $result['ValidIPTCData'] = 0; $result['ValidJFIFData'] = 0; $result['ValidEXIFData'] = 0; $result['ValidAPP2Data'] = 0; $result['ValidCOMData'] = 0; - + if ($result['ValidJpeg'] == 1) { // Next 2 bytes are MARKER tag (0xFFE#) $data = bin2hex(fread( $in, 2 )); @@ -772,56 +772,56 @@ if ($result['ValidJpeg'] == 1) { if ($data == 'ffe0') { // JFIF Marker $result['ValidJFIFData'] = 1; $result['JFIF']['Size'] = hexdec($size); - + if (hexdec($size)-2 > 0) { $data = fread( $in, hexdec($size)-2); $result['JFIF']['Data'] = $data; - } - + } + $result['JFIF']['Identifier'] = substr($data,0,5);; $result['JFIF']['ExtensionCode'] = bin2hex(substr($data,6,1)); - + $globalOffset+=hexdec($size)+2; - + } else if ($data == 'ffed') { // IPTC Marker $result['ValidIPTCData'] = 1; $result['IPTC']['Size'] = hexdec($size); - + if (hexdec($size)-2 > 0) { $data = fread( $in, hexdec($size)-2); $result['IPTC']['Data'] = $data ; - } + } $globalOffset+=hexdec($size)+2; - + } else if ($data == 'ffe2') { // EXIF extension Marker $result['ValidAPP2Data'] = 1; $result['APP2']['Size'] = hexdec($size); - + if (hexdec($size)-2 > 0) { $data = fread( $in, hexdec($size)-2); $result['APP2']['Data'] = $data ; - } + } $globalOffset+=hexdec($size)+2; - + } else if ($data == 'fffe') { // COM extension Marker $result['ValidCOMData'] = 1; $result['COM']['Size'] = hexdec($size); - + if (hexdec($size)-2 > 0) { $data = fread( $in, hexdec($size)-2); $result['COM']['Data'] = $data ; - } + } $globalOffset+=hexdec($size)+2; - + } else if ($data == 'ffe1') { $result['ValidEXIFData'] = 1; } - + $data = bin2hex(fread( $in, 2 )); $size = bin2hex(fread( $in, 2 )); } // END MARKER LOOP - + if ($data == 'ffe1') { $result['ValidEXIFData'] = 1; } else { @@ -829,16 +829,16 @@ if ($result['ValidJpeg'] == 1) { fclose($seek); return $result; } - - // Size of APP1 + + // Size of APP1 $result['APP1Size'] = hexdec($size); - + // Start of APP1 block starts with 'Exif' header (6 bytes) $header = fread( $in, 6 ); } // END IF ValidJpeg - - // Then theres a TIFF header with 2 bytes of endieness (II or MM) + + // Then theres a TIFF header with 2 bytes of endieness (II or MM) $header = fread( $in, 2 ); if ($header==='II') { $intel=1; @@ -850,14 +850,14 @@ if ($result['ValidJpeg'] == 1) { $intel=1; // not sure what the default should be, but this seems reasonable $result['Endien'] = 'Unknown'; } - + // 2 bytes of 0x002a $tag = bin2hex(fread( $in, 2 )); - + // Then 4 bytes of offset to IFD0 (usually 8 which includes all 8 bytes of TIFF header) $offset = bin2hex(fread( $in, 4 )); if ($intel == 1) $offset = intel2Moto($offset); - + // Check for extremely large values here if (hexdec($offset) > 100000) { $result['ValidEXIFData'] = 0; @@ -867,20 +867,20 @@ if ($result['ValidJpeg'] == 1) { } if (hexdec($offset)>8) $unknown = fread( $in, hexdec($offset)-8); // fixed this bug in 1.3 - + // add 12 to the offset to account for TIFF header if ($result['ValidJpeg'] == 1) { $globalOffset+=12; } - - + + //=========================================================== // Start of IFD0 $num = bin2hex(fread( $in, 2 )); if ($intel == 1) $num = intel2Moto($num); $num = hexdec($num); $result['IFD0NumTags'] = $num; - + if ($num<1000) { // 1000 entries is too much and is probably an error. for($i=0; $i<$num; $i++) { read_entry($result,$in,$seek,$intel,'IFD0',$globalOffset); @@ -889,19 +889,19 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; $result['Error'][$result['Errors']] = 'Illegal size for IFD0'; } - + // store offset to IFD1 $offset = bin2hex(fread( $in, 4 )); if ($intel == 1) $offset = intel2Moto($offset); $result['IFD1Offset'] = hexdec($offset); - + // Check for SubIFD if (!isset($result['IFD0']['ExifOffset']) || $result['IFD0']['ExifOffset'] == 0) { fclose($in); fclose($seek); return $result; } - + // seek to SubIFD (Value of ExifOffset tag) above. $ExitOffset = $result['IFD0']['ExifOffset']; $v = fseek($in,$globalOffset+$ExitOffset); @@ -909,14 +909,14 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; $result['Error'][$result['Errors']] = gettext('Couldnt Find SubIFD'); } - + //=========================================================== // Start of SubIFD $num = bin2hex(fread( $in, 2 )); if ($intel == 1) $num = intel2Moto($num); $num = hexdec($num); $result['SubIFDNumTags'] = $num; - + if ($num<1000) { // 1000 entries is too much and is probably an error. for($i=0; $i<$num; $i++) { read_entry($result,$in,$seek,$intel,'SubIFD',$globalOffset); @@ -925,10 +925,10 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; $result['Error'][$result['Errors']] = gettext('Illegal size for SubIFD'); } - + // Add the 35mm equivalent focal length: $result['SubIFD']['FocalLength35mmEquiv'] = get35mmEquivFocalLength($result); - + // Check for IFD1 if (!isset($result['IFD1Offset']) || $result['IFD1Offset'] == 0) { fclose($in); @@ -941,14 +941,14 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; $result['Error'][$result['Errors']] = gettext('Couldnt Find IFD1'); } - + //=========================================================== // Start of IFD1 $num = bin2hex(fread( $in, 2 )); if ($intel == 1) $num = intel2Moto($num); $num = hexdec($num); $result['IFD1NumTags'] = $num; - + if ($num<1000) { // 1000 entries is too much and is probably an error. for($i=0; $i<$num; $i++) { read_entry($result,$in,$seek,$intel,'IFD1',$globalOffset); @@ -966,9 +966,9 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; } $result['IFD1']['ThumbnailData'] = $data; - } - - + } + + // Check for Interoperability IFD if (!isset($result['SubIFD']['ExifInteroperabilityOffset']) || $result['SubIFD']['ExifInteroperabilityOffset'] == 0) { fclose($in); @@ -981,14 +981,14 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; $result['Error'][$result['Errors']] = gettext('Couldnt Find InteroperabilityIFD'); } - + //=========================================================== // Start of InteroperabilityIFD $num = bin2hex(fread( $in, 2 )); if ($intel == 1) $num = intel2Moto($num); $num = hexdec($num); $result['InteroperabilityIFDNumTags'] = $num; - + if ($num<1000) { // 1000 entries is too much and is probably an error. for($i=0; $i<$num; $i++) { read_entry($result,$in,$seek,$intel,'InteroperabilityIFD',$globalOffset); @@ -1007,37 +1007,9 @@ if ($result['ValidJpeg'] == 1) { //================================================================================================ function ConvertToFraction($v, &$n, &$d) { - $MaxTerms = 15; // Limit to prevent infinite loop - $MinDivisor = 0.000001; // Limit to prevent divide by zero - $MaxError = 0.00000001; // How close is enough - - $f = $v; // Initialize fraction being converted - - $n_un = 1; // Initialize fractions with 1/0, 0/1 - $d_un = 0; - $n_deux = 0; - $d_deux = 1; - - for ($i = 0; $i<$MaxTerms; $i++) - { - $a = floor($f); // Get next term - $f = $f - $a; // Get new divisor - $n = $n_un * $a + $n_deux; // Calculate new fraction - $d = $d_un * $a + $d_deux; - $n_deux = $n_un; // Save last two fractions - $d_deux = $d_un; - $n_un = $n; - $d_un = $d; - - if ($f < $MinDivisor) // Quit if dividing by zero - break; - - if (abs($v - $n / $d) < $MaxError) - break; - - $f = 1 / $f; // Take reciprocal - } -} + $n = 1; + $d = !empty($v) ? round(1.0 / $v) : 0; +} //================================================================================================ // Calculates the 35mm-equivalent focal length from the reported sensor resolution, by Tristan Harward. @@ -1070,7 +1042,7 @@ function get35mmEquivFocalLength(&$result) { } else { $fl = 0; } - + if (($width != 0) && !empty($units) && !empty($xres) && !empty($fl) && !empty($width)) { $ccdwidth = ($width * $unitfactor) / $xres; $equivfl = $fl / $ccdwidth*36+0.5; diff --git a/modules/exif/tests/Exif_Test.php b/modules/exif/tests/Exif_Test.php index f94d0357..5c5a5cb1 100644 --- a/modules/exif/tests/Exif_Test.php +++ b/modules/exif/tests/Exif_Test.php @@ -31,7 +31,7 @@ class Exif_Test extends Unit_Test_Case { array("caption" => "Color Space", "value" => "Uncalibrated"), array("caption" => "Exposure Value", "value" => "4294.67 EV"), array("caption" => "Exposure Program", "value" => "Program"), - array("caption" => "Exposure Time", "value" => "833/49979 sec"), + array("caption" => "Exposure Time", "value" => "1/60 sec"), array("caption" => "Flash", "value" => "No Flash"), array("caption" => "Focal Length", "value" => "50 mm"), array("caption" => "ISO", "value" => "6553700"), -- cgit v1.2.3 From 8f4c1c4ddf8473fbe401c2f8682ab1d69975eb6f Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Wed, 1 Jul 2009 11:31:12 -0700 Subject: Revert "Fix for ticket #437" This change had unintentional whitespace changes. Reverting for now, will reapply it. This reverts commit c65bfb5a10b125b2cf04ebd5c5d1b58051281f8c. --- modules/exif/lib/exif.php | 302 +++++++++++++++++++++------------------ modules/exif/tests/Exif_Test.php | 2 +- 2 files changed, 166 insertions(+), 138 deletions(-) (limited to 'modules/exif') diff --git a/modules/exif/lib/exif.php b/modules/exif/lib/exif.php index a5dc3c74..f335dad4 100644 --- a/modules/exif/lib/exif.php +++ b/modules/exif/lib/exif.php @@ -2,30 +2,30 @@ /* Exifer 1.6 Extracts EXIF information from digital photos. - + Originally created by: Copyright © 2005 Jake Olefsky http:// www.offsky.com/software/exif/index.php jake@olefsky.com - - 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 2 + + 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 2 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. + 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. http:// www.gnu.org/copyleft/gpl.html - + SUMMARY: This script will correctly parse all of the EXIF data included in images taken with digital cameras. It will read the IDF0, IDF1, SubIDF and InteroperabilityIFD fields as well as parsing some of the MakerNote fields that vary depending on camera make and model. This script parses more tags than the internal PHP exif implementation and it will correctly identify and decode what all the values mean. - - This version will correctly parse the MakerNote field for Nikon, Olympus, and Canon + + This version will correctly parse the MakerNote field for Nikon, Olympus, and Canon digital cameras. Others will follow. - + TESTED WITH: Nikon CoolPix 700 Nikon CoolPix E3200 @@ -34,7 +34,7 @@ Nikon Coolpix 5700 Canon PowerShot S200 Canon PowerShot S110 - Olympus C2040Z + Olympus C2040Z Olympus C960 Olumpus E-300 Olympus E-410 @@ -58,20 +58,20 @@ Kodak DC240 Kodak DC4800 Kodak DX3215 - Ricoh RDC-5300 + Ricoh RDC-5300 Sanyo VPC-G250 Sanyo VPC-SX550 Epson 3100z - + VERSION HISTORY: - - 1.0 September 23, 2002 - + + 1.0 September 23, 2002 + + First Public Release - + 1.1 January 25, 2003 - + + Gracefully handled the error case where you pass an empty string to this library + Fixed an inconsistency in the Olympus Camera parsing module + Added support for parsing the MakerNote of Canon images. @@ -80,12 +80,12 @@ + Negative rational numbers are properly displayed + Strange old cameras that use Motorola endineness are now properly supported + Tested with several more cameras - + Potential Problem: Negative Shorts and Negative Longs may not be correctly displayed, but I have not yet found an example of negative shorts or longs being used. - + 1.2 March 30, 2003 - + + Fixed an error that was displayed if you edited your image with WinXP's image viewer + Fixed a bug that caused some images saved from 3rd party software to not parse correctly + Changed the ExposureTime tag to display in fractional seconds rather than decimal @@ -94,9 +94,9 @@ + Added support for parsing the MakeNote of Sanyo images + Fixed a bug with parsing some Olympus MakerNote tags + Tested with several more cameras - + 1.3 June 15, 2003 - + + Fixed Canon MakerNote support for some models (Canon has very difficult and inconsistent MakerNote syntax) + Negative signed shorts and negative signed longs are properly displayed @@ -104,17 +104,17 @@ + More information in my comments about what each tag is + Parses and Displays GPS information if available + Tested with several more cameras - + 1.4 September 14, 2003 - + + This software is now licensed under the GNU General Public License + Exposure time is now correctly displayed when the numerator is 10 - + Fixed the calculation and display of ShutterSpeedValue, ApertureValue and MaxApertureValue + + Fixed the calculation and display of ShutterSpeedValue, ApertureValue and MaxApertureValue + Fixed a bug with the GPS code + Tested with several more cameras - + 1.5 February 18, 2005 - + + It now gracefully deals with a passed in file that cannot be found. + Fixed a GPS bug for the parsing of Altitude and other signed rational numbers + Defined more values for Canon cameras. @@ -127,25 +127,25 @@ + Now reads exif information when the jpeg markers are out of order + Gives raw data output for IPTC, COM and APP2 fields which are sometimes set by other applications + Improvements to Nikon Makernote parsing - + 1.6 March 25th, 2007 [Zenphoto] - + + Adopted into the Zenphoto gallery project, at http://www.zenphoto.org + Fixed a bug where strings had trailing null bytes. + Formatted selected strings better. + Added calculation of 35mm-equivalent focal length when possible. + Cleaned up code for readability and efficiency. - + 1.7 April 11th, 2008 [Zenphoto] - + + Fixed bug with newer Olympus cameras where number of fields was miscalculated leading to bad performance. + More logical fraction calculation for shutter speed. - + */ - + //================================================================================================ @@ -195,11 +195,11 @@ function lookup_tag($tag) { case '0213': $tag = 'YCbCrPositioning'; break; // integer values 1-2 case '0214': $tag = 'ReferenceBlackWhite'; break; // six positive rational numbers case '8298': $tag = 'Copyright'; break; // text string up to 999 bytes long - case '8649': $tag = 'PhotoshopSettings'; break; // ?? + case '8649': $tag = 'PhotoshopSettings'; break; // ?? case '8769': $tag = 'ExifOffset'; break; // positive integer - case '8825': $tag = 'GPSInfoOffset'; break; + case '8825': $tag = 'GPSInfoOffset'; break; case '9286': $tag = 'UserCommentOld'; break; // ?? - // used by Exif SubIFD 'Image Tags' + // used by Exif SubIFD 'Image Tags' case '829a': $tag = 'ExposureTime'; break; // seconds or fraction of seconds 1/x case '829d': $tag = 'FNumber'; break; // positive rational number case '8822': $tag = 'ExposureProgram'; break; // integer value 1-9 @@ -260,7 +260,7 @@ function lookup_tag($tag) { case '1000': $tag = 'RelatedImageFileFormat'; break; // text string up to 999 bytes long case '1001': $tag = 'RelatedImageWidth'; break; // integer in range 0-65535 case '1002': $tag = 'RelatedImageLength'; break; // integer in range 0-65535 - + // used by IFD1 'Thumbnail' case '0100': $tag = 'ImageWidth'; break; // integer in range 0-65535 case '0101': $tag = 'ImageLength'; break; // integer in range 0-65535 @@ -278,11 +278,11 @@ function lookup_tag($tag) { case '011a': $tag = 'ThumbnailXResolution'; break; // positive rational number case '011b': $tag = 'ThumbnailYResolution'; break; // positive rational number case '011c': $tag = 'PlanarConfiguration'; break; // values 1 or 2 - case '0128': $tag = 'ThumbnailResolutionUnit'; break; // values 1-3 - case '0201': $tag = 'JpegIFOffset'; break; + case '0128': $tag = 'ThumbnailResolutionUnit'; break; // values 1-3 + case '0201': $tag = 'JpegIFOffset'; break; case '0202': $tag = 'JpegIFByteCount'; break; case '0212': $tag = 'YCbCrSubSampling'; break; - + // misc case '00ff': $tag = 'SubfileType'; break; case '012d': $tag = 'TransferFunction'; break; @@ -298,7 +298,7 @@ function lookup_tag($tag) { case '828f': $tag = 'BatteryLevel'; break; case '83bb': $tag = 'IPTC/NAA'; break; case '8773': $tag = 'InterColorProfile'; break; - + case '8828': $tag = 'OECF'; break; case '8829': $tag = 'Interlace'; break; case '882a': $tag = 'TimeZoneOffset'; break; @@ -312,7 +312,7 @@ function lookup_tag($tag) { case '9215': $tag = 'ExposureIndex'; break; case '9216': $tag = 'TIFF/EPStandardID'; break; case 'a20b': $tag = 'FlashEnergy'; break; - + default: $tag = 'unknown:'.$tag; break; } return $tag; @@ -358,18 +358,18 @@ function formatData($type,$tag,$intel,$data) { } else if ($type == 'URATIONAL' || $type == 'SRATIONAL') { $data = bin2hex($data); if ($intel == 1) $data = intel2Moto($data); - + if ($intel == 1) $top = hexdec(substr($data,8,8)); // intel stores them bottom-top else $top = hexdec(substr($data,0,8)); // motorola stores them top-bottom - + if ($intel == 1) $bottom = hexdec(substr($data,0,8)); // intel stores them bottom-top else $bottom = hexdec(substr($data,8,8)); // motorola stores them top-bottom - + if ($type == 'SRATIONAL' && $top > 2147483647) $top = $top - 4294967296; // this makes the number signed instead of unsigned if ($bottom != 0) $data=$top/$bottom; else if ($top == 0) $data = 0; else $data = $top.'/'.$bottom; - + if (($tag == '011a' || $tag == '011b') && $bottom == 1) { // XResolution YResolution $data = $top.' dots per ResolutionUnit'; } else if ($tag == '829a') { // Exposure Time @@ -388,7 +388,7 @@ function formatData($type,$tag,$intel,$data) { // The formula is : Aperture = 2*log2(FNumber) <=> FNumber = e((Aperture.ln(2))/2) $data = exp(($data*log(2))/2); $data = round($data, 1);// Focal is given with a precision of 1 digit. - $data='f/'.$data; + $data='f/'.$data; } else if ($tag == '920a') { // FocalLength $data = $data.' mm'; } else if ($tag == '9201') { // ShutterSpeedValue @@ -400,17 +400,17 @@ function formatData($type,$tag,$intel,$data) { $data = exp($data * log(2)); if ($data != 0) $data = 1/$data; $data = formatExposure($data); - } - + } + } else if ($type == 'USHORT' || $type == 'SSHORT' || $type == 'ULONG' || $type == 'SLONG' || $type == 'FLOAT' || $type == 'DOUBLE') { $data = bin2hex($data); if ($intel == 1) $data = intel2Moto($data); if ($intel == 0 && ($type == 'USHORT' || $type == 'SSHORT')) $data = substr($data,0,4); $data = hexdec($data); - + if ($type == 'SSHORT' && $data > 32767) $data = $data - 65536; // this makes the number signed instead of unsigned if ($type == 'SLONG' && $data > 2147483647) $data = $data - 4294967296; // this makes the number signed instead of unsigned - + if ($tag == '0112') { // Orientation // Example of how all of these tag formatters should be... switch ($data) { @@ -424,16 +424,16 @@ function formatData($type,$tag,$intel,$data) { case 8 : $data = gettext('8: 90 deg CW'); break; default : $data = gettext('Unknown').': '.$data; } - + } else if ($tag == '0128' || $tag == 'a210' || $tag == '0128') { // ResolutionUnit and FocalPlaneResolutionUnit and ThumbnailResolutionUnit if ($data == 1) $data = gettext('No Unit'); else if ($data == 2) $data = gettext('Inch'); else if ($data == 3) $data = gettext('Centimeter'); - + } else if ($tag == '0213') { // YCbCrPositioning if ($data == 1) $data = gettext('Center of Pixel Array'); else if ($data == 2) $data = gettext('Datum Point'); - + } else if ($tag == '8822') { // ExposureProgram if ($data == 1) $data = gettext('Manual'); else if ($data == 2) $data = gettext('Program'); @@ -444,7 +444,7 @@ function formatData($type,$tag,$intel,$data) { else if ($data == 7) $data = gettext('Portrat'); else if ($data == 8) $data = gettext('Landscape'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == '9207') { // MeteringMode if ($data == 0) $data = gettext('Unknown'); else if ($data == 1) $data = gettext('Average'); @@ -455,7 +455,7 @@ function formatData($type,$tag,$intel,$data) { else if ($data == 6) $data = gettext('Partial'); else if ($data == 255) $data = gettext('Other'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == '9208') { // LightSource if ($data == 0) $data = gettext('Unknown or Auto'); else if ($data == 1) $data = gettext('Daylight'); @@ -480,7 +480,7 @@ function formatData($type,$tag,$intel,$data) { else if ($data == 24) $data = gettext('ISO Studio Tungsten'); else if ($data == 255) $data = gettext('Other'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == '9209') { // Flash if ($data == 0) $data = gettext('No Flash'); else if ($data == 1) $data = gettext('Flash'); @@ -505,19 +505,19 @@ function formatData($type,$tag,$intel,$data) { else if ($data == 93) $data = gettext('Red Eye, Auto-Mode, Return light not detected'); else if ($data == 95) $data = gettext('Red Eye, Auto-Mode, Return light detected'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == 'a001') { // ColorSpace if ($data == 1) $data = gettext('sRGB'); else $data = gettext('Uncalibrated'); - + } else if ($tag == 'a002' || $tag == 'a003') { // ExifImageWidth/Height $data = $data. ' '.gettext('pixels'); - + } else if ($tag == '0103') { // Compression if ($data == 1) $data = gettext('No Compression'); else if ($data == 6) $data = gettext('Jpeg Compression'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == 'a217') { // SensingMethod if ($data == 1) $data = gettext('Not defined'); if ($data == 2) $data = gettext('One Chip Color Area Sensor'); @@ -527,7 +527,7 @@ function formatData($type,$tag,$intel,$data) { if ($data == 7) $data = gettext('Trilinear Sensor'); if ($data == 8) $data = gettext('Color Sequential Linear Sensor'); else $data = gettext('Unknown').': '.$data; - + } else if ($tag == '0106') { // PhotometricInterpretation if ($data == 1) $data = gettext('Monochrome'); else if ($data == 2) $data = gettext('RGB'); @@ -555,9 +555,9 @@ function formatData($type,$tag,$intel,$data) { // case 2: $data="Auto bracket"; break; // default: $data="Unknown"; break; // } - + } else if ($type == 'UNDEFINED') { - + if ($tag == '9000' || $tag == 'a000' || $tag == '0002') { // ExifVersion,FlashPixVersion,InteroperabilityVersion $data=gettext('version').' '.$data/100; } @@ -589,7 +589,7 @@ function formatData($type,$tag,$intel,$data) { $data = bin2hex($data); if ($intel == 1) $data = intel2Moto($data); } - + return $data; } @@ -611,35 +611,35 @@ function formatExposure($data) { // Reads one standard IFD entry //================================================================================================ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) { - + if (feof($in)) { // test to make sure we can still read. $result['Errors'] = $result['Errors']+1; return; } - + // 2 byte tag $tag = bin2hex(fread($in, 2)); if ($intel == 1) $tag = intel2Moto($tag); $tag_name = lookup_tag($tag); - + // 2 byte datatype $type = bin2hex(fread($in, 2)); if ($intel == 1) $type = intel2Moto($type); lookup_type($type, $size); - + if (strpos($tag_name, 'unknown:') !== false && strpos($type, 'error:') !== false) { // we have an error $result['Errors'] = $result['Errors']+1; return; } - + // 4 byte number of elements $count = bin2hex(fread($in, 4)); if ($intel == 1) $count = intel2Moto($count); $bytesofdata = $size*hexdec($count); - + // 4 byte value or pointer to value if larger than 4 bytes $value = fread( $in, 4 ); - + if ($bytesofdata <= 4) { // if datatype is 4 bytes or less, its the value $data = $value; } else if ($bytesofdata < 100000) { // otherwise its a pointer to the value, so lets go get it @@ -657,7 +657,7 @@ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) { } if ($tag_name == 'MakerNote') { // if its a maker tag, we need to parse this specially $make = $result['IFD0']['Make']; - + if ($result['VerboseOutput'] == 1) { $result[$ifd_name]['MakerNote']['RawData'] = $data; } @@ -681,10 +681,10 @@ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) { require_once(dirname(__FILE__).'/makers/sanyo.php'); parseSanyo($data,$result,$seek,$globalOffset); $result[$ifd_name]['KnownMaker'] = 1; - } else if (eregi('Panasonic',$make)) { - require_once(dirname(__FILE__).'/makers/panasonic.php'); - parsePanasonic($data,$result,$seek,$globalOffset); - $result[$ifd_name]['KnownMaker'] = 1; + } else if (eregi('Panasonic',$make)) { + require_once(dirname(__FILE__).'/makers/panasonic.php'); + parsePanasonic($data,$result,$seek,$globalOffset); + $result[$ifd_name]['KnownMaker'] = 1; } else { $result[$ifd_name]['KnownMaker'] = 0; } @@ -696,9 +696,9 @@ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) { } else { // Format the data depending on the type and tag $formated_data = formatData($type,$tag,$intel,$data); - + $result[$ifd_name][$tag_name] = $formated_data; - + if ($result['VerboseOutput'] == 1) { if ($type == 'URATIONAL' || $type == 'SRATIONAL' || $type == 'USHORT' || $type == 'SSHORT' || $type == 'ULONG' || $type == 'SLONG' || $type == 'FLOAT' || $type == 'DOUBLE') { $data = bin2hex($data); @@ -725,19 +725,19 @@ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) { // http:// us2.php.net/manual/en/function.exif-read-data.php //================================================================================================ function read_exif_data_raw($path,$verbose) { - + if ($path == '' || $path == 'none') return; - + $in = @fopen($path, 'rb'); // the b is for windows machines to open in binary mode $seek = @fopen($path, 'rb'); // There may be an elegant way to do this with one file handle. - + $globalOffset = 0; - + if (!isset($verbose)) $verbose=0; - + $result['VerboseOutput'] = $verbose; $result['Errors'] = 0; - + if (!$in || !$seek) { // if the path was invalid, this error will catch it $result['Errors'] = 1; $result['Error'][$result['Errors']] = gettext('The file could not be found.'); @@ -745,22 +745,22 @@ function read_exif_data_raw($path,$verbose) { } $GLOBALS['exiferFileSize'] = filesize($path); - - // First 2 bytes of JPEG are 0xFFD8 + + // First 2 bytes of JPEG are 0xFFD8 $data = bin2hex(fread( $in, 2 )); if ($data == 'ffd8') { $result['ValidJpeg'] = 1; } else { $result['ValidJpeg'] = 0; fseek($in, 0); - } - + } + $result['ValidIPTCData'] = 0; $result['ValidJFIFData'] = 0; $result['ValidEXIFData'] = 0; $result['ValidAPP2Data'] = 0; $result['ValidCOMData'] = 0; - + if ($result['ValidJpeg'] == 1) { // Next 2 bytes are MARKER tag (0xFFE#) $data = bin2hex(fread( $in, 2 )); @@ -772,56 +772,56 @@ if ($result['ValidJpeg'] == 1) { if ($data == 'ffe0') { // JFIF Marker $result['ValidJFIFData'] = 1; $result['JFIF']['Size'] = hexdec($size); - + if (hexdec($size)-2 > 0) { $data = fread( $in, hexdec($size)-2); $result['JFIF']['Data'] = $data; - } - + } + $result['JFIF']['Identifier'] = substr($data,0,5);; $result['JFIF']['ExtensionCode'] = bin2hex(substr($data,6,1)); - + $globalOffset+=hexdec($size)+2; - + } else if ($data == 'ffed') { // IPTC Marker $result['ValidIPTCData'] = 1; $result['IPTC']['Size'] = hexdec($size); - + if (hexdec($size)-2 > 0) { $data = fread( $in, hexdec($size)-2); $result['IPTC']['Data'] = $data ; - } + } $globalOffset+=hexdec($size)+2; - + } else if ($data == 'ffe2') { // EXIF extension Marker $result['ValidAPP2Data'] = 1; $result['APP2']['Size'] = hexdec($size); - + if (hexdec($size)-2 > 0) { $data = fread( $in, hexdec($size)-2); $result['APP2']['Data'] = $data ; - } + } $globalOffset+=hexdec($size)+2; - + } else if ($data == 'fffe') { // COM extension Marker $result['ValidCOMData'] = 1; $result['COM']['Size'] = hexdec($size); - + if (hexdec($size)-2 > 0) { $data = fread( $in, hexdec($size)-2); $result['COM']['Data'] = $data ; - } + } $globalOffset+=hexdec($size)+2; - + } else if ($data == 'ffe1') { $result['ValidEXIFData'] = 1; } - + $data = bin2hex(fread( $in, 2 )); $size = bin2hex(fread( $in, 2 )); } // END MARKER LOOP - + if ($data == 'ffe1') { $result['ValidEXIFData'] = 1; } else { @@ -829,16 +829,16 @@ if ($result['ValidJpeg'] == 1) { fclose($seek); return $result; } - - // Size of APP1 + + // Size of APP1 $result['APP1Size'] = hexdec($size); - + // Start of APP1 block starts with 'Exif' header (6 bytes) $header = fread( $in, 6 ); } // END IF ValidJpeg - - // Then theres a TIFF header with 2 bytes of endieness (II or MM) + + // Then theres a TIFF header with 2 bytes of endieness (II or MM) $header = fread( $in, 2 ); if ($header==='II') { $intel=1; @@ -850,14 +850,14 @@ if ($result['ValidJpeg'] == 1) { $intel=1; // not sure what the default should be, but this seems reasonable $result['Endien'] = 'Unknown'; } - + // 2 bytes of 0x002a $tag = bin2hex(fread( $in, 2 )); - + // Then 4 bytes of offset to IFD0 (usually 8 which includes all 8 bytes of TIFF header) $offset = bin2hex(fread( $in, 4 )); if ($intel == 1) $offset = intel2Moto($offset); - + // Check for extremely large values here if (hexdec($offset) > 100000) { $result['ValidEXIFData'] = 0; @@ -867,20 +867,20 @@ if ($result['ValidJpeg'] == 1) { } if (hexdec($offset)>8) $unknown = fread( $in, hexdec($offset)-8); // fixed this bug in 1.3 - + // add 12 to the offset to account for TIFF header if ($result['ValidJpeg'] == 1) { $globalOffset+=12; } - - + + //=========================================================== // Start of IFD0 $num = bin2hex(fread( $in, 2 )); if ($intel == 1) $num = intel2Moto($num); $num = hexdec($num); $result['IFD0NumTags'] = $num; - + if ($num<1000) { // 1000 entries is too much and is probably an error. for($i=0; $i<$num; $i++) { read_entry($result,$in,$seek,$intel,'IFD0',$globalOffset); @@ -889,19 +889,19 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; $result['Error'][$result['Errors']] = 'Illegal size for IFD0'; } - + // store offset to IFD1 $offset = bin2hex(fread( $in, 4 )); if ($intel == 1) $offset = intel2Moto($offset); $result['IFD1Offset'] = hexdec($offset); - + // Check for SubIFD if (!isset($result['IFD0']['ExifOffset']) || $result['IFD0']['ExifOffset'] == 0) { fclose($in); fclose($seek); return $result; } - + // seek to SubIFD (Value of ExifOffset tag) above. $ExitOffset = $result['IFD0']['ExifOffset']; $v = fseek($in,$globalOffset+$ExitOffset); @@ -909,14 +909,14 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; $result['Error'][$result['Errors']] = gettext('Couldnt Find SubIFD'); } - + //=========================================================== // Start of SubIFD $num = bin2hex(fread( $in, 2 )); if ($intel == 1) $num = intel2Moto($num); $num = hexdec($num); $result['SubIFDNumTags'] = $num; - + if ($num<1000) { // 1000 entries is too much and is probably an error. for($i=0; $i<$num; $i++) { read_entry($result,$in,$seek,$intel,'SubIFD',$globalOffset); @@ -925,10 +925,10 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; $result['Error'][$result['Errors']] = gettext('Illegal size for SubIFD'); } - + // Add the 35mm equivalent focal length: $result['SubIFD']['FocalLength35mmEquiv'] = get35mmEquivFocalLength($result); - + // Check for IFD1 if (!isset($result['IFD1Offset']) || $result['IFD1Offset'] == 0) { fclose($in); @@ -941,14 +941,14 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; $result['Error'][$result['Errors']] = gettext('Couldnt Find IFD1'); } - + //=========================================================== // Start of IFD1 $num = bin2hex(fread( $in, 2 )); if ($intel == 1) $num = intel2Moto($num); $num = hexdec($num); $result['IFD1NumTags'] = $num; - + if ($num<1000) { // 1000 entries is too much and is probably an error. for($i=0; $i<$num; $i++) { read_entry($result,$in,$seek,$intel,'IFD1',$globalOffset); @@ -966,9 +966,9 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; } $result['IFD1']['ThumbnailData'] = $data; - } - - + } + + // Check for Interoperability IFD if (!isset($result['SubIFD']['ExifInteroperabilityOffset']) || $result['SubIFD']['ExifInteroperabilityOffset'] == 0) { fclose($in); @@ -981,14 +981,14 @@ if ($result['ValidJpeg'] == 1) { $result['Errors'] = $result['Errors']+1; $result['Error'][$result['Errors']] = gettext('Couldnt Find InteroperabilityIFD'); } - + //=========================================================== // Start of InteroperabilityIFD $num = bin2hex(fread( $in, 2 )); if ($intel == 1) $num = intel2Moto($num); $num = hexdec($num); $result['InteroperabilityIFDNumTags'] = $num; - + if ($num<1000) { // 1000 entries is too much and is probably an error. for($i=0; $i<$num; $i++) { read_entry($result,$in,$seek,$intel,'InteroperabilityIFD',$globalOffset); @@ -1007,9 +1007,37 @@ if ($result['ValidJpeg'] == 1) { //================================================================================================ function ConvertToFraction($v, &$n, &$d) { - $n = 1; - $d = !empty($v) ? round(1.0 / $v) : 0; -} + $MaxTerms = 15; // Limit to prevent infinite loop + $MinDivisor = 0.000001; // Limit to prevent divide by zero + $MaxError = 0.00000001; // How close is enough + + $f = $v; // Initialize fraction being converted + + $n_un = 1; // Initialize fractions with 1/0, 0/1 + $d_un = 0; + $n_deux = 0; + $d_deux = 1; + + for ($i = 0; $i<$MaxTerms; $i++) + { + $a = floor($f); // Get next term + $f = $f - $a; // Get new divisor + $n = $n_un * $a + $n_deux; // Calculate new fraction + $d = $d_un * $a + $d_deux; + $n_deux = $n_un; // Save last two fractions + $d_deux = $d_un; + $n_un = $n; + $d_un = $d; + + if ($f < $MinDivisor) // Quit if dividing by zero + break; + + if (abs($v - $n / $d) < $MaxError) + break; + + $f = 1 / $f; // Take reciprocal + } +} //================================================================================================ // Calculates the 35mm-equivalent focal length from the reported sensor resolution, by Tristan Harward. @@ -1042,7 +1070,7 @@ function get35mmEquivFocalLength(&$result) { } else { $fl = 0; } - + if (($width != 0) && !empty($units) && !empty($xres) && !empty($fl) && !empty($width)) { $ccdwidth = ($width * $unitfactor) / $xres; $equivfl = $fl / $ccdwidth*36+0.5; diff --git a/modules/exif/tests/Exif_Test.php b/modules/exif/tests/Exif_Test.php index 5c5a5cb1..f94d0357 100644 --- a/modules/exif/tests/Exif_Test.php +++ b/modules/exif/tests/Exif_Test.php @@ -31,7 +31,7 @@ class Exif_Test extends Unit_Test_Case { array("caption" => "Color Space", "value" => "Uncalibrated"), array("caption" => "Exposure Value", "value" => "4294.67 EV"), array("caption" => "Exposure Program", "value" => "Program"), - array("caption" => "Exposure Time", "value" => "1/60 sec"), + array("caption" => "Exposure Time", "value" => "833/49979 sec"), array("caption" => "Flash", "value" => "No Flash"), array("caption" => "Focal Length", "value" => "50 mm"), array("caption" => "ISO", "value" => "6553700"), -- cgit v1.2.3 From 7b1e3c50218b235a7d25ebe21f93eb8dd9acfb84 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Wed, 1 Jul 2009 11:32:27 -0700 Subject: Reapply c65bfb5a10b125b2cf04ebd5c5d1b58051281f8c without extra whitespace changes. --- modules/exif/lib/exif.php | 32 ++------------------------------ modules/exif/tests/Exif_Test.php | 2 +- 2 files changed, 3 insertions(+), 31 deletions(-) (limited to 'modules/exif') diff --git a/modules/exif/lib/exif.php b/modules/exif/lib/exif.php index f335dad4..21b028f8 100644 --- a/modules/exif/lib/exif.php +++ b/modules/exif/lib/exif.php @@ -1007,36 +1007,8 @@ if ($result['ValidJpeg'] == 1) { //================================================================================================ function ConvertToFraction($v, &$n, &$d) { - $MaxTerms = 15; // Limit to prevent infinite loop - $MinDivisor = 0.000001; // Limit to prevent divide by zero - $MaxError = 0.00000001; // How close is enough - - $f = $v; // Initialize fraction being converted - - $n_un = 1; // Initialize fractions with 1/0, 0/1 - $d_un = 0; - $n_deux = 0; - $d_deux = 1; - - for ($i = 0; $i<$MaxTerms; $i++) - { - $a = floor($f); // Get next term - $f = $f - $a; // Get new divisor - $n = $n_un * $a + $n_deux; // Calculate new fraction - $d = $d_un * $a + $d_deux; - $n_deux = $n_un; // Save last two fractions - $d_deux = $d_un; - $n_un = $n; - $d_un = $d; - - if ($f < $MinDivisor) // Quit if dividing by zero - break; - - if (abs($v - $n / $d) < $MaxError) - break; - - $f = 1 / $f; // Take reciprocal - } + $n = 1; + $d = !empty($v) ? round(1.0 / $v) : 0; } //================================================================================================ diff --git a/modules/exif/tests/Exif_Test.php b/modules/exif/tests/Exif_Test.php index f94d0357..5c5a5cb1 100644 --- a/modules/exif/tests/Exif_Test.php +++ b/modules/exif/tests/Exif_Test.php @@ -31,7 +31,7 @@ class Exif_Test extends Unit_Test_Case { array("caption" => "Color Space", "value" => "Uncalibrated"), array("caption" => "Exposure Value", "value" => "4294.67 EV"), array("caption" => "Exposure Program", "value" => "Program"), - array("caption" => "Exposure Time", "value" => "833/49979 sec"), + array("caption" => "Exposure Time", "value" => "1/60 sec"), array("caption" => "Flash", "value" => "No Flash"), array("caption" => "Focal Length", "value" => "50 mm"), array("caption" => "ISO", "value" => "6553700"), -- cgit v1.2.3 From 588f991d558e86a07389e27c9ca9b1b4ab0f9fe7 Mon Sep 17 00:00:00 2001 From: Tim Almdal Date: Wed, 1 Jul 2009 21:56:02 -0700 Subject: Updated to Exifer r4159 --- modules/exif/lib/exif.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'modules/exif') diff --git a/modules/exif/lib/exif.php b/modules/exif/lib/exif.php index 21b028f8..bd72f237 100644 --- a/modules/exif/lib/exif.php +++ b/modules/exif/lib/exif.php @@ -1007,8 +1007,16 @@ if ($result['ValidJpeg'] == 1) { //================================================================================================ function ConvertToFraction($v, &$n, &$d) { - $n = 1; - $d = !empty($v) ? round(1.0 / $v) : 0; + if ($v == 0) { + $n = 0; + $d = 1; + return; + } + for ($n=1; $n<100; $n++) { + $v1 = 1/$v*$n; + $d = round($v1, 0); + if (abs($d - $v1) < 0.02) return;// within tolarance + } } //================================================================================================ -- cgit v1.2.3 From 43c63362575264f473e8bba3345524fa7e58afe1 Mon Sep 17 00:00:00 2001 From: Tim Almdal Date: Wed, 8 Jul 2009 08:37:40 -0700 Subject: Add Task logging to the Extract EXIF data task --- modules/exif/helpers/exif_task.php | 65 ++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 27 deletions(-) (limited to 'modules/exif') diff --git a/modules/exif/helpers/exif_task.php b/modules/exif/helpers/exif_task.php index 375503e3..649ad092 100644 --- a/modules/exif/helpers/exif_task.php +++ b/modules/exif/helpers/exif_task.php @@ -38,37 +38,48 @@ class exif_task_Core { } static function update_index($task) { - $completed = $task->get("completed", 0); + try { + $completed = $task->get("completed", 0); - $start = microtime(true); - foreach (ORM::factory("item") - ->join("exif_records", "items.id", "exif_records.item_id", "left") - ->where("type", "photo") - ->open_paren() - ->where("exif_records.item_id", null) - ->orwhere("exif_records.dirty", 1) - ->close_paren() - ->find_all() as $item) { - if (microtime(true) - $start > 1.5) { - break; - } + $start = microtime(true); + $message = array(); + foreach (ORM::factory("item") + ->join("exif_records", "items.id", "exif_records.item_id", "left") + ->where("type", "photo") + ->open_paren() + ->where("exif_records.item_id", null) + ->orwhere("exif_records.dirty", 1) + ->close_paren() + ->find_all() as $item) { + if (microtime(true) - $start > 1.5) { + break; + } - $completed++; - exif::extract($item); - } + $completed++; + exif::extract($item); + $message[] = t("Updated Exif meta data for '%title'", + array("title" => p::purify($item->title))); + } - list ($remaining, $total, $percent) = exif::stats(); - $task->set("completed", $completed); - if ($remaining == 0 || !($remaining + $completed)) { + $task->log($message); + list ($remaining, $total, $percent) = exif::stats(); + $task->set("completed", $completed); + if ($remaining == 0 || !($remaining + $completed)) { + $task->done = true; + $task->state = "success"; + site_status::clear("exif_index_out_of_date"); + $task->percent_complete = 100; + } else { + $task->percent_complete = round(100 * $completed / ($remaining + $completed)); + } + $task->status = t2("one record updated, index is %percent% up-to-date", + "%count records updated, index is %percent% up-to-date", + $completed, array("percent" => $percent)); + } catch (Exception $e) { $task->done = true; - $task->state = "success"; - site_status::clear("exif_index_out_of_date"); - $task->percent_complete = 100; - } else { - $task->percent_complete = round(100 * $completed / ($remaining + $completed)); + $task->state = "error"; + $task->status = $e->getMessage(); + $task->log($e->__toString()); } - $task->status = t2("one record updated, index is %percent% up-to-date", - "%count records updated, index is %percent% up-to-date", - $completed, array("percent" => $percent)); } } -- cgit v1.2.3 From fabdde9bb97bc01c52de41069fed0d046717d3fe Mon Sep 17 00:00:00 2001 From: Tim Almdal Date: Fri, 10 Jul 2009 17:46:33 -0700 Subject: Reference exif consistently as EXIF ticket #526. --- modules/exif/helpers/exif_task.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/exif') diff --git a/modules/exif/helpers/exif_task.php b/modules/exif/helpers/exif_task.php index 649ad092..6929b797 100644 --- a/modules/exif/helpers/exif_task.php +++ b/modules/exif/helpers/exif_task.php @@ -57,7 +57,7 @@ class exif_task_Core { $completed++; exif::extract($item); - $message[] = t("Updated Exif meta data for '%title'", + $message[] = t("Updated EXIF meta data for '%title'", array("title" => p::purify($item->title))); } -- cgit v1.2.3 From 6320babf78deb66f0916e569b36eaeb598603997 Mon Sep 17 00:00:00 2001 From: Shai Ben-Naphtali Date: Sat, 11 Jul 2009 13:56:43 +0800 Subject: Fixes ticket #526 Signed-off-by: Tim Almdal --- modules/exif/helpers/exif.php | 2 +- modules/exif/helpers/exif_task.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'modules/exif') diff --git a/modules/exif/helpers/exif.php b/modules/exif/helpers/exif.php index b0e7e93f..20ecd0cb 100644 --- a/modules/exif/helpers/exif.php +++ b/modules/exif/helpers/exif.php @@ -163,7 +163,7 @@ class exif_Core { list ($remaining) = exif::stats(); if ($remaining) { site_status::warning( - t('Your EXIF index needs to be updated. Fix this now', + t('Your Exif index needs to be updated. Fix this now', array("url" => url::site("admin/maintenance/start/exif_task::update_index?csrf=__CSRF__"))), "exif_index_out_of_date"); } diff --git a/modules/exif/helpers/exif_task.php b/modules/exif/helpers/exif_task.php index 6929b797..f3e77975 100644 --- a/modules/exif/helpers/exif_task.php +++ b/modules/exif/helpers/exif_task.php @@ -28,12 +28,12 @@ class exif_task_Core { list ($remaining, $total, $percent) = exif::stats(); return array(Task_Definition::factory() ->callback("exif_task::update_index") - ->name(t("Extract EXIF data")) + ->name(t("Extract Exif data")) ->description($remaining ? t2("1 photo needs to be scanned", "%count (%percent%) of your photos need to be scanned", $remaining, array("percent" => (100 - $percent))) - : t("EXIF data is up-to-date")) + : t("Exif data is up-to-date")) ->severity($remaining ? log::WARNING : log::SUCCESS)); } @@ -57,7 +57,7 @@ class exif_task_Core { $completed++; exif::extract($item); - $message[] = t("Updated EXIF meta data for '%title'", + $message[] = t("Updated Exif meta data for '%title'", array("title" => p::purify($item->title))); } -- cgit v1.2.3 From e2a9a1d28459b96e412004df4d4ec010fb9b30e2 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Mon, 13 Jul 2009 10:36:55 -0700 Subject: Add quotes around all values that contain spaces in them, and add a test to make sure that we continue to do so. This makes sure that we don't have problems with 5.3 which treats the literal "on" as a boolean. --- modules/akismet/module.info | 2 +- modules/comment/module.info | 2 +- modules/digibug/module.info | 4 +-- modules/exif/module.info | 2 +- modules/g2_import/module.info | 4 +-- modules/gallery/module.info | 4 +-- modules/gallery/tests/File_Structure_Test.php | 37 +++++++++++++++++++++++++++ modules/image_block/module.info | 4 +-- modules/info/module.info | 4 +-- modules/notification/module.info | 2 +- modules/organize/module.info | 4 +-- modules/recaptcha/module.info | 2 +- modules/rss/module.info | 4 +-- modules/search/module.info | 4 +-- modules/server_add/module.info | 4 +-- modules/slideshow/module.info | 4 +-- modules/tag/module.info | 4 +-- modules/user/module.info | 4 +-- modules/watermark/module.info | 4 +-- themes/admin_default/theme.info | 6 ++--- themes/default/theme.info | 6 ++--- 21 files changed, 74 insertions(+), 37 deletions(-) (limited to 'modules/exif') diff --git a/modules/akismet/module.info b/modules/akismet/module.info index d45d8a7b..b61ed107 100644 --- a/modules/akismet/module.info +++ b/modules/akismet/module.info @@ -1,3 +1,3 @@ -name = Akismet +name = "Akismet" description = "Filter comments through the Akismet web service to detect and eliminate spam (http://akismet.com). You'll need a WordPress.com API key to use it." version = 1 diff --git a/modules/comment/module.info b/modules/comment/module.info index 55997317..c371cf27 100644 --- a/modules/comment/module.info +++ b/modules/comment/module.info @@ -1,3 +1,3 @@ -name = Comments +name = "Comments" description = "Allows users and guests to leave comments on photos and albums." version = 2 diff --git a/modules/digibug/module.info b/modules/digibug/module.info index c25a2454..be4e880a 100644 --- a/modules/digibug/module.info +++ b/modules/digibug/module.info @@ -1,3 +1,3 @@ -name = Digibug -description = Digibug Photo Printing Module +name = "Digibug" +description = "Digibug Photo Printing Module" version = 2 diff --git a/modules/exif/module.info b/modules/exif/module.info index 1e16a5ff..c8ae688e 100644 --- a/modules/exif/module.info +++ b/modules/exif/module.info @@ -1,3 +1,3 @@ -name = Exif Data +name = "Exif Data" description = "Extract Exif data and display it on photo pages." version = 1 diff --git a/modules/g2_import/module.info b/modules/g2_import/module.info index 9e04f49b..554cf33b 100644 --- a/modules/g2_import/module.info +++ b/modules/g2_import/module.info @@ -1,3 +1,3 @@ -name = Gallery2 Import -description = Import your Gallery 2 content into Gallery 3 +name = "Gallery2 Import" +description = "Import your Gallery 2 content into Gallery 3" version = 1 diff --git a/modules/gallery/module.info b/modules/gallery/module.info index c184aba7..64a30b1f 100644 --- a/modules/gallery/module.info +++ b/modules/gallery/module.info @@ -1,3 +1,3 @@ -name = Gallery 3 -description = Gallery core application +name = "Gallery 3" +description = "Gallery core application" version = 6 diff --git a/modules/gallery/tests/File_Structure_Test.php b/modules/gallery/tests/File_Structure_Test.php index 06f456ff..8a97e00b 100644 --- a/modules/gallery/tests/File_Structure_Test.php +++ b/modules/gallery/tests/File_Structure_Test.php @@ -213,6 +213,43 @@ class File_Structure_Test extends Unit_Test_Case { } } } + + public function module_info_is_well_formed_test() { + $info_files = array_merge( + glob("modules/*/module.info"), + glob("themes/*/module.info")); + + $errors = array(); + foreach ($info_files as $file) { + foreach (file($file) as $line) { + $parts = explode("=", $line, 2); + $values[trim($parts[0])] = trim($parts[1]); + } + + $module = dirname($file); + // Certain keys must exist + foreach (array("name", "description", "version") as $key) { + if (!array_key_exists($key, $values)) { + $errors[] = "$module: missing key $key"; + } + } + + // Any values containing spaces must be quoted + foreach ($values as $key => $value) { + if (strpos($value, " ") !== false && !preg_match('/^".*"$/', $value)) { + $errors[] = "$module: value for $key must be quoted"; + } + } + + // The file must parse + if (!is_array(parse_ini_file($file))) { + $errors[] = "$module: info file is not parseable"; + } + } + if ($errors) { + $this->assert_true(false, $errors); + } + } } class PhpCodeFilterIterator extends FilterIterator { diff --git a/modules/image_block/module.info b/modules/image_block/module.info index 8852d33c..e6d85048 100644 --- a/modules/image_block/module.info +++ b/modules/image_block/module.info @@ -1,3 +1,3 @@ -name = Image Block -description = Display a random image in the sidebar +name = "Image Block" +description = "Display a random image in the sidebar" version = 1 diff --git a/modules/info/module.info b/modules/info/module.info index ce03473e..e352213c 100644 --- a/modules/info/module.info +++ b/modules/info/module.info @@ -1,3 +1,3 @@ -name = Info -description = Display extra information about photos and albums +name = "Info" +description = "Display extra information about photos and albums" version = 1 diff --git a/modules/notification/module.info b/modules/notification/module.info index d4dc34e0..31684ccf 100644 --- a/modules/notification/module.info +++ b/modules/notification/module.info @@ -1,3 +1,3 @@ -name = Notification +name = "Notification" description = "Send notifications to users when changes are made to watched albums." version = 1 diff --git a/modules/organize/module.info b/modules/organize/module.info index b3ae94a3..5c6b1de0 100644 --- a/modules/organize/module.info +++ b/modules/organize/module.info @@ -1,3 +1,3 @@ -name = Organize -description = Organize your gallery by apply tags or moving images +name = "Organize" +description = "Organize your gallery by apply tags or moving images" version = 1 diff --git a/modules/recaptcha/module.info b/modules/recaptcha/module.info index 9f44648a..cfa1bf7a 100644 --- a/modules/recaptcha/module.info +++ b/modules/recaptcha/module.info @@ -1,3 +1,3 @@ -name = reCAPTCHA +name = "reCAPTCHA" description = "reCAPTCHA displays a graphical verification that protects the input form from abuse from 'bots,' or automated programs usually written to generate spam (http://recaptcha.net)." version = 1 diff --git a/modules/rss/module.info b/modules/rss/module.info index ffd26192..81ee7848 100644 --- a/modules/rss/module.info +++ b/modules/rss/module.info @@ -1,3 +1,3 @@ -name = RSS -description = Provide a RSS feeds +name = "RSS" +description = "Provide a RSS feeds" version = 1 diff --git a/modules/search/module.info b/modules/search/module.info index b286ab6c..f417c4fa 100644 --- a/modules/search/module.info +++ b/modules/search/module.info @@ -1,3 +1,3 @@ -name = Search -description = Allows users to search their Gallery +name = "Search" +description = "Allows users to search their Gallery" version = 1 diff --git a/modules/server_add/module.info b/modules/server_add/module.info index 295d3beb..23acab94 100644 --- a/modules/server_add/module.info +++ b/modules/server_add/module.info @@ -1,3 +1,3 @@ -name = Server Add -description = Allows authorized users to load images directly from your web server +name = "Server Add" +description = "Allows authorized users to load images directly from your web server" version = 3 diff --git a/modules/slideshow/module.info b/modules/slideshow/module.info index 5eb69ce3..6841199a 100644 --- a/modules/slideshow/module.info +++ b/modules/slideshow/module.info @@ -1,3 +1,3 @@ -name = Slideshow -description = Allows users to view a slideshow of photos +name = "Slideshow" +description = "Allows users to view a slideshow of photos" version = 1 diff --git a/modules/tag/module.info b/modules/tag/module.info index 562d5c32..e505dd81 100644 --- a/modules/tag/module.info +++ b/modules/tag/module.info @@ -1,3 +1,3 @@ -name = Tags -description = Allows users to tag photos and albums +name = "Tags" +description = "Allows users to tag photos and albums" version = 1 diff --git a/modules/user/module.info b/modules/user/module.info index 2dba517d..8a9af407 100644 --- a/modules/user/module.info +++ b/modules/user/module.info @@ -1,3 +1,3 @@ -name = Users and Groups -description = Provides user and group management +name = "Users and Groups" +description = "Provides user and group management" version = 1 diff --git a/modules/watermark/module.info b/modules/watermark/module.info index 7f866695..abd4a3cf 100644 --- a/modules/watermark/module.info +++ b/modules/watermark/module.info @@ -1,3 +1,3 @@ -name = Watermarks -description = Allows users to watermark their photos +name = "Watermarks" +description = "Allows users to watermark their photos" version = 1 diff --git a/themes/admin_default/theme.info b/themes/admin_default/theme.info index d21b0ff5..b3d9741d 100644 --- a/themes/admin_default/theme.info +++ b/themes/admin_default/theme.info @@ -1,6 +1,6 @@ -name = Gallery Default -description = A crisp Site Administration theme with soft colors and drop down menus. +name = "Gallery Default" +description = "A crisp Site Administration theme with soft colors and drop down menus." version = 1 -author = Gallery Team +author = "Gallery Team" admin = 1 site = 0 diff --git a/themes/default/theme.info b/themes/default/theme.info index 71e8a740..5f19d0d7 100644 --- a/themes/default/theme.info +++ b/themes/default/theme.info @@ -1,6 +1,6 @@ -name = Gallery Default -description = A crisp and distinctive theme that uses large fonts and icons for easy navigation and an enjoyable browsing experience. +name = "Gallery Default" +description = "A crisp and distinctive theme that uses large fonts and icons for easy navigation and an enjoyable browsing experience." version = 1 -author = Gallery Team +author = "Gallery Team" site = 1 admin = 0 -- cgit v1.2.3