source: extensions/exif_view/main.inc.php @ 30219

Last change on this file since 30219 was 27556, checked in by plg, 11 years ago

avoid division by zero on digital zoom

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 11.6 KB
Line 
1<?php /*
2Plugin Name: Exif View
3Version: 2.6.b
4Description: Converts EXIF values to human readable localized values. Corresponds to EXIF specification 2.2, details in http://www.exif.org. Easily extensible.
5Plugin URI: http://piwigo.org/ext/extension_view.php?eid=155
6Author: Martin Javorek
7Author URI: mailto:maple@seznam.cz&subject=PWG%20EXIF%20View
8*/
9
10/*
11-------------------------------------------------------------------------------
12Change log:
13
140.2, 23th August 2007
15- exposurue bias fix, date time original formatting
16
170.1, 1st August 2007
18- initial version
19
20
21-------------------------------------------------------------------------------
22
23Extend your configuration in /include/config.local.inc.php file - example:
24
25$conf['show_exif_fields'] = array(
26  'Make',
27  'Model',
28  'ExifVersion',
29  'Software',
30  'DateTimeOriginal',
31  'FNumber',
32  'ExposureBiasValue',
33  'FILE;FileSize',
34  'ExposureTime',
35  'Flash',
36  'ISOSpeedRatings',
37  'FocalLength',
38  'FocalLengthIn35mmFilm',
39  'WhiteBalance',
40  'ExposureMode',
41  'MeteringMode',
42  'ExposureProgram',
43  'LightSource',
44  'Contrast',
45  'Saturation',
46  'Sharpness',
47  );
48
49*/
50
51add_event_handler('format_exif_data', 'exif_translation' );
52
53/**
54 * Date and time format.
55 * @see http://cz2.php.net/manual/en/function.date.php
56 */
57define('DATE_TIME_FORMAT', 'H:i:s j.n.Y');
58
59/**
60 * Truncates number.
61 *
62 * @param num number
63 * @param digits number of digits, default 0
64 */
65function truncate($num, $digits = 0) {
66    $shift = pow(10 , $digits);
67    return ((floor($num * $shift)) / $shift);
68}
69
70/**
71 * Format date.
72 *
73 * @param date given EXIF date
74 */
75function formatDate($date) {
76        $dateTime = explode(' ', $date);
77        $d = explode(':', $dateTime[0]);
78        $t = explode(':', $dateTime[1]);
79        // beware of american date format for mktime, it accepts date in M/D/Y ;-)
80        return date(DATE_TIME_FORMAT, mktime($t[0], $t[1], $t[2], $d[1], $d[2], $d[0]));
81}
82
83/**
84 * EXIF translation.
85 *
86 * @param $key EXIF key name
87 * @param $value EXIF key value
88 * @return translated value depending on key meaning and choosed language
89 */
90function exif_key_translation($key, $value) {
91   // EXIF
92        if (!(strpos($key, 'ExifVersion') === FALSE)) {
93      return $value[1].'.'.$value[2];
94   }
95   
96   // Date Time Original
97   if (!(strpos($key, 'DateTimeOriginal') === FALSE)) {
98     // to fix bug:1862 the easiest way without releasing a new version of
99     // Piwigo itself, it's better to bypass the date format function
100     //
101     // return formatDate($value);
102     return $value;
103   }
104
105   // exposure time
106         if (!(strpos($key, 'ExposureTime') === FALSE)) {
107      $tokens = explode('/', $value);
108      while ($tokens[0] % 10 == 0) {
109         $tokens[0] = $tokens[0] / 10;
110         $tokens[1] = $tokens[1] / 10;
111      }
112      if ($tokens[1] == 1) {
113         return $tokens[0].' s';
114      } else {
115        return '1/'.floor(1/($tokens[0]/$tokens[1])).' s';
116         // return $tokens[0].'/'.$tokens[1].' s';
117      }
118   }
119
120   // aperture
121         if (!(strpos($key, 'FNumber') === FALSE)) {
122      $tokens = explode('/', $value);
123      return $tokens[0]/$tokens[1];
124   }
125
126   // flash
127   if (!(strpos($key, 'Flash') === FALSE)) {
128      // 1st bit is fired/did not fired
129      if (($value & 1) > 0) {
130         $retValue = l10n('yes');
131      } else {
132         $retValue = l10n('no');
133      }
134      // 2nd+3rd bits are return light mode
135      $returnLight = $value & (3 << 1);
136      switch ($returnLight) {
137        case 2 << 1: $retValue .= ', '.l10n('exif_value_flash_return_light_not_detected');break;
138        case 3 << 1: $retValue .= ', '.l10n('exif_value_flash_return_light_detected');break;
139      }
140      // 4th+5th bits are mode
141      $mode = $value & (3 << 3);
142      switch ($mode) {
143        case 0: $retValue .= ', '.l10n('exif_value_flash_mode').': '.l10n('exif_value_flash_mode_unknown');break;
144        case 1 << 3: $retValue .= ', '.l10n('exif_value_flash_mode').': '.l10n('exif_value_flash_mode_compulsory');break;
145        case 2 << 3: $retValue .= ', '.l10n('exif_value_flash_mode').': '.l10n('exif_value_flash_mode_supress');break;
146        case 3 << 3: $retValue .= ', '.l10n('exif_value_flash_mode').': '.l10n('exif_value_flash_mode_auto');break;
147      }
148                        // 6th bit is red eye function
149      if (($value & (1 << 6)) > 0) {
150         $retValue .= ', '.l10n('exif_value_red_eye');
151      }
152      return $retValue;
153   }
154
155   // exposure bias
156   if (!(strpos($key, 'ExposureBiasValue') === FALSE)) {
157      $tokens = explode('/', $value);
158      $newValue = $tokens[0] / $tokens[1];
159      // max EV range +-
160      $maxEV = 5;
161      // default value
162      $retValue = $newValue;
163      $absValue = truncate(abs($newValue), 2);
164      $found = FALSE;
165      // find through 1/3
166      for ($i = 1; $i <= $maxEV * 3 ; $i++) {
167         $ev = floor($i * 1/3.0 * 100) / 100;
168         if ($ev == $absValue) {
169            if ($i > 3) {
170               $retValue = (truncate($i / 3)).' '.($i % 3).'/3';
171            } else {
172               $retValue = $i.'/3';
173            }
174            $found = TRUE;
175            break;
176         }
177      }
178      // find through 1/2
179      if (!$found) {
180         for ($i = 1; $i <= $maxEV * 2 ; $i++) {
181            $ev = floor($i * 1/2.0 * 100) / 100;
182            if ($ev == $absValue) {
183               if ($i > 2) {
184                  $retValue = ($i / 2).' '.($i % 2).'/2';
185               } else {
186                  $retValue = $i.'/2';
187               }
188               $found = TRUE;
189               break;
190            }
191         }
192      }
193      // signs
194      if (($newValue < 0) && $found) {
195         $retValue = '- '.$retValue;
196      }
197      if ($newValue > 0) {
198         $retValue = '+ '.$retValue;
199      }
200      return $retValue.' EV';
201   }
202
203   // focal length 35mm
204   if (!(strpos($key, 'FocalLengthIn35mmFilm') === FALSE)) {
205      return $value.' mm';
206   }
207
208   // focal length
209   if (!(strpos($key, 'FocalLength') === FALSE)) {
210      $tokens = explode('/', $value);
211      return (round($tokens[0]/$tokens[1])).' mm';
212   }
213
214   // digital zoom
215   if (!(strpos($key, 'DigitalZoomRatio') === FALSE)) {
216      $tokens = explode('/', $value);
217      if (isset($tokens[1]))
218      {
219        if ($tokens[1] > 0)
220        {
221          return ($tokens[0]/$tokens[1]);
222        }
223        else
224        {
225          return $tokens[0];
226        }
227      }
228      else
229      {
230        return $value;
231      }
232   }
233
234   // distance to subject
235   if (!(strpos($key, 'SubjectDistance') === FALSE)) {
236      $tokens = explode('/', $value);
237      if (isset($tokens[1]))
238      { 
239        $distance = $tokens[0]/$tokens[1];
240      }
241      else
242      { 
243        $distance = $value;
244      }
245      return $distance.' m';
246   }
247
248   // white balance
249   if (!(strpos($key, 'WhiteBalance') === FALSE)) {
250      switch ($value) {
251         case 0: return l10n('exif_value_white_balance_auto');
252         case 1: return l10n('exif_value_white_balance_manual');
253         default: return '';
254      }
255   }
256
257   // exposure mode
258   if (!(strpos($key, 'ExposureMode') === FALSE)) {
259      switch ($value) {
260         case 0: return l10n('exif_value_exposure_mode_auto');
261         case 1: return l10n('exif_value_exposure_mode_manual');
262         case 2: return l10n('exif_value_exposure_mode_auto_bracket');
263         default: return '';
264      }
265   }
266
267   // exposure metering mode
268   if (!(strpos($key, 'MeteringMode') === FALSE)) {
269      switch ($value) {
270         case 0: return l10n('exif_value_metering_mode_unknown');
271         case 1: return l10n('exif_value_metering_mode_average');
272         case 2: return l10n('exif_value_metering_mode_CenterWeightedAVG');
273         case 3: return l10n('exif_value_metering_mode_spot');
274         case 4: return l10n('exif_value_metering_mode_multispot');
275         case 5: return l10n('exif_value_metering_mode_pattern');
276         case 6: return l10n('exif_value_metering_mode_partial');
277         default: return '';
278      }
279   }
280
281   // exposure program
282   if (!(strpos($key, 'ExposureProgram') === FALSE)) {
283      switch ($value) {
284         case 0: return l10n('exif_value_exposure_program_not_defined');
285         case 1: return l10n('exif_value_exposure_program_manual');
286         case 2: return l10n('exif_value_exposure_program_normal');
287         case 3: return l10n('exif_value_exposure_program_aperture');
288         case 4: return l10n('exif_value_exposure_program_shutter');
289         case 5: return l10n('exif_value_exposure_program_creative');
290         case 6: return l10n('exif_value_exposure_program_action');
291         case 7: return l10n('exif_value_exposure_program_portrait');
292         case 8: return l10n('exif_value_exposure_program_landscape');
293         default: return '';
294      }
295   }
296   
297   // light source
298   if (!(strpos($key, 'LightSource') === FALSE)) {
299      switch ($value) {
300         case 0: return l10n('exif_value_light_source_unknown');
301         case 1: return l10n('exif_value_light_source_daylight');
302         case 2: return l10n('exif_value_light_source_fluorescent');
303         case 3: return l10n('exif_value_light_source_tungsten');
304         case 4: return l10n('exif_value_light_source_flash');
305         case 9: return l10n('exif_value_light_source_fine_weather');
306         case 10: return l10n('exif_value_light_source_cloudy_weather');
307         case 11: return l10n('exif_value_light_source_shade');
308         case 12: return l10n('exif_value_light_source_daylight_fluorescent_d');
309         case 13: return l10n('exif_value_light_source_daywhite_fluorescent_n');
310         case 14: return l10n('exif_value_light_source_coolwhite_fluorescent_w');
311         case 15: return l10n('exif_value_light_source_white_fluorescent');
312         case 17: return l10n('exif_value_light_source_standard_light_a');
313         case 18: return l10n('exif_value_light_source_standard_light_b');
314         case 19: return l10n('exif_value_light_source_standard_light_c');
315         case 20: return l10n('exif_value_light_source_D55');
316         case 21: return l10n('exif_value_light_source_D65');
317         case 22: return l10n('exif_value_light_source_D75');
318         case 23: return l10n('exif_value_light_source_D50');
319         case 24: return l10n('exif_value_light_source_iso_studio_tungsten');
320         case 255: return l10n('exif_value_light_source_other');
321         default: return '';
322      }
323   }
324
325   // contrast
326   if (!(strpos($key, 'Contrast') === FALSE)) {
327      switch ($value) {
328         case 0: return l10n('exif_value_contrast_normal');
329         case 1: return l10n('exif_value_contrast_soft');
330         case 2: return l10n('exif_value_contrast_hard');
331         default: return '';
332      }
333   }
334
335   // sharpness
336   if (!(strpos($key, 'Sharpness') === FALSE)) {
337      switch ($value) {
338         case 0: return l10n('exif_value_sharpness_normal');
339         case 1: return l10n('exif_value_sharpness_soft');
340         case 2: return l10n('exif_value_sharpness_hard');
341         default: return '';
342      }
343   }
344
345   // saturation
346   if (!(strpos($key, 'Saturation') === FALSE)) {
347      switch ($value) {
348         case 0: return l10n('exif_value_saturation_normal');
349         case 1: return l10n('exif_value_saturation_low');
350         case 2: return l10n('exif_value_saturation_hard');
351         default: return '';
352      }
353   }
354
355   // return value unchanged
356   return $value;
357}
358define('exif_DIR' , basename(dirname(__FILE__)));
359define('exif_PATH' , PHPWG_PLUGINS_PATH . exif_DIR . '/');
360        /**
361         * Loads plugin language file.
362         */
363  function loadLang() {
364    global $lang;
365    load_language('lang.exif', exif_PATH);
366  }
367
368/**
369 * EXIF translation.
370 *
371 * @param $key EXIF key name
372 * @param $value EXIF key value
373 * @return translated value dependend on key meaning and choosed language
374 */
375function exif_translation($exif) {
376         // translate all exif fields
377         if (is_array($exif)) {
378         loadLang();
379
380           foreach ($exif as $key => $value) {
381                         $exif[$key] = exif_key_translation($key, $value);
382           }
383         }
384   return $exif;
385}
386
387?>
Note: See TracBrowser for help on using the repository browser.