[ansel] Ansel and Exif.php
Heath S. Hendrickson
heath at outerspaceconsultants.com
Tue Jan 20 09:09:40 PST 2004
Oops, I meant to send this to the list but instead just sent it to
Chuck... Here it is again (sorry for the duplication, Chuck).
Your impression was right, sorta. There appears to be better support
for the various camera specific "makernote" fields in the Exifer code.
I just think that the native PHP code should be faster (compiled in
versus runtime). That and it'll get you out of the game of supporting
and updating that section of code (always a plus, right). Also, the
Exifer code takes care of the conversions of the APEX format fields
(shutter speed, exposure time, f number) where I've had to do it
manually with the PHP function.
I've been playing around with re-writing the Exif code to use the native
PHP calls. While most of my modifications wouldn't necessarily be of a
lot of value now, as the PHP version of the code matures, I can imagine
most of the Exifer-based code will become either deprecated or be merged
into the main PHP tree (pure speculation on my part here).
I've attached a patch to exif-image.inc that uses the native PHP calls.
I've completely removed the dependency on lib/Exif.php.
Anyway, I can probably put together a patch that will put human readable
names on the Exif fields (I'll have to strip out my other stuff first)
if you think it would be worthwhile. I just made an associate array
with the key being the Exif field name and the value being the human
readable form.
Let me know if you'd like me to send the patch out for just the
description or if you can pull it out of the patch I've included below.
heath
P.S. In case I haven't said it already, the Horde team rocks. For a
bunch of volunteers, you guys have managed to put together something
amazing.
----------- patch to templates/view/exif-image.diff ------------
Index: templates/view/exif-image.inc
===================================================================
RCS file: /usr/local/horde/cvs/ansel/templates/view/exif-image.inc,v
retrieving revision 1.1
diff -r1.1 exif-image.inc
2c2
< require_once ANSEL_BASE . '/lib/Exif.php';
---
> //require_once ANSEL_BASE . '/lib/Exif.php';
4,14c4,33
< $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');
---
> $result = exif_read_data($imageFile, 0, false);
> 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'
> );
17,27c36,182
<
< foreach ($result['IFD0'] as $key => $value) {
< if (in_array($key, $IDF0) && trim($value) != '') {
< $output[] = "<b>$key</b>: $value";
< }
< }
<
< foreach ($result['SubIFD'] as $key => $value) {
< if (in_array($key, $SubIDF) && 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; }
> 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;
> default:
> }
> $output[] = "<b>$desc</b>: $data";
32a188,200
>
> /* 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>";
> }
> }
> }
> */
33a202
> ?>
------------ end patch ----------------
Chuck Hagenbuch wrote:
>Quoting "Heath S. Hendrickson" <heath at outerspaceconsultants.com>:
>
>
>
>>Is there any reason that Exif.php has the elaborate code for
>>read_exif_data_raw now that PHP>4.2.0 has a native function to do just
>>this? I'm guessing it's legacy, but wanted to hear first before I
>>submit a patch to replace it with a call to exif_read_data.
>>
>>
>
>I was under the impression that the code we have there provides more information
>than exif_read_data(). If that's not the case, or if it's even close, really,
>we should adapt to use the native function.
>
>-chuck
>
>--
>Charles Hagenbuch, <chuck at horde.org>
>"Here, I brought some cole slaw. It's made from peeeooople! Just kidding."
>
>
>
More information about the ansel
mailing list