source: extensions/AMetaData/JpegMetaData/Readers/NikonReader.class.php

Last change on this file was 17554, checked in by grum, 12 years ago

feature:2701
bug:2702
bug:2720
bug:2722

  • Property svn:executable set to *
File size: 21.0 KB
Line 
1<?php
2/*
3 * --:: JPEG MetaDatas ::-------------------------------------------------------
4 *
5 *  Author    : Grum
6 *   email    : grum at piwigo.org
7 *   website  : http://photos.grum.fr
8 *
9 *   << May the Little SpaceFrog be with you ! >>
10 *
11 *
12 * +-----------------------------------------------------------------------+
13 * | JpegMetaData - a PHP based Jpeg Metadata manager                      |
14 * +-----------------------------------------------------------------------+
15 * | Copyright(C) 2010  Grum - http://www.grum.fr                          |
16 * +-----------------------------------------------------------------------+
17 * | This program is free software; you can redistribute it and/or modify  |
18 * | it under the terms of the GNU General Public License as published by  |
19 * | the Free Software Foundation                                          |
20 * |                                                                       |
21 * | This program is distributed in the hope that it will be useful, but   |
22 * | WITHOUT ANY WARRANTY; without even the implied warranty of            |
23 * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
24 * | General Public License for more details.                              |
25 * |                                                                       |
26 * | You should have received a copy of the GNU General Public License     |
27 * | along with this program; if not, write to the Free Software           |
28 * | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
29 * | USA.                                                                  |
30 * +-----------------------------------------------------------------------+
31 *
32 *
33 * -----------------------------------------------------------------------------
34 *
35 * The NikonReader class is the dedicated to read the specific Nikon tags
36 *
37 * ====> See MakerNotesReader.class.php to know more about the structure <======
38 *
39 * -----------------------------------------------------------------------------
40 *
41 * .. Notes ..
42 *
43 *
44 * ****             All known tags are not implemented !!                   ****
45 *
46 *
47 * The NikonReader class is derived from the MakerNotesReader class.
48 *
49 * =====> See MakerNotesReader.class.php to know more about common methods <====
50 *
51 * -----------------------------------------------------------------------------
52 */
53
54
55
56  require_once(JPEG_METADATA_DIR."TagDefinitions/NikonTags.class.php");
57  require_once(JPEG_METADATA_DIR."Readers/MakerNotesReader.class.php");
58
59  class NikonReader extends MakerNotesReader
60  {
61    protected $schema = Schemas::EXIF;
62
63    /* these 2 specific metadata are used to decrypt some information, like the
64     * data lens
65     */
66    protected $serialNumber="";
67    protected $shutterCount=-1;
68
69    protected $toDecode=Array();
70
71    /**
72     * The constructor needs, like the ancestor, the datas to be parsed
73     *
74     * Some datas are offset on extra data, and this offset can be (some time)
75     * absolute inside the IFD, or relative. So, the offset of the IFD structure
76     * is needed
77     *
78     * The byte order can be different from the TIFF byte order !
79     *
80     * The constructor need the maker signature (see the MakerNotesSignatures
81     * class for a list of known signatures)
82     *
83     * @param String $data
84     * @param ULong $offset : offset of IFD block in the jpeg file
85     * @param String $byteOrder
86     * @param String $makerSignature :
87     */
88    function __construct($data, $offset, $byteOrder, $makerSignature)
89    {
90      $this->maker = MAKER_NIKON;
91      switch($makerSignature)
92      {
93        case MakerNotesSignatures::Nikon2Header:
94          $this->header = MakerNotesSignatures::Nikon2Header;
95          $this->headerSize = MakerNotesSignatures::Nikon2HeaderSize;
96          break;
97        case MakerNotesSignatures::Nikon3Header:
98          $this->header = MakerNotesSignatures::Nikon3Header;
99          $this->headerSize = MakerNotesSignatures::Nikon3HeaderSize;
100          break;
101      }
102
103      // offset inside Nikon maker note are relative
104      $offset=-10;
105
106      parent::__construct($data, $offset, $byteOrder);
107
108      $this->processEncryptedTags();
109    }
110
111    function __destruct()
112    {
113      parent::__destruct();
114    }
115
116    /**
117     * initialize the definition for Pentax exif tags
118     */
119    protected function initializeTagDef()
120    {
121      $this->tagDef = new NikonTags();
122    }
123
124    /**
125     * skip the IFD header
126     */
127    protected function skipHeader($headerSize=0)
128    {
129      parent::skipHeader($headerSize);
130      if($this->header == MakerNotesSignatures::Nikon3Header)
131      {
132        /*
133         * the nikon3header is made of 7 char, and then 3 next char ?????
134         */
135        $header=$this->data->readASCII(3);
136
137
138        $header=$this->data->readASCII(2);
139        /*
140         * The Nikon3Header is formatted as a TIFF header, but the class is not
141         * derived from TiffReader, because we can think there is no more than
142         * one IFD in the maker notes.
143         * By this way, it's easier to skip the header and start reading the
144         * entries.
145         *
146         * begins wih "II" or "MM" (indicate the byte order)
147         * next value is an USHORT, must equals 0x2a
148         *
149         * all data have to be read with the byte order defined in header
150         */
151        if($header=="II" or $header="MM")
152        {
153          $this->byteOrder=$header;
154          $this->data->setByteOrder($this->byteOrder);
155
156          $header=$this->data->readUShort();
157          if($header==0x002a)
158          {
159            $this->isValid=true;
160            $header=$this->data->readULong();
161          }
162        }
163      }
164    }
165
166    /**
167     * encrypted values are processed in one shot when all the tags are processed
168     * with this method, we are sure the "SerialNumber" (0x001d) and the
169     * "ShutterCount" (0x00a7) tags are initialized
170     */
171    protected function processEncryptedTags()
172    {
173      foreach($this->toDecode as $key=>$val)
174      {
175        $tagIndex=$this->getTagIndexById($key);
176        if($tagIndex>-1)
177        {
178          $this->entries[$tagIndex]->getTag()->setLabel($this->processSpecialTag($key, $val[0], $val[1]));
179          //echo sprintf("%04x * %s => %s<br>",$key,ConvertData::toHexDump($val[0], ByteType::ASCII),$this->processSpecialTag($key, $val[0], $val[1]));
180        }
181      }
182    }
183
184    /**
185     * this function do the interpretation of specials tags
186     *
187     * the function return the interpreted value for the tag
188     *
189     * @param $tagId             : the id of the tag
190     * @param $values            : 'raw' value to be interpreted
191     * @param UByte $type        : if needed (for IFD structure) the type of data
192     * @param ULong $valueOffset : if needed, the offset of data in the jpeg file
193     * @return String or Array or DateTime or Integer or Float...
194     */
195    protected function processSpecialTag($tagId, $values, $type, $valuesOffset=0)
196    {
197      switch($tagId)
198      {
199        case 0x0001: // "MakerNoteVersion"
200          // 0x30323030 => String "0200" => 2.00
201          $major=substr($values,0,2);
202          if(substr($values,0,1)=="0")
203          {
204            $major=substr($values,1,1);
205          }
206          else
207          {
208            $major=substr($values,0,2);
209          }
210          $minor=substr($values,2);
211          $returned=sprintf("%s.%s", $major, $minor);
212          break;
213        case 0x001d: // "SerialNumber"
214          $returned=ConvertData::toStrings($values);
215          $this->serialNumber=$returned;
216          break;
217        case 0x0003: // "ColorMode"
218        case 0x0004: // "Quality"
219        case 0x0005: // "WhiteBalance"
220        case 0x0006: // "Sharpness"
221        case 0x0007: // "FocusMode"
222        case 0x0008: // "FlashSetting"
223        case 0x0009: // "FlashType"
224        case 0x000f: // "ISOSelection"
225        case 0x0080: // "ImageAdjustment"
226        case 0x0081: // "ToneComp"
227        case 0x0082: // "AuxiliaryLens"
228        case 0x008D: // "ColorHue"
229        case 0x008f: // "SceneMode"
230        case 0x0090: // "LightSource"
231        case 0x0095: // "NoiseReduction"
232        case 0x009c: // "SceneAssist"
233        case 0x00a0: // "SerialNumber"
234        case 0x00a9: // "ImageOptimization"
235        case 0x00aa: // "Saturation"
236        case 0x00ab: // "VariProgram"
237        case 0x0e09: // "NikonCaptureVersion"
238          /*
239           * null terminated strings
240           */
241          $returned=ConvertData::toStrings($values);
242          break;
243        case 0x092: // "HueAdjustment"
244        case 0x00a2: // "ImageDataSize"
245          $returned=$values;
246          break;
247        case 0x0a7: // "ShutterCount"
248          $this->shutterCount=$values;
249          $returned=$values;
250          break;
251        case 0x001f: // "VRInfo"
252          $returned=(ord($values{4})==1)?"On":"Off";
253          break;
254        case 0x0083: // "LensType"
255          $tag=$this->tagDef->getTagById(0x0083);
256
257          $returned=Array();
258          if(($values & 0x0001) == 0x0001)
259            $returned[]=$tag['tagValues.specialValues'][0x0001];
260
261          if(($values & 0x0002) == 0x0002)
262            $returned[]=$tag['tagValues.specialValues'][0x0002];
263
264          if(($values & 0x0004) == 0x0004)
265            $returned[]=$tag['tagValues.specialValues'][0x0004];
266
267          if(($values & 0x0008) == 0x0008)
268            $returned[]=$tag['tagValues.specialValues'][0x0008];
269          unset($tag);
270          break;
271        case 0x0084: // "Lens"
272          /* array of 4 rationnal
273           * - short focal
274           * - long focal
275           * - aperture at short focal
276           * - aperture at long focal
277           *
278           * ==> 18-70mm f/3.5-4.5
279           */
280          $result=array();
281          foreach($values as $val)
282          {
283            if($val[1]==0) $val[1]==1;
284            $result[]=$val[0]/$val[1];
285          }
286
287          if($result[0]!=$result[1])
288          {
289            $returned=sprintf("%.0f-%.0fmm ", $result[0], $result[1]);
290          }
291          else
292          {
293            $returned=sprintf("%.0fmm ", $result[0]);
294          }
295
296          if($result[2]!=$result[3])
297          {
298            $returned.=sprintf("f/%.1f-%.1f", $result[2], $result[3]);
299          }
300          else
301          {
302            $returned.=sprintf("f/%.1f", $result[2]);
303          }
304          break;
305        case 0x0086: // "DigitalZoom"
306          if($values[1]==0) $values[1]=1;
307          $returned=sprintf("x%.1f", $values[0]/$values[1]);
308          break;
309        case 0x0088: // "AFInfo"
310          /* - shortInt : AFAreaMode
311           * - shortInt : AFPoint
312           * - longInt  : AFPointsInFocus
313           */
314          $tag=$this->tagDef->getTagById(0x0088);
315
316          $values.="\0\0\0\0";
317
318          $returned=Array();
319
320          $tmp=ord($values{0});
321          $returned['AFAreaMode'] = $tag['tagValues.specialValues'][0][$tmp];
322
323          $tmp=ord($values{1});
324          $returned['AFPoint'] = $tag['tagValues.specialValues'][1][$tmp];
325
326          if($values=="\x00\x07\xff\xff")
327          {
328            $returned['AFPointsInFocus'] = $tag['tagValues.specialValues'][2][$values];
329          }
330          else
331          {
332            $tmp=ord($values{2}) * 256 + ord($values{3});
333            $returned['AFPointsInFocus']=Array();
334            foreach($tag['tagValues.specialValues'][2] as $key => $val)
335            {
336              if(($tmp & $key) == $key)
337                $returned['AFPointsInFocus'][]=$val;
338            }
339          }
340          unset($tag);
341          break;
342        case 0x0089: // "ShootingMode"
343          $returned=Array();
344          $tag=$this->tagDef->getTagById(0x0089);
345
346          if(!($values & 0x87))
347          {
348            $returned[]=$tag['tagValues.specialValues'][0x00];
349          }
350
351          if(preg_match("/.*d70.*/i",GlobalTags::getExifMaker()))
352          {
353            $bit5=1;
354          }
355          else
356          {
357            $bit5=0;
358          }
359
360          if($values)
361          {
362            foreach($tag['tagValues.specialValues'] as $key => $val)
363            {
364              if((($values & $key) == $key) && ($key!=0x00))
365              {
366                if($key==0x20)
367                {
368                  $returned[]=$val[$bit5];
369                }
370                else
371                {
372                  $returned[]=$val;
373                }
374              }
375            }
376          }
377          unset($tag);
378          break;
379        case 0x0098: // "LensData"
380          if(($this->shutterCount==-1 or $this->serialNumber=="") and
381            ( substr($values,0,2)=="02" ))
382          {
383            $this->toDecode[0x0098]=Array($values, $type);
384          }
385          $returned=$this->readLensData($values);
386          break;
387        case 0x0099: // "RawImageCenter"
388          $returned=Array(
389            'x' => $values[0],
390            'y' => $values[1],
391          );
392          break;
393        case 0x009a: // "SensorPixelSize"
394          if($values[0][1]==0) $values[0][1]=1;
395          if($values[1][1]==0) $values[1][1]=1;
396
397          $returned=sprintf("%.1f x %.1f µm", ($values[0][0]/$values[0][1]), ($values[1][0]/$values[1][1]));
398          break;
399        default:
400          $returned="Not yet implemented;".ConvertData::toHexDump($tagId, ByteType::USHORT)." => ".ConvertData::toHexDump($values, $type);
401          break;
402      }
403      return($returned);
404    }
405
406    /**
407     * this function is used to decrypt datas from the Nikon "LensData" tag
408     *
409     * @param String $data : data from the exif.Nikon.LensData metadata
410     * @return Array : list of properties + lens name (computed)
411     */
412    private function readLensData($data)
413    {
414      $returned="";
415      $nfo=Array();
416      $dataReader=new Data($data, $this->byteOrder);
417
418      $nfo['LensDataVersion']=$dataReader->readASCII(4);
419
420      if(substr($nfo['LensDataVersion'],0,2)=="02")
421      {
422        // in this case, data are encrypted
423        $decrypted=$nfo['LensDataVersion'].$this->decryptData($this->serialNumberInteger(), $this->shutterCount,$dataReader->readASCII(-1,4));
424        $dataReader->setData($decrypted);
425      }
426
427      switch($nfo['LensDataVersion'])
428      {
429        case '0100' :
430            $nfo['LensIDNumber']=$dataReader->readUByte(6);
431            $nfo['LensFStops']=$dataReader->readUByte(7);
432            $nfo['MinFocalLength']=$dataReader->readUByte(8);
433            $nfo['MaxFocalLength']=$dataReader->readUByte(9);
434            $nfo['MaxApertureAtMinFocal']=$dataReader->readUByte(10);
435            $nfo['MaxApertureAtMaxFocal']=$dataReader->readUByte(11);
436            $nfo['MCUVersion']=$dataReader->readUByte(12);
437          break;
438        case '0101' :
439        case '0201' :
440        case '0202' :
441        case '0203' :
442            $nfo['LensIDNumber']=$dataReader->readUByte(11);
443            $nfo['LensFStops']=$dataReader->readUByte(12);
444            $nfo['MinFocalLength']=$dataReader->readUByte(13);
445            $nfo['MaxFocalLength']=$dataReader->readUByte(14);
446            $nfo['MaxApertureAtMinFocal']=$dataReader->readUByte(15);
447            $nfo['MaxApertureAtMaxFocal']=$dataReader->readUByte(16);
448            $nfo['MCUVersion']=$dataReader->readUByte(17);
449          break;
450        case '0204' :
451            $nfo['LensIDNumber']=$dataReader->readUByte(12);
452            $nfo['LensFStops']=$dataReader->readUByte(13);
453            $nfo['MinFocalLength']=$dataReader->readUByte(14);
454            $nfo['MaxFocalLength']=$dataReader->readUByte(15);
455            $nfo['MaxApertureAtMinFocal']=$dataReader->readUByte(16);
456            $nfo['MaxApertureAtMaxFocal']=$dataReader->readUByte(17);
457            $nfo['MCUVersion']=$dataReader->readUByte(18);
458          break;
459      }
460
461      $keyLens = sprintf("%02X %02X %02X %02X %02X %02X %02X %02X",
462        $nfo['LensIDNumber'],
463        $nfo['LensFStops'],
464        $nfo['MinFocalLength'],
465        $nfo['MaxFocalLength'],
466        $nfo['MaxApertureAtMinFocal'],
467        $nfo['MaxApertureAtMaxFocal'],
468        $nfo['MCUVersion'],
469        $this->getTagById(0x0083)->getValue()
470      );
471
472      $tag=$this->tagDef->getTagById(0x0098);
473      if(array_key_exists($keyLens, $tag['tagValues.lenses']))
474      {
475        $returned = $tag['tagValues.lenses'][$keyLens];
476      }
477      else
478      {
479        $returned = $tag['tagValues.lenses']['unknown']." (".$keyLens." / ".$nfo['LensDataVersion'].")";
480      }
481
482      if(is_array($returned))
483        $returned=$returned[0];
484
485      unset($data);
486      unset($nfo);
487      return($returned);
488    }
489
490    /**
491     * Nikon encrypt some data
492     * This function is used to decrypt them. Don't ask anything about "how does
493     * it work" and "what's it doing", I just translated the C++ & Perl code
494     * from Exiv2, Exiftool & Raw Photo Parser (Copyright 2004-2006 Dave Coffin)
495     *
496     * @param Integer $serialNumber : the camera serial number, in Integer
497     *                                format (from the 0x001d tag, not the 0x00a0)
498     * @param Integer $shutterCount : shutterCount value in the file
499     * @param String $data : data to decrypt
500     * @param Integer $decryptedLength : number of byte to decrypt
501     * @return String : the decrypted data
502     */
503    private function decryptData($serialNumber, $shutterCount, $data, $decryptedLength=0)
504    {
505      $xlat = Array(
506                Array(0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
507                      0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
508                      0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
509                      0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
510                      0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
511                      0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
512                      0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
513                      0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
514                      0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
515                      0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
516                      0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
517                      0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
518                      0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
519                      0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
520                      0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
521                      0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7),
522                Array(0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
523                      0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
524                      0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
525                      0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
526                      0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
527                      0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
528                      0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
529                      0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
530                      0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
531                      0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
532                      0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
533                      0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
534                      0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
535                      0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
536                      0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
537                      0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f)
538              );
539      $returned="";
540
541      if($decryptedLength==0 or $decryptedLength>strlen($data))
542        $decryptedLength=strlen($data);
543
544      $key = 0;
545      for($i=0; $i < 4; $i++)
546      {
547        $key = $key ^ (($shutterCount >> ($i*8)) & 0xff);
548      }
549      $ci = $xlat[0][$serialNumber & 0xff];
550      $cj = $xlat[1][$key];
551      $ck = 0x60;
552
553      for($i=0;$i<$decryptedLength;++$i)
554      {
555        $cj+=$ci*$ck++;
556        $returned.= chr(ord($data{$i}) ^ $cj);
557      }
558      return($returned);
559    }
560
561    /**
562     * return the serialNumber as an integer
563     */
564    private function serialNumberInteger()
565    {
566      if(trim($this->serialNumber)!="")
567      {
568        return(0+$this->serialNumber);
569      }
570      elseif(preg_match("/.*d50.*/i",GlobalTags::getExifMaker()))
571      {
572        //D50
573        return(0x22);
574      }
575      else
576      {
577        //D200, D40X, ...
578        return(0x60);
579      }
580    }
581  }
582
583
584?>
Note: See TracBrowser for help on using the repository browser.