[ansel] Patch to convert Ansel to the PHP native exif functions

Heath S. Hendrickson heath at outerspaceconsultants.com
Tue Jan 20 14:09:26 PST 2004


Attached is a file with patches (made via 'cvs diff -u [files] > 
output') to:
  templates/view/exif-image.inc
  templates/image/exif.inc
  lib/Exif.php

that replace the Exifer code with the native PHP exif function call 
(exif_read_data()).

They should be compliant with the coding standards, but cleanliness may 
be another matter (I did my best, but that's not necessarily saying much).

I'm only submitting these as a proof-of-concept, so if you decide to 
include them or not, it's up to the maintainers.

Pros:
- supports pretty labels for the fields
- supports units for data where appropriate
- inline image display is done in a 3 column table now instead of the 
wrapped mega-line
- easy to add extra EXIF fields to the output, just modify 
exif-image.inc and exif.inc

Cons:
- not the best support for proprietary "makernote" data
   -> the data is all there, but turning the values into something 
useful is dependent on the schema used by the camera maker
   -> none of this was included in the original Ansel Exif display anyway
- requires PHP >= 4.2.0 compiled with exif support

heath
-------------- next part --------------
Index: templates/view/exif-image.inc
===================================================================
RCS file: /usr/local/horde/cvs/ansel/templates/view/exif-image.inc,v
retrieving revision 1.1
diff -u -r1.1 exif-image.inc
--- templates/view/exif-image.inc	19 Jan 2004 22:37:55 -0000	1.1
+++ templates/view/exif-image.inc	20 Jan 2004 21:39:45 -0000
@@ -2,32 +2,66 @@
 require_once ANSEL_BASE . '/lib/Exif.php';
 $imageFile = $image->toFile();
 $result = read_exif_data_raw($imageFile);
-if (!empty($result['ValidEXIFData'])) {
-    $IDF0 = array('Make', 'Model', 'Orientation', 'xResolution',
-                  'yResolution', 'ResolutionUnit', 'Software', 'DateTime',
-                  'YCbCrPositioning');
-    $SubIDF = array('ExposureTime', 'FNumber', 'ExifVersion',
-                    'DateTimeOriginal', 'DateTimedigitized', 'ComponentsConfiguration',
-                    'ComponentsConfiguration', 'CompressedBitsPerPixel',
-                    'ShutterSpeedValue', 'ApertureValue', 'MeteringMode', 'Flash',
-                    'FocalLength', 'UserComment', 'ColorSpace', 'ExifImageWidth',
-                    'ExifImageHeight', 'SensingMethod', 'FileSource');
+if ($result) {
+    // Array of EXIF fields to populate. 
+    // The key is the Exif field name, the value is the display name.
+    $ExifFields = array('Make' => 'Camera Make', 
+                        'Model' => 'Camera Model',  
+			'ImageType' => 'Image Type',
+       			'FileSize' => 'File Size',
+			'DateTime' => 'Image Taken', 
+			'ExifImageWidth' => 'Width', 
+			'ExifImageLength' => 'Height', 
+			'XResolution' => 'X Resolution',
+                  	'YResolution' => 'Y Resolution',	
+			'ShutterSpeedValue' => 'Shutter Speed', 
+			'ExposureTime' => 'Exposure', 
+			'FocalLength' => 'Focal Length', 
+			'ApertureValue' => 'Aperture',
+                  	'FNumber' => 'F-Number', 
+			'ISOSpeedRatings' => 'ISO Setting' , 
+			'ExposureBiasValue' => 'Exposure Bias', 
+			'ExposureMode' => 'Exposure Mode',
+			'MeteringMode' => 'Metering Mode', 
+			'Flash' => 'Flash Setting',
+                  	'UserComment' => 'User Comment', 
+			'ColorSpace' => 'Color Space', 
+			'SensingMethod' => 'Sensing Method', 
+			'WhiteBalance' => 'White Balance', 
+			'Orientation' => 'Camera Orientation',
+			'Copyright' => 'Copyright'
+		       );
 
     $output = array();
-
-    foreach ($result['IFD0'] as $key => $value) {
-        if (in_array($key, $IDF0) && trim($value) != '') {
-            $output[] = "<b>$key</b>:&nbsp;$value";
-        }
+    $keys = array();
+    foreach ($ExifFields as $field => $desc) {
+        array_key_exists($field,$result) ?  $data = $result[$field] : $data = '';
+        if (trim($data) == '') { continue; }
+        $data = convert_exif_data($field,$data);
+        $output[] = "<td class='item'><b>$desc</b>:</td<td class='item'>$data</td>";
     }
 
-    foreach ($result['SubIFD'] as $key => $value) {
-        if (in_array($key, $SubIDF) && trim($value) != '') {
-            $output[] = "<b>$key</b>:&nbsp;$value";
+    if (count($output)) {
+        $newout = array_chunk($output,3);
+        echo '<br /><div align="center"><table border="0" cellpadding="2" cellspacing="0">';
+        foreach($newout as $elem) {
+            //echo '<td class="item" valign="top">'.implode('<br>',$elem).'</td>';
+            echo '<tr>'.implode('<td class="item">&nbsp;</td>',$elem).'</tr>';
         }
+        echo '</table></div>';
     }
 
-    if (count($output)) {
-        echo '<br /><div align="center"><table border="0" cellpadding="2" cellspacing="0"><tr><td class="item">[&nbsp;' . implode(' | ', $output) . '&nbsp;]</td></tr></table></div>';
+/* Debug output to dump the entire EXIF data
+    echo '<br>Full EXIF:<br>';
+    foreach($result as $key => $value) {
+        if(!is_array($value)) {
+            echo "$key:&nbsp;$value<br>";
+        } else {
+            foreach($value as $subvalue => $type) {
+              echo "$key.$subvalue:&nbsp;$type<br>";
+            }
+        }
     }
+*/
 }
+?>
Index: lib/Exif.php
===================================================================
RCS file: /usr/local/horde/cvs/ansel/lib/Exif.php,v
retrieving revision 1.6
diff -u -r1.6 Exif.php
--- lib/Exif.php	19 Jan 2004 22:37:54 -0000	1.6
+++ lib/Exif.php	20 Jan 2004 21:34:51 -0000
@@ -4,597 +4,7 @@
  *
  * $Horde: ansel/lib/Exif.php,v 1.5 2003/10/17 19:01:38 chuck Exp $
  *
-	Exifer 1.4
-	Extracts EXIF information from digital photos.
-
-	Copyright © 2003 Jake Olefsky
-	http://www.offsky.com/software/exif/index.php
-	jake at 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
-	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. 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
-				digital cameras.  Others will follow.
-
-	TESTED WITH:
-				Nikon CoolPix 700
-				Nikon CoolPix 4500
-				Nikon CoolPix 950
-				Nikon Coolpix 5700
-				Canon PowerShot S200
-				Canon PowerShot S110
-				Olympus C2040Z
-				Olympus C960
-				Canon Ixus
-				FujiFilm DX 10
-				FujiFilm MX-1200
-				FujiFilm FinePix2400
-				FujiFilm FinePix2600
-				FujiFilm FinePix S602
-				FujiFilm FinePix40i
-				Sony D700
-				Sony Cybershot
-				Kodak DC210
-				Kodak DC240
-				Kodak DC4800
-				Ricoh RDC-5300
-				Sanyo VPC-G250
-				Sanyo VPC-SX550
-
-	If you improve this script or test it with a camera not on my list, please email me a copy of
-	the improvement so everyone can benefit from it.  Thanks!
-
-
-	VERSION HISTORY:
-
-	1.0 	Sept 23, 2002
-
-			First Public Release
-
-	1.1		Jan 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.
-			+Modified how the imagefile is opened so it works for windows machines.
-			+Correctly parses the FocalPlaneResolutionUnit and PhotometricInterpretation fields
-			+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		Mar 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
-			+Updated the ShutterSpeedValue tag to have the units of 'sec'
-			+Added support for parsing the MakeNote of FujiFilm images
-			+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		Jun 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
-			+Several more tags are defined
-			+More information in my comments about what each tag is
-			+Parses and Displays GPS information if available
-			+Tested with several more cameras
-
-	1.4		Sept 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 a bug with the GPS code
-			+Tested with several more cameras
-*/
-//================================================================================================
-//================================================================================================
-//================================================================================================
-
-
-require_once ANSEL_BASE . '/lib/Exif/nikon.php';
-require_once ANSEL_BASE . '/lib/Exif/olympus.php';
-require_once ANSEL_BASE . '/lib/Exif/canon.php';
-require_once ANSEL_BASE . '/lib/Exif/fujifilm.php';
-require_once ANSEL_BASE . '/lib/Exif/sanyo.php';
-require_once ANSEL_BASE . '/lib/Exif/gps.php';
-
-
-//================================================================================================
-//================================================================================================
-// Converts from Intel to Motorola endian.  Just reverses the bytes (assumes hex is passed in)
-//================================================================================================
-//================================================================================================
-function intel2Moto($intel) {
-	$len = strlen($intel);
-	$moto="";
-	for($i=0; $i<=$len; $i+=2) {
-		$moto.=substr($intel, $len-$i,2);
-	}
-	return $moto;
-}
-
-//================================================================================================
-//================================================================================================
-// Looks up the name of the tag
-//================================================================================================
-//================================================================================================
-function lookup_tag($tag)
-{
-	switch($tag) {
-			//used by IFD0 'Camera Tags'
-    case '000b': $tag = 'ACDComment';break;						//text string up to 999 bytes long
-    case '00fe': $tag = 'ImageType';break;						//integer -2147483648 to 2147483647
-    case '0106': $tag = 'PhotometricInterpret';break;			//?? Please send sample image with this tag
-    case '010e': $tag = 'ImageDescription';break;				//text string up to 999 bytes long
-    case '010f': $tag = 'Make';break;							//text string up to 999 bytes long
-    case '0110': $tag = 'Model';break;							//text string up to 999 bytes long
-    case '0112': $tag = 'Orientation';break;					//integer values 1-9
-    case '0115': $tag = 'SamplePerPixel';break;					//integer 0-65535
-    case '011a': $tag = 'xResolution';break;					//positive rational number
-    case '011b': $tag = 'yResolution';break;					//positive rational number
-    case '011c': $tag = 'PlanarConfig';break;					//integer values 1-2
-		case '0128': $tag = 'ResolutionUnit';break;					//integer values 1-3
-		case '0131': $tag = 'Software';break;						//text string up to 999 bytes long
-		case '0132': $tag = 'DateTime';break;						//YYYY:MM:DD HH:MM:SS
-		case '013b': $tag = 'Artist';break;							//text string up to 999 bytes long
-		case '013e': $tag = 'WhitePoint';break;						//two positive rational numbers
-		case '013f': $tag = 'PrimaryChromaticities';break;			//six positive rational numbers
-		case '0211': $tag = 'YCbCrCoefficients';break;				//three positive rational numbers
-		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 '8825': $tag = 'GPSInfoOffset';break;
-		case '9286': $tag = 'UserCommentOld';break;					//??
-		case '8769': $tag = 'ExifOffset';break;						//positive integer
-
-			//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
-		case '8824': $tag = 'SpectralSensitivity';break;			//??
-		case '8827': $tag = 'ISOSpeedRatings';break;				//integer 0-65535
-		case '9000': $tag = 'ExifVersion';break;					//??
-		case '9003': $tag = 'DateTimeOriginal';break;				//YYYY:MM:DD HH:MM:SS
-		case '9004': $tag = 'DateTimedigitized';break;				//YYYY:MM:DD HH:MM:SS
-		case '9101': $tag = 'ComponentsConfiguration';break;		//??
-		case '9102': $tag = 'CompressedBitsPerPixel';break;			//positive rational number
-		case '9201': $tag = 'ShutterSpeedValue';break;				//seconds or fraction of seconds 1/x
-		case '9202': $tag = 'ApertureValue';break;					//positive rational number
-		case '9203': $tag = 'BrightnessValue';break;				//positive rational number
-		case '9204': $tag = 'ExposureBiasValue';break;				//positive rational number (EV)
-		case '9205': $tag = 'MaxApertureValue';break;				//positive rational number
-		case '9206': $tag = 'SubjectDistance';break;				//positive rational number (meters)
-		case '9207': $tag = 'MeteringMode';break;					//integer 1-6 and 255
-		case '9208': $tag = 'LightSource';break;					//integer 1-255
-		case '9209': $tag = 'Flash';break;							//integer 1-255
-		case '920a': $tag = 'FocalLength';break;					//positive rational number (mm)
-		case '9213': $tag = 'ImageHistory';break;					//text string up to 999 bytes long
-		case '927c': $tag = 'MakerNote';break;						//a bunch of data
-		case '9286': $tag = 'UserComment';break;					//text string
-		case '9290': $tag = 'SubsecTime';break;						//text string up to 999 bytes long
-		case '9291': $tag = 'SubsecTimeOriginal';break;				//text string up to 999 bytes long
-		case '9292': $tag = 'SubsecTimeDigitized';break;			//text string up to 999 bytes long
-		case 'a000': $tag = 'FlashPixVersion';break;				//??
-		case 'a001': $tag = 'ColorSpace';break;						//values 1 or 65535
-		case 'a002': $tag = 'ExifImageWidth';break;					//ingeter 1-65535
-		case 'a003': $tag = 'ExifImageHeight';break;				//ingeter 1-65535
-		case 'a004': $tag = 'RelatedSoundFile';break;				//text string 12 bytes long
-		case 'a005': $tag = 'ExifInteroperabilityOffset';break;		//positive integer
-		case 'a20c': $tag = 'SpacialFreqResponse';break;			//??
-		case 'a20b': $tag = 'FlashEnergy';break;					//positive rational number
-		case 'a20e': $tag = 'FocalPlaneXResolution';break;			//positive rational number
-		case 'a20f': $tag = 'FocalPlaneYResolution';break;			//positive rational number
-		case 'a210': $tag = 'FocalPlaneResolutionUnit';break;		//values 1-3
-		case 'a214': $tag = 'SubjectLocation';break;				//two integers 0-65535
-		case 'a215': $tag = 'ExposureIndex';break;					//positive rational number
-		case 'a217': $tag = 'SensingMethod';break;					//values 1-8
-		case 'a300': $tag = 'FileSource';break;						//integer
-		case 'a301': $tag = 'SceneType';break;						//integer
-		case 'a302': $tag = 'CFAPattern';break;						//undefined data type
-
-		case 'a401': $tag = 'CustomerRender';break;					//values 0 or 1
-		case 'a402': $tag = 'ExposureMode';break;					//values 0-2
-		case 'a403': $tag = 'WhiteBalance';break;					//values 0 or 1
-		case 'a404': $tag = 'DigitalZoomRatio';break;				//positive rational number
-		case 'a406': $tag = 'SceneCaptureMode';break;				//values 0-3
-		case 'a407': $tag = 'GainControl';break;					//values 0-4
-		case 'a408': $tag = 'Contrast';break;						//values 0-2
-		case 'a409': $tag = 'Saturation';break;						//values 0-2
-		case 'a40a': $tag = 'Sharpness';break;						//values 0-2
-
-
-			//used by Interoperability IFD
-		case '0001': $tag = 'InteroperabilityIndex';break; 			//text string 3 bytes long
-		case '0002': $tag = 'InteroperabilityVersion';break; 		//datatype undefined
-		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
-		case '0102': $tag = 'BitsPerSample';break;					//integers in range 0-65535
-		case '0103': $tag = 'Compression';break;					//values 1 or 6
-		case '0106': $tag = 'PhotometricInterpretation';break;		//values 0-4
-		case '010e': $tag = 'ThumbnailDescription';break;			//text string up to 999 bytes long
-		case '010f': $tag = 'ThumbnailMake';break;					//text string up to 999 bytes long
-		case '0110': $tag = 'ThumbnailModel';break;					//text string up to 999 bytes long
-		case '0111': $tag = 'StripOffsets';break;					//??
-		case '0112': $tag = 'ThumbnailOrientation';break;			//integer 1-9
-		case '0115': $tag = 'SamplesPerPixel';break;				//??
-		case '0116': $tag = 'RowsPerStrip';break;					//??
-		case '0117': $tag = 'StripByteCounts';break;				//??
-		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 '0202': $tag = 'JpegIFByteCount';break;
-		case '0212': $tag = 'YCbCrSubSampling';break;
-
-			//misc
-		case '00ff': $tag = 'SubfileType';break;
-		case '012d': $tag = 'TransferFunction';break;
-		case '013d': $tag = 'Predictor';break;
-		case '0142': $tag = 'TileWidth';break;
-		case '0143': $tag = 'TileLength';break;
-		case '0144': $tag = 'TileOffsets';break;
-		case '0145': $tag = 'TileByteCounts';break;
-		case '014a': $tag = 'SubIFDs';break;
-		case '015b': $tag = 'JPEGTables';break;
-		case '828d': $tag = 'CFARepeatPatternDim';break;
-		case '828e': $tag = 'CFAPattern';break;
-		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;
-		case '882b': $tag = 'SelfTimerMode';break;
-		case '920b': $tag = 'FlashEnergy';break;
-		case '920c': $tag = 'SpatialFrequencyResponse';break;
-		case '920d': $tag = 'Noise';break;
-		case '9211': $tag = 'ImageNumber';break;
-		case '9212': $tag = 'SecurityClassification';break;
-		case '9214': $tag = 'SubjectLocation';break;
-		case '9215': $tag = 'ExposureIndex';break;
-		case '9216': $tag = 'TIFF/EPStandardID';break;
-		case 'a20b': $tag = 'FlashEnergy';break;
-
-		default: $tag = 'unknown:'.$tag;break;
-	}
-	return $tag;
-
-}
-
-//================================================================================================
-//================================================================================================
-// Looks up the datatype
-//================================================================================================
-//================================================================================================
-function lookup_type(&$type,&$size) {
-	switch($type) {
-		case '0001': $type = 'UBYTE';$size=1;break;
-		case '0002': $type = 'ASCII';$size=1;break;
-		case '0003': $type = 'USHORT';$size=2;break;
-		case '0004': $type = 'ULONG';$size=4;break;
-		case '0005': $type = 'URATIONAL';$size=8;break;
-		case '0006': $type = 'SBYTE';$size=1;break;
-		case '0007': $type = 'UNDEFINED';$size=1;break;
-		case '0008': $type = 'SSHORT';$size=2;break;
-		case '0009': $type = 'SLONG';$size=4;break;
-		case '000a': $type = 'SRATIONAL';$size=8;break;
-		case '000b': $type = 'FLOAT';$size=4;break;
-		case '000c': $type = 'DOUBLE';$size=8;break;
-		default: $type = 'error:'.$type;$size=0;break;
-	}
-	return $type;
-}
-
-//================================================================================================
-//================================================================================================
-// Formats Data for the data type
-//================================================================================================
-//================================================================================================
-function formatData($type, $tag, $intel, $data) {
-
-	if($type=='ASCII') {
-		//do nothing
-	} 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
-			if($top/10 == 1) $data='1/'.round($bottom/10, 0).' sec';
-			else $data=$top.'/'.$bottom.' sec';
-		} else if($tag=='829d') { //FNumber
-			$data='f '.$data;
-		} else if($tag=='9204') { //ExposureBiasValue
-			$data=$data.' EV';
-		} else if($tag=='9205' || $tag=='9202') { //ApertureValue and MaxApertureValue
-			//ApertureValue is given in the APEX Mode. Many thanks to Matthieu Froment for this code
-			//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;
-		} else if($tag=='920a') { //FocalLength
-			$data=$data.' mm';
-		} else if($tag=='9201') { //ShutterSpeedValue
-			// The ShutterSpeedValue is given in the APEX mode. Many thanks to Matthieu Froment for this code
-			// The formula is : Shutter = - log2(exposureTime) (Appendix C of EXIF spec.)
-			// Where shutter is in APEX, log2(exposure) = ln(exposure)/ln(2)
-			// So final formula is : exposure = exp(-ln(2).shutter)
-			// The formula can be developed : exposure = 1/(exp(ln(2).shutter))
-			$data = exp($data * log(2));
-			if ($data > 1) $data = floor($data);  //Do not take care of what is behind the coma.
-			$data = 1/$data; //Final calculation. We now have a floating number. Transform it in a pretty number
-			$n=0;$d=0;
-			ConvertToFraction($data, $n, $d);
-			if ($n>=1 && $d==1) $data = $n.' sec'; //To avoid exposure times style 3/1 sec.
-			else $data = $n.'/'.$d.' sec';
-		}
-
-	} 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
-			if($data==1) $data = 'Normal (O deg)';
-			if($data==2) $data = 'Mirrored';
-			if($data==3) $data = 'Upsidedown';
-			if($data==4) $data = 'Upsidedown Mirrored';
-			if($data==5) $data = '90 deg CW Mirrored';
-			if($data==6) $data = '90 deg CCW';
-			if($data==7) $data = '90 deg CCW Mirrored';
-			if($data==8) $data = '90 deg CW';
-		} else if($tag=='0128' || $tag=='a210' || $tag=='0128') {  //ResolutionUnit and FocalPlaneResolutionUnit and ThumbnailResolutionUnit
-			if($data==1) $data = 'No Unit';
-			if($data==2) $data = 'Inch';
-			if($data==3) $data = 'Centimeter';
-		} else if($tag=='0213') { //YCbCrPositioning
-			if($data==1) $data = 'Center of Pixel Array';
-			if($data==2) $data = 'Datum Point';
-		} else if($tag=='8822') { //ExposureProgram
-			if($data==1) $data = 'Manual';
-			else if($data==2) $data = 'Program';
-			else if($data==3) $data = 'Aperature Priority';
-			else if($data==4) $data = 'Shutter Priority';
-			else if($data==5) $data = 'Program Creative';
-			else if($data==6) $data = 'Program Action';
-			else if($data==7) $data = 'Portrat';
-			else if($data==8) $data = 'Landscape';
-			else $data = 'Unknown: '.$data;
-		} else if($tag=='9207') { //MeteringMode
-			if($data==0) $data = 'Unknown';
-			else if($data==1) $data = 'Average';
-			else if($data==2) $data = 'Center Weighted Average';
-			else if($data==3) $data = 'Spot';
-			else if($data==4) $data = 'Multi-Spot';
-			else if($data==5) $data = 'Multi-Segment';
-			else if($data==6) $data = 'Partial';
-			else if($data==255) $data = 'Other';
-			else $data = 'Unknown: '.$data;
-		} else if($tag=='9208') { //LightSource
-			if($data==0) $data = 'Unknown or Auto';
-			else if($data==1) $data = 'Daylight';
-			else if($data==2) $data = 'Flourescent';
-			else if($data==3) $data = 'Tungsten';
-			else if($data==10) $data = 'Flash';
-			else if($data==17) $data = 'Standard Light A';
-			else if($data==18) $data = 'Standard Light B';
-			else if($data==19) $data = 'Standard Light C';
-			else if($data==20) $data = 'D55';
-			else if($data==21) $data = 'D65';
-			else if($data==22) $data = 'D75';
-			else if($data==255) $data = 'Other';
-			else $data = 'Unknown: '.$data;
-		} else if($tag=='9209') { //Flash
-			if($data==0) $data = 'No Flash';
-			else if($data==1) $data = 'Flash';
-			else if($data==5) $data = 'Flash, strobe return light not detected';
-			else if($data==7) $data = 'Flash, strob return light detected';
-			else if($data==9) $data = 'Compulsory Flash';
-			else if($data==13) $data = 'Compulsory Flash, Return light not detected';
-			else if($data==15) $data = 'Compulsory Flash, Return light detected';
-			else if($data==16) $data = 'No Flash';
-			else if($data==24) $data = 'No Flash';
-			else if($data==25) $data = 'Flash, Auto-Mode';
-			else if($data==29) $data = 'Flash, Auto-Mode, Return light not detected';
-			else if($data==31) $data = 'Flash, Auto-Mode, Return light detected';
-			else if($data==32) $data = 'No Flash';
-			else if($data==65) $data = 'Red Eye';
-			else if($data==69) $data = 'Red Eye, Return light not detected';
-			else if($data==71) $data = 'Red Eye, Return light detected';
-			else if($data==73) $data = 'Red Eye, Compulsory Flash';
-			else if($data==77) $data = 'Red Eye, Compulsory Flash, Return light not detected';
-			else if($data==79) $data = 'Red Eye, Compulsory Flash, Return light detected';
-			else if($data==89) $data = 'Red Eye, Auto-Mode';
-			else if($data==93) $data = 'Red Eye, Auto-Mode, Return light not detected';
-			else if($data==95) $data = 'Red Eye, Auto-Mode, Return light detected';
-			else $data = 'Unknown: '.$data;
-		} else if($tag=='a001') { //ColorSpace
-			if($data==1) $data = 'sRGB';
-			else $data = 'Uncalibrated';
-		} else if($tag=='a002' || $tag=='a003') { //ExifImageWidth/Height
-			$data = $data. ' pixels';
-		} else if($tag=='0103') { //Compression
-			if($data==1) $data = 'No Compression';
-			else if($data==6) $data = 'Jpeg Compression';
-			else $data = 'Unknown: '.$data;
-		} else if($tag=='a217') { //SensingMethod
-			if($data==1) $data = 'Not defined';
-			if($data==2) $data = 'One Chip Color Area Sensor';
-			if($data==3) $data = 'Two Chip Color Area Sensor';
-			if($data==4) $data = 'Three Chip Color Area Sensor';
-			if($data==5) $data = 'Color Sequential Area Sensor';
-			if($data==7) $data = 'Trilinear Sensor';
-			if($data==8) $data = 'Color Sequential Linear Sensor';
-			else $data = 'Unknown: '.$data;
-		} else if($tag=='0106') { //PhotometricInterpretation
-			if($data==1) $data = 'Monochrome';
-			else if($data==2) $data = 'RGB';
-			else if($data==6) $data = 'YCbCr';
-			else $data = 'Unknown: '.$data;
-		}
-
-	} else if($type=='UNDEFINED') {
-
-		if($tag=='9000' || $tag=='a000' || $tag=='0002') { //ExifVersion,FlashPixVersion,InteroperabilityVersion
-			$data='version '.$data/100;
-		}
-		if($tag=='a300') { //FileSource
-			$data = bin2hex($data);
-			$data	= str_replace('00','', $data);
-			$data	= str_replace('03','Digital Still Camera', $data);
-		}
-		if($tag=='a301') { //SceneType
-			$data = bin2hex($data);
-			$data	= str_replace('00','', $data);
-			$data	= str_replace('01','Directly Photographed', $data);
-		}
-		if($tag=='9101') {	//ComponentsConfiguration
-			$data = bin2hex($data);
-			$data	= str_replace('01','Y', $data);
-			$data	= str_replace('02','Cb', $data);
-			$data	= str_replace('03','Cr', $data);
-			$data	= str_replace('04','R', $data);
-			$data	= str_replace('05','G', $data);
-			$data	= str_replace('06','B', $data);
-			$data	= str_replace('00','', $data);
-		}
-	} else {
-		$data = bin2hex($data);
-		if($intel==1) $data = intel2Moto($data);
-	}
-
-	return $data;
-}
-
-//================================================================================================
-//================================================================================================
-// Reads one standard IFD entry
-//================================================================================================
-//================================================================================================
-function read_entry(&$result, $in, $seek, $intel, $ifd_name, $globalOffset) {
-
-	//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);
-
-	//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 );
-    $data = null;
-
-	if($bytesofdata<=4) { 	//if datatype is 4 bytes or less, its the value
-		$data = $value;
-	} else {				//otherwise its a pointer to the value, so lets go get it
-		$value = bin2hex($value);
-		if($intel==1) $value = intel2Moto($value);
-		$v = fseek($seek, $globalOffset+hexdec($value));  //offsets are from TIFF header which is 12 bytes from the start of the file
-		if($v==0) {
-			$data = @fread($seek, $bytesofdata);
-		} else if($v==-1) {
-			$result['Errors'] = $result['Errors']++;
-		}
-	}
-	if($tag_name=='MakerNote') { //if its a maker tag, we need to parse this specially
-		$make = isset($result['IFD0']['Make']) ? $result['IFD0']['Make'] : '';
-
-		if ($result['VerboseOutput'] == 1) {
-			$result[$ifd_name]['MakerNote']['RawData'] = $data;
-		}
-		if ($make == "NIKON\0") {
-			parseNikon($data, $result);
-			$result[$ifd_name]['KnownMaker'] = 1;
-		} elseif (stristr($make, 'OLYMPUS')){
-			parseOlympus($data, $result, $seek, $globalOffset);
-			$result[$ifd_name]['KnownMaker'] = 1;
-		} elseif (stristr($make, 'Canon')) {
-			parseCanon($data, $result, $seek, $globalOffset);
-			$result[$ifd_name]['KnownMaker'] = 1;
-		} elseif (stristr($make, 'FUJIFILM')) {
-			parseFujifilm($data, $result);
-			$result[$ifd_name]['KnownMaker'] = 1;
-		} elseif (stristr($make, 'SANYO')) {
-			parseSanyo($data, $result, $seek, $globalOffset);
-			$result[$ifd_name]['KnownMaker'] = 1;
-		} else {
-			$result[$ifd_name]['KnownMaker'] = 0;
-		}
-	} elseif ($tag_name=='GPSInfoOffset') {
-		$formated_data = formatData($type, $tag, $intel, $data);
-		$result[$ifd_name]['GPSInfo'] = $formated_data;
-		parseGPS($data, $result, $formated_data, $seek, $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);
-				if($intel==1) $data = intel2Moto($data);
-			}
-			$result[$ifd_name][$tag_name.'_Verbose']['RawData'] = $data;
-			$result[$ifd_name][$tag_name.'_Verbose']['Type'] = $type;
-			$result[$ifd_name][$tag_name.'_Verbose']['Bytes'] = $bytesofdata;
-		}
-	}
-}
+ */
 
 //================================================================================================
 //================================================================================================
@@ -608,178 +18,185 @@
 //================================================================================================
 function read_exif_data_raw($path, $verbose = 0) {
 
-	if($path=='' || $path=='none') return;
-
-	$in = fopen($path, 'rb');
-	$seek = fopen($path, 'rb'); // There may be an elegant way to do this with one file handle.
+    if($path=='' || $path=='none') return;
 
-	$globalOffset = 0;
-
-	$result['VerboseOutput'] = $verbose;
-	$result['Errors'] = 0;
-    $result['IFD0'] = array();
-    $result['SubIFD'] = array();
-
-	//First 2 bytes of JPEG are 0xFFD8
-	$data = bin2hex(fread( $in, 2 ));
-	if ($data == 'ffd8') {
-		$result['ValidJpeg'] = 1;
-	} else {
-		$result['ValidJpeg'] = 0;
-		fclose($in);
-		fclose($seek);
-		return $result;
-	}
-
-	// Next 2 bytes are MARKER tag (0xFFE#).
-	$data = bin2hex(fread($in, 2));
-	if ($data=='ffe0') {
-		$result['ValidJFIFData'] = 1;
-		$size = bin2hex(fread( $in, 2 ));
-		$result['JFIF']['Size'] = hexdec($size);
-		$ident = fread( $in, 5 );
-		$result['JFIF']['Identifier'] = $ident;
-		$code = fread( $in, 1 );
-		$result['JFIF']['ExtensionCode'] =  bin2hex($code);
-
-		$data = fread( $in, hexdec($size)-8 );
-		$result['JFIF']['Data'] = $data;
-		$globalOffset+=hexdec($size)+2;
-
-		$data = bin2hex(fread( $in, 2 ));
-	} else {
-		$result['ValidJFIFData'] = 0;
-	}
-
-	if ($data == 'ffe1') {
-		$result['ValidEXIFData'] = 1;
-	} else {
-		$result['ValidEXIFData'] = 0;
-		fclose($in);
-		fclose($seek);
-		return $result;
-	}
-
-	// Size of APP1.
-	$size = bin2hex(fread($in, 2));
-	$result['APP1Size'] = hexdec($size);
-
-	// Start of APP1 block starts with 'Exif' header (6 bytes).
-	$header = fread( $in, 6 );
-
-	// Then there's a TIFF header with 2 bytes of endianess (II or
-	// MM).
-	$header = fread($in, 2);
-	if ($header === 'II') {
-		$intel = 1;
-		$result['Endian'] = 'Intel';
-	} elseif ($header === 'MM') {
-		$intel = 0;
-		$result['Endian'] = 'Motorola';
-	} else {
-        $intel = null;
-    }
-
-	// 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);
-    }
-	if (hexdec($offset) > 8) {
-        @fread($in, hexdec($offset) - 8);
-    }
-
-	// add 12 to the offset to account for TIFF header.
-	$globalOffset += 12;
-
-	//===========================================================Start of IFD0
-	$num = bin2hex(fread($in, 2));
-	if($intel==1) $num = intel2Moto($num);
-	$result['IFD0NumTags'] = hexdec($num);
-
-	for($i=0;$i<hexdec($num);$i++) {
-		read_entry($result, $in, $seek, $intel,'IFD0', $globalOffset);
-	}
-
-	//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);
-	if($v==-1) {
-		$result['Errors'] = $result['Errors']++;
-	}
-
-	//===========================================================Start of SubIFD
-	$num = bin2hex(fread( $in, 2 ));
-	if($intel==1) $num = intel2Moto($num);
-	$result['SubIFDNumTags'] = hexdec($num);
-
-	for($i=0;$i<hexdec($num);$i++) {
-		read_entry($result, $in, $seek, $intel,'SubIFD', $globalOffset);
-	}
-
-	//Check for IFD1
-	if(!isset($result['IFD1Offset']) || $result['IFD1Offset']==0) {
-		fclose($in);
-		fclose($seek);
-		return $result;
-	}
-	//seek to IFD1
-	$v = fseek($in, $globalOffset+$result['IFD1Offset']);
-	if($v==-1) {
-		$result['Errors'] = $result['Errors']++;
-	}
-
-	//===========================================================Start of IFD1
-	$num = bin2hex(fread( $in, 2 ));
-	if($intel==1) $num = intel2Moto($num);
-	$result['IFD1NumTags'] = hexdec($num);
-
-	for($i=0;$i<hexdec($num);$i++) {
-		read_entry($result, $in, $seek, $intel,'IFD1', $globalOffset);
-	}
-
-	//Check for Interoperability IFD
-	if(!isset($result['SubIFD']['ExifInteroperabilityOffset']) || $result['SubIFD']['ExifInteroperabilityOffset']==0) {
-		fclose($in);
-		fclose($seek);
-		return $result;
-	}
-	//seek to InteroperabilityIFD
-	$v = fseek($in, $globalOffset+$result['SubIFD']['ExifInteroperabilityOffset']);
-	if($v==-1) {
-		$result['Errors'] = $result['Errors']++;
-	}
-
-	//===========================================================Start of InteroperabilityIFD
-	$num = bin2hex(fread( $in, 2 ));
-	if($intel==1) $num = intel2Moto($num);
-	$result['InteroperabilityIFDNumTags'] = hexdec($num);
-
-
-	for($i=0;$i<hexdec($num);$i++) {
-		read_entry($result, $in, $seek, $intel,'InteroperabilityIFD', $globalOffset);
-	}
-
-	fclose($in);
-	fclose($seek);
-	return $result;
+    $result['VerboseOutput'] = $verbose;
+        $result = exif_read_data($path, 0, false);
+    return $result;
+}
+
+//================================================================================================
+//================================================================================================
+// Returns the human readable form of the EXIF data.
+//================================================================================================
+//================================================================================================
+function convert_exif_data($field, $data) {
+    switch($field) {
+        case 'ExposureMode';
+            switch($data) {
+                case 0: $data = 'Easy shooting'; break;
+                case 1: $data = 'Program'; break;
+                case 2: $data = 'Tv-priority'; break;
+                case 3: $data = 'Av-priority'; break;
+                case 4: $data = 'Manual'; break;
+                case 5: $data = 'A-DEP'; break;
+            }
+            break;
+
+        case 'XResolution':
+        case 'YResolution':
+            list($n, $d) = explode('/',$data);
+            $data = $n . ' pixels';
+            break;
+
+        case 'ExifImageWidth':
+        case 'ExifImageLength':
+            $data = $data . ' pixels';
+            break;
+
+        case 'Orientation':
+            switch($data) {
+                case 1: $data = 'Normal (O deg)'; break;
+                case 2: $data = 'Mirrored'; break;
+                case 3: $data = 'Upsidedown'; break;
+                case 4: $data = 'Upsidedown Mirrored'; break;
+                case 5: $data = '90 deg CW Mirrored'; break;
+                case 6: $data = '90 deg CCW'; break;
+                case 7: $data = '90 deg CCW Mirrored'; break;
+                case 8: $data = '90 deg CW'; break;
+            }
+            break;
+
+        case 'ExposureTime':
+            $data = $data . " sec";
+            break; 
+
+        case 'ShutterSpeedValue':
+            list($n, $d) = explode('/',$data);
+            $data = $n / $d;
+            $data = exp($data * log(2));
+            if ($data > 1) { $data = floor($data); }  //Do not take care of what is behind the coma.
+            if ($data < 1) {
+                $data = round(1/$data);
+            } else { 
+                $data = '1/'.$data; 
+            }
+            $data = $data . ' sec';
+            break;
+
+        case 'ApertureValue':
+        case 'MaxApertureValue':
+            list($n, $d) = explode('/',$data);
+            $data = $n / $d;
+            $data = exp(($data*log(2))/2);
+            $data = round($data, 1);//Focal is given with a precision of 1 digit.
+            $data='f '.$data;
+            break;
+
+        case 'FocalLength':
+            list($n, $d) = explode('/',$data);
+            $data = $n . " mm";
+            break;
+
+        case 'FNumber':
+            list($n, $d) = explode('/',$data);
+            $data='f '.round($n/$d,1);
+            break;
+
+        case 'ExposureBiasValue':
+            list($n, $d) = explode('/',$data);
+            if ($n!=0) {
+                $data=$data.' EV';
+            } else {
+                $data = '0 EV';
+            }
+            break;
+
+        case 'MeteringMode':
+            switch($data) {
+                case 0: $data = 'Unknown'; break;
+                case 1: $data = 'Average'; break;
+                case 2: $data = 'Center Weighted Average'; break;
+                case 3: $data = 'Spot'; break;
+                case 4: $data = 'Multi-Spot'; break;
+                case 5: $data = 'Multi-Segment'; break;
+                case 6: $data = 'Partial'; break;
+                case 255: $data = 'Other'; break;
+            }
+            break;
+
+        case 'WhiteBalance':
+            switch ($data) {
+                case 0: $data = 'Auto'; break;
+                case 1: $data = 'Sunny'; break;
+                case 2: $data = 'Cloudy'; break;
+                case 3: $data = 'Tungsten'; break;
+                case 4: $data = 'Fluorescent'; break;
+                case 5: $data = 'Flash'; break;
+                case 6: $data = 'Custom'; break;
+                case 129: $data = 'Manual'; break;
+            }  
+            break;
+
+        case 'FocalLength':
+            $data = $data . ' mm';
+            break;
+
+        case 'Flash':
+            switch($data) {
+                case 0: $data = 'No Flash'; break;
+                case 1: $data = 'Flash'; break;
+                case 5: $data = 'Flash, strobe return light not detected'; break;
+                case 7: $data = 'Flash, strob return light detected'; break;
+                case 9: $data = 'Compulsory Flash'; break;
+                case 13: $data = 'Compulsory Flash, Return light not detected'; break;
+                case 15: $data = 'Compulsory Flash, Return light detected'; break;
+                case 16: $data = 'No Flash'; break;
+                case 24: $data = 'No Flash'; break;
+                case 25: $data = 'Flash, Auto-Mode'; break;
+                case 29: $data = 'Flash, Auto-Mode, Return light not detected'; break;
+                case 31: $data = 'Flash, Auto-Mode, Return light detected'; break;
+                case 32: $data = 'No Flash'; break;
+                case 65: $data = 'Red Eye'; break;
+                case 69: $data = 'Red Eye, Return light not detected'; break;
+                case 71: $data = 'Red Eye, Return light detected'; break;
+                case 73: $data = 'Red Eye, Compulsory Flash'; break;
+                case 77: $data = 'Red Eye, Compulsory Flash, Return light not detected'; break;
+                case 79: $data = 'Red Eye, Compulsory Flash, Return light detected'; break;
+                case 89: $data = 'Red Eye, Auto-Mode'; break;
+                case 93: $data = 'Red Eye, Auto-Mode, Return light not detected'; break;
+                case 95: $data = 'Red Eye, Auto-Mode, Return light detected'; break;
+                default: $data = 'Unknown: ' . $data;
+            }
+            break;
+
+        case 'FileSize':
+            $data = $data . ' bytes';
+            break;
+
+        case 'SensingMethod':
+            switch($data) {
+                case 1: $data = 'Not defined'; break;
+                case 2: $data = 'One Chip Color Area Sensor'; break;
+                case 3: $data = 'Two Chip Color Area Sensor'; break;
+                case 4: $data = 'Three Chip Color Area Sensor'; break;
+                case 5: $data = 'Color Sequential Area Sensor'; break;
+                case 7: $data = 'Trilinear Sensor'; break;
+                case 8: $data = 'Color Sequential Linear Sensor'; break;
+                default: $data = 'Unknown: '.$data;
+            }
+            break;
+
+        case 'ColorSpace':
+            switch($data) {
+                case 1: $data = 'sRGB'; break;
+                default: $data = 'Uncalibrated';
+            }
+            break;
+    } 
+    return $data;
 }
