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

Last change on this file since 32179 was 30355, checked in by plg, 10 years ago

avoid division by zero on ExposureTime

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 11.8 KB
Line 
1<?php /*
2Plugin Name: Exif View
3Version: 2.7.a
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
109      if (isset($tokens[1]))
110      {
111        if ($tokens[1] > 0)
112        {
113          while ($tokens[0] % 10 == 0)
114          {
115            $tokens[0] = $tokens[0] / 10;
116            $tokens[1] = $tokens[1] / 10;
117          }
118         
119          if ($tokens[1] == 1)
120          {
121            return $tokens[0].' s';
122          }
123          else
124          {
125            return '1/'.floor(1/($tokens[0]/$tokens[1])).' s';
126          }
127        }
128        else
129        {
130          return $tokens[0].' s';
131        }
132      }
133      else
134      {
135        return $value.' s';
136      }
137   }
138
139   // aperture
140         if (!(strpos($key, 'FNumber') === FALSE)) {
141      $tokens = explode('/', $value);
142      return $tokens[0]/$tokens[1];
143   }
144
145   // flash
146   if (!(strpos($key, 'Flash') === FALSE)) {
147      // 1st bit is fired/did not fired
148      if (($value & 1) > 0) {
149         $retValue = l10n('yes');
150      } else {
151         $retValue = l10n('no');
152      }
153      // 2nd+3rd bits are return light mode
154      $returnLight = $value & (3 << 1);
155      switch ($returnLight) {
156        case 2 << 1: $retValue .= ', '.l10n('exif_value_flash_return_light_not_detected');break;
157        case 3 << 1: $retValue .= ', '.l10n('exif_value_flash_return_light_detected');break;
158      }
159      // 4th+5th bits are mode
160      $mode = $value & (3 << 3);
161      switch ($mode) {
162        case 0: $retValue .= ', '.l10n('exif_value_flash_mode').': '.l10n('exif_value_flash_mode_unknown');break;
163        case 1 << 3: $retValue .= ', '.l10n('exif_value_flash_mode').': '.l10n('exif_value_flash_mode_compulsory');break;
164        case 2 << 3: $retValue .= ', '.l10n('exif_value_flash_mode').': '.l10n('exif_value_flash_mode_supress');break;
165        case 3 << 3: $retValue .= ', '.l10n('exif_value_flash_mode').': '.l10n('exif_value_flash_mode_auto');break;
166      }
167                        // 6th bit is red eye function
168      if (($value & (1 << 6)) > 0) {
169         $retValue .= ', '.l10n('exif_value_red_eye');
170      }
171      return $retValue;
172   }
173
174   // exposure bias
175   if (!(strpos($key, 'ExposureBiasValue') === FALSE)) {
176      $tokens = explode('/', $value);
177      $newValue = $tokens[0] / $tokens[1];
178      // max EV range +-
179      $maxEV = 5;
180      // default value
181      $retValue = $newValue;
182      $absValue = truncate(abs($newValue), 2);
183      $found = FALSE;
184      // find through 1/3
185      for ($i = 1; $i <= $maxEV * 3 ; $i++) {
186         $ev = floor($i * 1/3.0 * 100) / 100;
187         if ($ev == $absValue) {
188            if ($i > 3) {
189               $retValue = (truncate($i / 3)).' '.($i % 3).'/3';
190            } else {
191               $retValue = $i.'/3';
192            }
193            $found = TRUE;
194            break;
195         }
196      }
197      // find through 1/2
198      if (!$found) {
199         for ($i = 1; $i <= $maxEV * 2 ; $i++) {
200            $ev = floor($i * 1/2.0 * 100) / 100;
201            if ($ev == $absValue) {
202               if ($i > 2) {
203                  $retValue = ($i / 2).' '.($i % 2).'/2';
204               } else {
205                  $retValue = $i.'/2';
206               }
207               $found = TRUE;
208               break;
209            }
210         }
211      }
212      // signs
213      if (($newValue < 0) && $found) {
214         $retValue = '- '.$retValue;
215      }
216      if ($newValue > 0) {
217         $retValue = '+ '.$retValue;
218      }
219      return $retValue.' EV';
220   }
221
222   // focal length 35mm
223   if (!(strpos($key, 'FocalLengthIn35mmFilm') === FALSE)) {
224      return $value.' mm';
225   }
226
227   // focal length
228   if (!(strpos($key, 'FocalLength') === FALSE)) {
229      $tokens = explode('/', $value);
230      return (round($tokens[0]/$tokens[1])).' mm';
231   }
232
233   // digital zoom
234   if (!(strpos($key, 'DigitalZoomRatio') === FALSE)) {
235      $tokens = explode('/', $value);
236      if (isset($tokens[1]))
237      {
238        if ($tokens[1] > 0)
239        {
240          return ($tokens[0]/$tokens[1]);
241        }
242        else
243        {
244          return $tokens[0];
245        }
246      }
247      else
248      {
249        return $value;
250      }
251   }
252
253   // distance to subject
254   if (!(strpos($key, 'SubjectDistance') === FALSE)) {
255      $tokens = explode('/', $value);
256      if (isset($tokens[1]))
257      { 
258        $distance = $tokens[0]/$tokens[1];
259      }
260      else
261      { 
262        $distance = $value;
263      }
264      return $distance.' m';
265   }
266
267   // white balance
268   if (!(strpos($key, 'WhiteBalance') === FALSE)) {
269      switch ($value) {
270         case 0: return l10n('exif_value_white_balance_auto');
271         case 1: return l10n('exif_value_white_balance_manual');
272         default: return '';
273      }
274   }
275
276   // exposure mode
277   if (!(strpos($key, 'ExposureMode') === FALSE)) {
278      switch ($value) {
279         case 0: return l10n('exif_value_exposure_mode_auto');
280         case 1: return l10n('exif_value_exposure_mode_manual');
281         case 2: return l10n('exif_value_exposure_mode_auto_bracket');
282         default: return '';
283      }
284   }
285
286   // exposure metering mode
287   if (!(strpos($key, 'MeteringMode') === FALSE)) {
288      switch ($value) {
289         case 0: return l10n('exif_value_metering_mode_unknown');
290         case 1: return l10n('exif_value_metering_mode_average');
291         case 2: return l10n('exif_value_metering_mode_CenterWeightedAVG');
292         case 3: return l10n('exif_value_metering_mode_spot');
293         case 4: return l10n('exif_value_metering_mode_multispot');
294         case 5: return l10n('exif_value_metering_mode_pattern');
295         case 6: return l10n('exif_value_metering_mode_partial');
296         default: return '';
297      }
298   }
299
300   // exposure program
301   if (!(strpos($key, 'ExposureProgram') === FALSE)) {
302      switch ($value) {
303         case 0: return l10n('exif_value_exposure_program_not_defined');
304         case 1: return l10n('exif_value_exposure_program_manual');
305         case 2: return l10n('exif_value_exposure_program_normal');
306         case 3: return l10n('exif_value_exposure_program_aperture');
307         case 4: return l10n('exif_value_exposure_program_shutter');
308         case 5: return l10n('exif_value_exposure_program_creative');
309         case 6: return l10n('exif_value_exposure_program_action');
310         case 7: return l10n('exif_value_exposure_program_portrait');
311         case 8: return l10n('exif_value_exposure_program_landscape');
312         default: return '';
313      }
314   }
315   
316   // light source
317   if (!(strpos($key, 'LightSource') === FALSE)) {
318      switch ($value) {
319         case 0: return l10n('exif_value_light_source_unknown');
320         case 1: return l10n('exif_value_light_source_daylight');
321         case 2: return l10n('exif_value_light_source_fluorescent');
322         case 3: return l10n('exif_value_light_source_tungsten');
323         case 4: return l10n('exif_value_light_source_flash');
324         case 9: return l10n('exif_value_light_source_fine_weather');
325         case 10: return l10n('exif_value_light_source_cloudy_weather');
326         case 11: return l10n('exif_value_light_source_shade');
327         case 12: return l10n('exif_value_light_source_daylight_fluorescent_d');
328         case 13: return l10n('exif_value_light_source_daywhite_fluorescent_n');
329         case 14: return l10n('exif_value_light_source_coolwhite_fluorescent_w');
330         case 15: return l10n('exif_value_light_source_white_fluorescent');
331         case 17: return l10n('exif_value_light_source_standard_light_a');
332         case 18: return l10n('exif_value_light_source_standard_light_b');
333         case 19: return l10n('exif_value_light_source_standard_light_c');
334         case 20: return l10n('exif_value_light_source_D55');
335         case 21: return l10n('exif_value_light_source_D65');
336         case 22: return l10n('exif_value_light_source_D75');
337         case 23: return l10n('exif_value_light_source_D50');
338         case 24: return l10n('exif_value_light_source_iso_studio_tungsten');
339         case 255: return l10n('exif_value_light_source_other');
340         default: return '';
341      }
342   }
343
344   // contrast
345   if (!(strpos($key, 'Contrast') === FALSE)) {
346      switch ($value) {
347         case 0: return l10n('exif_value_contrast_normal');
348         case 1: return l10n('exif_value_contrast_soft');
349         case 2: return l10n('exif_value_contrast_hard');
350         default: return '';
351      }
352   }
353
354   // sharpness
355   if (!(strpos($key, 'Sharpness') === FALSE)) {
356      switch ($value) {
357         case 0: return l10n('exif_value_sharpness_normal');
358         case 1: return l10n('exif_value_sharpness_soft');
359         case 2: return l10n('exif_value_sharpness_hard');
360         default: return '';
361      }
362   }
363
364   // saturation
365   if (!(strpos($key, 'Saturation') === FALSE)) {
366      switch ($value) {
367         case 0: return l10n('exif_value_saturation_normal');
368         case 1: return l10n('exif_value_saturation_low');
369         case 2: return l10n('exif_value_saturation_hard');
370         default: return '';
371      }
372   }
373
374   // return value unchanged
375   return $value;
376}
377define('exif_DIR' , basename(dirname(__FILE__)));
378define('exif_PATH' , PHPWG_PLUGINS_PATH . exif_DIR . '/');
379        /**
380         * Loads plugin language file.
381         */
382  function loadLang() {
383    global $lang;
384    load_language('lang.exif', exif_PATH);
385  }
386
387/**
388 * EXIF translation.
389 *
390 * @param $key EXIF key name
391 * @param $value EXIF key value
392 * @return translated value dependend on key meaning and choosed language
393 */
394function exif_translation($exif) {
395         // translate all exif fields
396         if (is_array($exif)) {
397         loadLang();
398
399           foreach ($exif as $key => $value) {
400                         $exif[$key] = exif_key_translation($key, $value);
401           }
402         }
403   return $exif;
404}
405
406?>
Note: See TracBrowser for help on using the repository browser.