[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>: $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>: $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"> </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">[ ' . implode(' | ', $output) . ' ]</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: $value<br>";
+ } else {
+ foreach($value as $subvalue => $type) {
+ echo "$key.$subvalue: $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> $key</td><td> $value </td></tr>";
- }
- }
-
- foreach ($result['SubIFD'] as $key => $value) {
- if (in_array($key, $SubIDF) && trim($value) != '') {
- $output .= "<tr><td> $key</td><td> $value </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