+
 
 //================================================================================================
 //================================================================================================
Index: templates/image/exif.inc
===================================================================
RCS file: /usr/local/horde/cvs/ansel/templates/image/exif.inc,v
retrieving revision 1.4
diff -u -r1.4 exif.inc
--- templates/image/exif.inc	14 Nov 2003 20:23:56 -0000	1.4
+++ templates/image/exif.inc	20 Jan 2004 21:57:17 -0000
@@ -9,23 +9,46 @@
 
 $output = '';
 
-if (empty($result['ValidEXIFData'])) {
+if (empty($result)) {
     $output .= '<tr><td colspan="2" class="text"><i>' . _("No embedded information found.") . '</i></td></tr>';
 } else {
-    $IDF0 = array('Make', 'Model', 'Orientation', 'xResolution', 'yResolution', 'ResolutionUnit', 'Software', 'DateTime', 'YCbCrPositioning');
-    $SubIDF = array('ExposureTime', 'FNumber', 'ExifVersion', 'DateTimeOriginal', 'DateTimedigitized', 'ComponentsConfiguration', 'ComponentsConfiguration', 'CompressedBitsPerPixel', 'ShutterSpeedValue', 'ApertureValue', 'MeteringMode', 'Flash', 'FocalLength', 'UserComment', 'ColorSpace', 'ExifImageWidth', 'ExifImageHeight', 'SensingMethod', 'FileSource');
+    // Array of EXIF fields to populate. 
+    // The key is the Exif field name, the value is the display name.
+    $ExifFields = array('Make' => 'Camera Make', 
+                        'Model' => 'Camera Model',  
+			'ImageType' => 'Image Type',
+       			'FileSize' => 'File Size',
+			'DateTime' => 'Image Taken', 
+			'ExifImageWidth' => 'Width', 
+			'ExifImageLength' => 'Height', 
+			'XResolution' => 'X Resolution',
+                  	'YResolution' => 'Y Resolution',	
+			'ShutterSpeedValue' => 'Shutter Speed', 
+			'ExposureTime' => 'Exposure', 
+			'FocalLength' => 'Focal Length', 
+			'ApertureValue' => 'Aperture',
+                  	'FNumber' => 'F-Number', 
+			'ISOSpeedRatings' => 'ISO Setting' , 
+			'ExposureBiasValue' => 'Exposure Bias', 
+			'ExposureMode' => 'Exposure Mode',
+			'MeteringMode' => 'Metering Mode', 
+			'Flash' => 'Flash Setting',
+                  	'UserComment' => 'User Comment', 
+			'ColorSpace' => 'Color Space', 
+			'SensingMethod' => 'Sensing Method', 
+			'WhiteBalance' => 'White Balance', 
+			'Orientation' => 'Camera Orientation',
+			'Copyright' => 'Copyright'
+		       );
 
-	foreach ($result['IFD0'] as $key => $value) {
-		if (in_array($key, $IDF0) && trim($value) != '') {
-            $output .= "<tr><td>&nbsp;$key</td><td>&nbsp;$value&nbsp;</td></tr>";
-        }
-	}
-
-	foreach ($result['SubIFD'] as $key => $value) {
-		if (in_array($key, $SubIDF) && trim($value) != '') {
-            $output .= "<tr><td>&nbsp;$key</td><td>&nbsp;$value&nbsp;</td></tr>";
-        }
-	}
+    $output = array();
+    $keys = array();
+    foreach ($ExifFields as $field => $desc) {
+        array_key_exists($field,$result) ?  $data = $result[$field] : $data = '';
+        if (trim($data) == '') { continue; }
+        $data = convert_exif_data($field,$data);
+        $output[] = "<tr><td class='item'><b>$desc</b>:</td<td class='item'>$data</td></td>";
+    }
 }
 
-echo '<table width="100%">' . $output . '</table>';
+echo '<table>' . implode('',$output) . '</table>';


More information about the ansel mailing list