Overview

Packages

  • Image
  • None

Classes

  • Horde_Image
  • Horde_Image_Base
  • Horde_Image_Effect
  • Horde_Image_Effect_Border
  • Horde_Image_Effect_Gd_DropShadow
  • Horde_Image_Effect_Gd_RoundCorners
  • Horde_Image_Effect_Gd_TextWatermark
  • Horde_Image_Effect_Gd_Unsharpmask
  • Horde_Image_Effect_Im_Border
  • Horde_Image_Effect_Im_CenterCrop
  • Horde_Image_Effect_Im_Composite
  • Horde_Image_Effect_Im_DropShadow
  • Horde_Image_Effect_Im_LiquidResize
  • Horde_Image_Effect_Im_PhotoStack
  • Horde_Image_Effect_Im_PolaroidImage
  • Horde_Image_Effect_Im_RoundCorners
  • Horde_Image_Effect_Im_TextWatermark
  • Horde_Image_Effect_Im_Unsharpmask
  • Horde_Image_Effect_Imagick_Border
  • Horde_Image_Effect_Imagick_CenterCrop
  • Horde_Image_Effect_Imagick_Composite
  • Horde_Image_Effect_Imagick_DropShadow
  • Horde_Image_Effect_Imagick_LiquidResize
  • Horde_Image_Effect_Imagick_PhotoStack
  • Horde_Image_Effect_Imagick_PolaroidImage
  • Horde_Image_Effect_Imagick_RoundCorners
  • Horde_Image_Effect_Imagick_SmartCrop
  • Horde_Image_Effect_Imagick_TextWatermark
  • Horde_Image_Effect_Imagick_Unsharpmask
  • Horde_Image_Exception
  • Horde_Image_Exif
  • Horde_Image_Exif_Base
  • Horde_Image_Exif_Bundled
  • Horde_Image_Exif_Exiftool
  • Horde_Image_Exif_Parser_Base
  • Horde_Image_Exif_Php
  • Horde_Image_Gd
  • Horde_Image_Im
  • Horde_Image_Imagick
  • Horde_Image_Png
  • Horde_Image_Svg
  • Horde_Image_Swf
  • Horde_Image_Translation
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * General class for fetching and parsing EXIF information from images.
  4:  *
  5:  * Works equally well with either the built in php exif functions (if PHP
  6:  * compiled with exif support), the Exiftool package (more complete but slower),
  7:  * or the bundled exif library.
  8:  *
  9:  * Copyright 2003-2012 Horde LLC (http://www.horde.org/)
 10:  *
 11:  * @author Michael J. Rubinsky <mrubinsk@horde.org>
 12:  * @author Chuck Hagenbuch <chuck@horde.org>
 13:  * @category Horde
 14:  * @package Image
 15:  */
 16: class Horde_Image_Exif
 17: {
 18:     /**
 19:      * Factory method for instantiating a Horde_Image_Exif object.
 20:      *
 21:      * @param string $driver
 22:      * @param array $params
 23:      *
 24:      * @return Horde_Image_Exif
 25:      */
 26:     static public function factory($driver = null, $params = array())
 27:     {
 28:         if (empty($driver) && function_exists('exif_read_data')) {
 29:             $driver = 'Php';
 30:         } elseif (empty($driver)) {
 31:             $driver = 'Bundled';
 32:         } else {
 33:             $driver = basename($driver);
 34:         }
 35: 
 36:         $class = 'Horde_Image_Exif_' . $driver;
 37: 
 38:         return new $class($params);
 39:     }
 40: 
 41:     /**
 42:      * Converts from Intel to Motorola endien.  Just reverses the bytes
 43:      * (assumes hex is passed in)
 44:      *
 45:      * @param $intel
 46:      *
 47:      * @return
 48:      */
 49:     static public function intel2Moto($intel)
 50:     {
 51:         $len  = strlen($intel);
 52:         $moto = '';
 53:         for($i = 0; $i <= $len; $i += 2) {
 54:             $moto .= substr($intel, $len-$i, 2);
 55:         }
 56: 
 57:         return $moto;
 58:     }
 59: 
 60:     /**
 61:      * Obtain an array of supported meta data fields.
 62:      *
 63:      * @TODO: This should probably be extended by the subclass?
 64:      *
 65:      * @return array
 66:      */
 67:     static public function getCategories()
 68:     {
 69:         return array(
 70:             'IPTC' => array(
 71:                 'Keywords' => array('description' => Horde_Image_Translation::t("Image keywords"), 'type' => 'array'),
 72:                 'ObjectName' => array('description' => Horde_Image_Translation::t("Image Title"), 'type' => 'text'),
 73:                 'By-line' => array('description' => Horde_Image_Translation::t("By"), 'type' => 'text'),
 74:                 'CopyrightNotice' => array('description' => Horde_Image_Translation::t("Copyright"), 'type' => 'text'),
 75:                 'Caption-Abstract' => array('description' => Horde_Image_Translation::t("Caption"), 'type' => 'text'),
 76:             ),
 77: 
 78:             'XMP' => array(
 79:                 'Creator' => array('description' => Horde_Image_Translation::t("Image Creator"), 'type' => 'text'),
 80:                 'Rights' => array('description' => Horde_Image_Translation::t("Rights"), 'type' => 'text'),
 81:                 'UsageTerms' => array('description' => Horde_Image_Translation::t("Usage Terms"), 'type' => 'type'),
 82:             ),
 83: 
 84:             'EXIF' => array(
 85:                 'DateTime' => array('description' => Horde_Image_Translation::t("Date Photo Modified"), 'type' => 'date'),
 86:                 'DateTimeOriginal' => array('description' => Horde_Image_Translation::t("Date Photo Taken"), 'type' => 'date'),
 87:                 'DateTimeDigitized' => array('description' => Horde_Image_Translation::t("Date Photo Digitized"), 'type' => 'date'),
 88:                 'GPSLatitude' => array('description' => Horde_Image_Translation::t("Latitude"), 'type' => 'gps'),
 89:                 'GPSLongitude' => array('description' => Horde_Image_Translation::t("Longitude"), 'type' => 'gps'),
 90:                 'Make' => array('description' => Horde_Image_Translation::t("Camera Make"), 'type' => 'text'),
 91:                 'Model' => array('description' => Horde_Image_Translation::t("Camera Model"), 'type' => 'text'),
 92:                 'Software' => array('description' => Horde_Image_Translation::t("Software Version"), 'type' => 'text'),
 93:                 'ImageType' => array('description' => Horde_Image_Translation::t("Photo Type"), 'type' => 'text'),
 94:                 'ImageDescription' => array('description' => Horde_Image_Translation::t("Photo Description"), 'type' => 'text'),
 95:                 'FileSize' => array('description' => Horde_Image_Translation::t("File Size"), 'type' => 'number'),
 96:                 'ExifImageWidth' => array('description' => Horde_Image_Translation::t("Width"), 'type' => 'number'),
 97:                 'ExifImageLength' => array('description' => Horde_Image_Translation::t("Height"), 'type' => 'number'),
 98:                 'XResolution' => array('description' => Horde_Image_Translation::t("X Resolution"), 'type' => 'number'),
 99:                 'YResolution' => array('description' => Horde_Image_Translation::t("Y Resolution"), 'type' => 'number'),
100:                 'ResolutionUnit' => array('description' => Horde_Image_Translation::t("Resolution Unit"), 'type' => 'text'),
101:                 'ShutterSpeedValue' => array('description' => Horde_Image_Translation::t("Shutter Speed"), 'type' => 'number'),
102:                 'ExposureTime' => array('description' => Horde_Image_Translation::t("Exposure"), 'type' => 'number'),
103:                 'FocalLength' => array('description' => Horde_Image_Translation::t("Focal Length"), 'type' => 'number'),
104:                 'FocalLengthIn35mmFilm' => array('description' => Horde_Image_Translation::t("Focal Length (35mm equiv)"), 'type' => 'number'),
105:                 'ApertureValue' => array('description' => Horde_Image_Translation::t("Aperture"), 'type' => 'number'),
106:                 'FNumber' => array('description' => Horde_Image_Translation::t("F-Number"), 'type' => 'number'),
107:                 'ISOSpeedRatings' => array('description' => Horde_Image_Translation::t("ISO Setting"), 'type' => 'number'),
108:                 'ExposureBiasValue' => array('description' => Horde_Image_Translation::t("Exposure Bias"), 'type' => 'number'),
109:                 'ExposureMode' => array('description' => Horde_Image_Translation::t("Exposure Mode"), 'type' => 'number'),
110:                 'ExposureProgram' => array('description' => Horde_Image_Translation::t("Exposure Program"), 'type' => 'number'),
111:                 'MeteringMode' => array('description' => Horde_Image_Translation::t("Metering Mode"), 'type' => 'number'),
112:                 'Flash' => array('description' => Horde_Image_Translation::t("Flash Setting"), 'type' => 'number'),
113:                 'UserComment' => array('description' => Horde_Image_Translation::t("User Comment"), 'type' => 'text'),
114:                 'ColorSpace' => array('description' => Horde_Image_Translation::t("Color Space"), 'type' => 'number'),
115:                 'SensingMethod' => array('description' => Horde_Image_Translation::t("Sensing Method"), 'type' => 'number'),
116:                 'WhiteBalance' => array('description' => Horde_Image_Translation::t("White Balance"), 'type' => 'number'),
117:                 'Orientation' => array('description' => Horde_Image_Translation::t("Camera Orientation"), 'type' => 'number'),
118:                 'Copyright' => array('description' => Horde_Image_Translation::t("Copyright"), 'type' => 'text'),
119:                 'Artist' => array('description' => Horde_Image_Translation::t("Artist"), 'type' => 'text'),
120:                 'LightSource' => array('description' => Horde_Image_Translation::t("Light source"), 'type' => 'number'),
121:                 'ImageStabalization' => array('description' => Horde_Image_Translation::t("Image Stabilization"), 'type' => 'text'),
122:                 'SceneCaptureType' => array('description' => Horde_Image_Translation::t("Scene Type"), 'type' => 'number'),
123:             ),
124: 
125:             'COMPOSITE' => array(
126:                 'LensID' => array('description' => Horde_Image_Translation::t("Lens Id"), 'type' => 'text'),
127:                 'Lens' => array('description' => 'Lens', 'type' => 'text'),
128:                 'Aperture' => array('description' => Horde_Image_Translation::t("Aperture"), 'type' => 'text'),
129:                 'DOF' => array('description' => Horde_Image_Translation::t("Depth of Field"), 'type' => 'text'),
130:                 'FOV' => array('description' => Horde_Image_Translation::t("Field of View"), 'type' => 'text')
131:             )
132:         );
133:     }
134: 
135:     /**
136:      * Return a flattened array of supported metadata fields.
137:      *
138:      * @param $driver
139:      * @return unknown_type
140:      */
141:     static public function getFields($driver = null, $description_only = false)
142:     {
143:         if (!is_null($driver) && is_array($driver)) {
144:             $driver = self::factory($driver[0], $driver[1]);
145:         }
146: 
147:         if ($driver instanceof Horde_Image_Exif_Base) {
148:             $supported = $driver->supportedCategories();
149:         } else {
150:             $supported = array('XMP', 'IPTC', 'EXIF'    );
151:         }
152:         $categories = self::getCategories();
153:         $flattened = array();
154:         foreach ($supported as $category) {
155:             $flattened = array_merge($flattened, $categories[$category]);
156:         }
157: 
158:         if ($description_only) {
159:             foreach ($flattened as $key => $data) {
160:                 $return[$key] = $data['description'];
161:             }
162:             return $return;
163:         }
164: 
165:         return $flattened;
166:     }
167: 
168:     /**
169:      * More human friendly exposure formatting.
170:      */
171:     static protected function _formatExposure($data)
172:     {
173:         if ($data > 0) {
174:             if ($data > 1) {
175:                 return sprintf(Horde_Image_Translation::t("%d sec"), round($data, 2));
176:             } else {
177:                 $n = $d = 0;
178:                 self::_convertToFraction($data, $n, $d);
179:                 if ($n <> 1) {
180:                     return sprintf(Horde_Image_Translation::t("%4f sec"), $n / $d);
181:                 }
182:                 return sprintf(Horde_Image_Translation::t("%s / %s sec"), $n, $d);
183:             }
184:         } else {
185:             return Horde_Image_Translation::t("Bulb");
186:         }
187:     }
188: 
189:     /**
190:      * Converts a floating point number into a fraction.
191:      * Many thanks to Matthieu Froment for this code.
192:      *
193:      * (Ported from the Exifer library).
194:      */
195:     static protected function _convertToFraction($v, &$n, &$d)
196:     {
197:         $MaxTerms = 15;         // Limit to prevent infinite loop
198:         $MinDivisor = 0.000001; // Limit to prevent divide by zero
199:         $MaxError = 0.00000001; // How close is enough
200: 
201:         // Initialize fraction being converted
202:         $f = $v;
203: 
204:         // Initialize fractions with 1/0, 0/1
205:         $n_un = 1;
206:         $d_un = 0;
207:         $n_deux = 0;
208:         $d_deux = 1;
209: 
210:         for ($i = 0; $i < $MaxTerms; $i++) {
211:             $a = floor($f); // Get next term
212:             $f = $f - $a; // Get new divisor
213:             $n = $n_un * $a + $n_deux; // Calculate new fraction
214:             $d = $d_un * $a + $d_deux;
215:             $n_deux = $n_un; // Save last two fractions
216:             $d_deux = $d_un;
217:             $n_un = $n;
218:             $d_un = $d;
219: 
220:             // Quit if dividing by zero
221:             if ($f < $MinDivisor) {
222:                 break;
223:             }
224:             if (abs($v - $n / $d) < $MaxError) {
225:                 break;
226:             }
227: 
228:             // reciprocal
229:             $f = 1 / $f;
230:         }
231:     }
232: 
233:     /**
234:      * Convert an exif field into human-readable form.
235:      * Some of these cases are ported from the Exifer library, others were
236:      * changed from their implementation where the EXIF standard dictated
237:      * different behaviour.
238:      *
239:      * @param string $field  The name of the field to translate.
240:      * @param string $data   The data value to translate.
241:      *
242:      * @return string  The converted data.
243:      */
244:     static public function getHumanReadable($field, $data)
245:     {
246:         switch ($field) {
247:         case 'ExposureMode':
248:             switch ($data) {
249:             case 0: return Horde_Image_Translation::t("Auto exposure");
250:             case 1: return Horde_Image_Translation::t("Manual exposure");
251:             case 2: return Horde_Image_Translation::t("Auto bracket");
252:             default: return Horde_Image_Translation::t("Unknown");
253:             }
254: 
255:         case 'ExposureProgram':
256:             switch ($data) {
257:             case 1: return Horde_Image_Translation::t("Manual");
258:             case 2: return Horde_Image_Translation::t("Normal Program");
259:             case 3: return Horde_Image_Translation::t("Aperture Priority");
260:             case 4: return Horde_Image_Translation::t("Shutter Priority");
261:             case 5: return Horde_Image_Translation::t("Creative");
262:             case 6: return Horde_Image_Translation::t("Action");
263:             case 7: return Horde_Image_Translation::t("Portrait");
264:             case 8: return Horde_Image_Translation::t("Landscape");
265:             default: return Horde_Image_Translation::t("Unknown");
266:             }
267: 
268:         case 'XResolution':
269:         case 'YResolution':
270:             if (strpos($data, '/') !== false) {
271:                 list($n, $d) = explode('/', $data, 2);
272:                 return sprintf(Horde_Image_Translation::t("%d dots per unit"), $n);
273:             }
274:             return sprintf(Horde_Image_Translation::t("%d per unit"), $data);
275: 
276:         case 'ResolutionUnit':
277:             switch ($data) {
278:             case 1: return Horde_Image_Translation::t("Pixels");
279:             case 2: return Horde_Image_Translation::t("Inch");
280:             case 3: return Horde_Image_Translation::t("Centimeter");
281:             default: return Horde_Image_Translation::t("Unknown");
282:             }
283: 
284:         case 'ExifImageWidth':
285:         case 'ExifImageLength':
286:             return sprintf(Horde_Image_Translation::t("%d pixels"), $data);
287: 
288:         case 'Orientation':
289:             switch ($data) {
290:             case 1:
291:                 return sprintf(Horde_Image_Translation::t("Normal (O deg)"));
292:             case 2:
293:                 return sprintf(Horde_Image_Translation::t("Mirrored"));
294:             case 3:
295:                 return sprintf(Horde_Image_Translation::t("Upsidedown"));
296:             case 4:
297:                 return sprintf(Horde_Image_Translation::t("Upsidedown Mirrored"));
298:             case 5:
299:                 return sprintf(Horde_Image_Translation::t("90 deg CW Mirrored"));
300:             case 6:
301:                 return sprintf(Horde_Image_Translation::t("90 deg CCW"));
302:             case 7:
303:                 return sprintf(Horde_Image_Translation::t("90 deg CCW Mirrored"));
304:             case 8:
305:                 return sprintf(Horde_Image_Translation::t("90 deg CW"));
306:             }
307:             break;
308: 
309:         case 'ExposureTime':
310:             if (strpos($data, '/') !== false) {
311:                 list($n, $d) = explode('/', $data, 2);
312:                 if ($d == 0) {
313:                     return;
314:                 }
315:                 $data = $n / $d;
316:             }
317:             return self::_formatExposure($data);
318: 
319:         case 'ShutterSpeedValue':
320:             if (strpos($data, '/') !== false) {
321:                 list($n, $d) = explode('/', $data, 2);
322:                 if ($d == 0) {
323:                     return;
324:                 }
325:                 $data = $n / $d;
326:             }
327:             $data = exp($data * log(2));
328:             if ($data > 0) {
329:                 $data = 1 / $data;
330:             }
331:             return self::_formatExposure($data);
332: 
333:         case 'ApertureValue':
334:         case 'MaxApertureValue':
335:             if (strpos($data, '/') !== false) {
336:                 list($n, $d) = explode('/', $data, 2);
337:                 if ($d == 0) {
338:                     return;
339:                 }
340:                 $data = $n / $d;
341:                 $data = exp(($data * log(2)) / 2);
342: 
343:                 // Precision is 1 digit.
344:                 $data = round($data, 1);
345:             }
346:             return 'f/' . $data;
347: 
348:         case 'FocalLength':
349:             if (strpos($data, '/') !== false) {
350:                 list($n, $d) = explode('/', $data, 2);
351:                 if ($d == 0) {
352:                     return;
353:                 }
354:                 return sprintf(Horde_Image_Translation::t("%d mm"), round($n / $d));
355:             }
356:             return sprintf(Horde_Image_Translation::t("%d mm"), $data);
357: 
358:         case 'FNumber':
359:             if (strpos($data, '/') !== false) {
360:                 list($n, $d) = explode('/', $data, 2);
361:                 if ($d != 0) {
362:                     return 'f/' . round($n / $d, 1);
363:                 }
364:             }
365:             return 'f/' . $data;
366: 
367:         case 'ExposureBiasValue':
368:             if (strpos($data, '/') !== false) {
369:                 list($n, $d) = explode('/', $data, 2);
370:                 if ($n == 0) {
371:                     return '0 EV';
372:                 }
373:             }
374:             return $data . ' EV';
375: 
376:         case 'MeteringMode':
377:             switch ($data) {
378:             case 0: return Horde_Image_Translation::t("Unknown");
379:             case 1: return Horde_Image_Translation::t("Average");
380:             case 2: return Horde_Image_Translation::t("Center Weighted Average");
381:             case 3: return Horde_Image_Translation::t("Spot");
382:             case 4: return Horde_Image_Translation::t("Multi-Spot");
383:             case 5: return Horde_Image_Translation::t("Multi-Segment");
384:             case 6: return Horde_Image_Translation::t("Partial");
385:             case 255: return Horde_Image_Translation::t("Other");
386:             default: return sprintf(Horde_Image_Translation::t("Unknown: %s"), $data);
387:             }
388:             break;
389: 
390:         case 'LightSource':
391:             switch ($data) {;
392:             case 1: return Horde_Image_Translation::t("Daylight");
393:             case 2: return Horde_Image_Translation::t("Fluorescent");
394:             case 3: return Horde_Image_Translation::t("Tungsten");
395:             case 4: return Horde_Image_Translation::t("Flash");
396:             case 9: return Horde_Image_Translation::t("Fine weather");
397:             case 10: return Horde_Image_Translation::t("Cloudy weather");
398:             case 11: return Horde_Image_Translation::t("Shade");
399:             case 12: return Horde_Image_Translation::t("Daylight fluorescent");
400:             case 13: return Horde_Image_Translation::t("Day white fluorescent");
401:             case 14: return Horde_Image_Translation::t("Cool white fluorescent");
402:             case 15: return Horde_Image_Translation::t("White fluorescent");
403:             case 17: return Horde_Image_Translation::t("Standard light A");
404:             case 18: return Horde_Image_Translation::t("Standard light B");
405:             case 19: return Horde_Image_Translation::t("Standard light C");
406:             case 20: return 'D55';
407:             case 21: return 'D65';
408:             case 22: return 'D75';
409:             case 23: return 'D50';
410:             case 24: return Horde_Image_Translation::t("ISO studio tungsten");
411:             case 255: return Horde_Image_Translation::t("other light source");
412:             default: return Horde_Image_Translation::t("Unknown");
413:             }
414: 
415:         case 'WhiteBalance':
416:             switch ($data) {
417:             case 0: return Horde_Image_Translation::t("Auto");
418:             case 1: return Horde_Image_Translation::t("Manual");
419:             default: Horde_Image_Translation::t("Unknown");
420:             }
421:             break;
422: 
423:         case 'FocalLengthIn35mmFilm':
424:             return $data . ' mm';
425: 
426:         case 'Flash':
427:             switch ($data) {
428:             case 0: return Horde_Image_Translation::t("No Flash");
429:             case 1: return Horde_Image_Translation::t("Flash");
430:             case 5: return Horde_Image_Translation::t("Flash, strobe return light not detected");
431:             case 7: return Horde_Image_Translation::t("Flash, strobe return light detected");
432:             case 9: return Horde_Image_Translation::t("Compulsory Flash");
433:             case 13: return Horde_Image_Translation::t("Compulsory Flash, Return light not detected");
434:             case 15: return Horde_Image_Translation::t("Compulsory Flash, Return light detected");
435:             case 16: return Horde_Image_Translation::t("No Flash");
436:             case 24: return Horde_Image_Translation::t("No Flash");
437:             case 25: return Horde_Image_Translation::t("Flash, Auto-Mode");
438:             case 29: return Horde_Image_Translation::t("Flash, Auto-Mode, Return light not detected");
439:             case 31: return Horde_Image_Translation::t("Flash, Auto-Mode, Return light detected");
440:             case 32: return Horde_Image_Translation::t("No Flash");
441:             case 65: return Horde_Image_Translation::t("Red Eye");
442:             case 69: return Horde_Image_Translation::t("Red Eye, Return light not detected");
443:             case 71: return Horde_Image_Translation::t("Red Eye, Return light detected");
444:             case 73: return Horde_Image_Translation::t("Red Eye, Compulsory Flash");
445:             case 77: return Horde_Image_Translation::t("Red Eye, Compulsory Flash, Return light not detected");
446:             case 79: return Horde_Image_Translation::t("Red Eye, Compulsory Flash, Return light detected");
447:             case 89: return Horde_Image_Translation::t("Red Eye, Auto-Mode");
448:             case 93: return Horde_Image_Translation::t("Red Eye, Auto-Mode, Return light not detected");
449:             case 95: return Horde_Image_Translation::t("Red Eye, Auto-Mode, Return light detected");
450:             }
451:             break;
452: 
453:         case 'FileSize':
454:            if ($data <= 0) {
455:               return '0 Bytes';
456:            }
457:            $s = array('B', 'kB', 'MB', 'GB');
458:            $e = floor(log($data, 1024));
459:            return round($data/pow(1024, $e), 2) . ' ' . $s[$e];
460: 
461:         case 'SensingMethod':
462:             switch ($data) {
463:             case 1: return Horde_Image_Translation::t("Not defined");
464:             case 2: return Horde_Image_Translation::t("One Chip Color Area Sensor");
465:             case 3: return Horde_Image_Translation::t("Two Chip Color Area Sensor");
466:             case 4: return Horde_Image_Translation::t("Three Chip Color Area Sensor");
467:             case 5: return Horde_Image_Translation::t("Color Sequential Area Sensor");
468:             case 7: return Horde_Image_Translation::t("Trilinear Sensor");
469:             case 8: return Horde_Image_Translation::t("Color Sequential Linear Sensor");
470:             default: return Horde_Image_Translation::t("Unknown");
471:             }
472: 
473:         case 'ColorSpace':
474:             switch ($data) {
475:             case 1: return Horde_Image_Translation::t("sRGB");
476:             default: return Horde_Image_Translation::t("Uncalibrated");
477:             }
478: 
479:         case 'SceneCaptureType':
480:             switch ($data) {
481:             case 0: return Horde_Image_Translation::t("Standard");
482:             case 1: return Horde_Image_Translation::t("Landscape");
483:             case 2: return Horde_Image_Translation::t("Portrait");
484:             case 3: return Horde_Image_Translation::t("Night Scene");
485:             default: return Horde_Image_Translation::t("Unknown");
486:             }
487: 
488:         case 'DateTime':
489:         case 'DateTimeOriginal':
490:         case 'DateTimeDigitized':
491:             return date('m/d/Y H:i:s O', $data);
492: 
493:         case 'UserComment':
494:             //@TODO: the first 8 bytes of this field contain the charset used
495:             //       to encode the comment. Either ASCII, JIS, UNICODE, or
496:             //       UNDEFINED. Should probably either convert to a known charset
497:             //       here and let the calling code deal with it, or allow this
498:             //       method to take an optional charset to convert to (would
499:             //       introduce a dependency on Horde_String to do the conversion).
500:             $data = trim(substr($data, 7))  ;
501: 
502: 
503:         default:
504:             return !empty($data) ? $data : '---';
505:         }
506:     }
507: 
508: }
509: 
API documentation generated by ApiGen