source: extensions/AMetaData/JpegMetaData/Common/ConvertData.class.php @ 4972

Last change on this file since 4972 was 4972, checked in by grum, 14 years ago

Canon camera's maker note implementation + extended Xmp segments managed

  • Property svn:executable set to *
File size: 13.4 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 * | JpegMetaData - a PHP based Jpeg Metadata manager                      |
13 * +-----------------------------------------------------------------------+
14 * | Copyright(C) 2010  Grum - http://www.grum.fr                          |
15 * +-----------------------------------------------------------------------+
16 * | This program is free software; you can redistribute it and/or modify  |
17 * | it under the terms of the GNU General Public License as published by  |
18 * | the Free Software Foundation                                          |
19 * |                                                                       |
20 * | This program is distributed in the hope that it will be useful, but   |
21 * | WITHOUT ANY WARRANTY; without even the implied warranty of            |
22 * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
23 * | General Public License for more details.                              |
24 * |                                                                       |
25 * | You should have received a copy of the GNU General Public License     |
26 * | along with this program; if not, write to the Free Software           |
27 * | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
28 * | USA.                                                                  |
29 * +-----------------------------------------------------------------------+
30 *
31 *
32 * -----------------------------------------------------------------------------
33 *
34 * ConvertData class is used to convert data from a type into another type
35 *
36 * This class provides theses public functions :
37 *  - (static) toUByte
38 *  - (static) toSByte
39 *  - (static) toUShort
40 *  - (static) toSShort
41 *  - (static) toULong
42 *  - (static) toSLong
43 *  - (static) toURational
44 *  - (static) toSRational
45 *  - (static) toExposureTime
46 *  - (static) toFNumber
47 *  - (static) toDateTime
48 *  - (static) toFocalLength
49 *  - (static) toEV
50 *  - (static) toDistance
51 *  - (static) toStrings
52 *  - (static) toDMS
53 *  - (static) toHexDump
54 *
55 * -----------------------------------------------------------------------------
56 */
57
58  require_once(JPEG_METADATA_DIR."Common/Const.class.php");
59
60  class ConvertData
61  {
62    /**
63     * Convert the given data into a single unsigned Byte (8bit)
64     *
65     * @param String $data : representing the unsigned Byte
66     * @return UByte
67     */
68    static public function toUByte($data)
69    {
70      if(strlen($data)>=1)
71        return(ord($data{0}));
72      else
73        return(0);
74    }
75
76    /**
77     * Convert the given data into a single signed Byte (8bit)
78     *
79     * @param String $data : representing the signed Byte
80     * @return SByte
81     */
82    static public function toSByte($data)
83    {
84      $unsigned = self::toUByte($data);
85      if($unsigned>127)
86        return($unsigned-256);
87      else
88        return($unsigned);
89    }
90
91    /**
92     * Convert the given data into an unsigned Short integer (16bit)
93     *
94     * @param String $data       : representing the unsigned Short
95     * @param String $endianType : the byte order
96     * @return UShort
97     */
98    static public function toUShort($data, $endianType)
99    {
100      if(strlen($data)>=2)
101      {
102        if($endianType==BYTE_ORDER_LITTLE_ENDIAN)
103          return(ord($data{0}) +
104                 ord($data{1})*256);
105        else
106          return(ord($data{0})*256 +
107                 ord($data{1}));
108      }
109      else
110      {
111        return(0);
112      }
113    }
114
115    /**
116     * Convert the given data into a signed Short integer (16bit)
117     *
118     * @param String $data       : representing the signed Short
119     * @param String $endianType : the byte order
120     * @return SShort
121     */
122    static public function toSShort($data, $endianType)
123    {
124      $unsigned = self::toUShort($data, $endianType);
125      if($unsigned>32767)
126        return($unsigned-65536);
127      else
128        return($unsigned);
129    }
130
131    /**
132     * Convert the given data into an unsigned Long integer (32bit)
133     *
134     * @param String $data       : representing the unsigned Long
135     * @param String $endianType : the byte order
136     * @return ULong
137     */
138    static public function toULong($data, $endianType)
139    {
140      if(strlen($data)>=4)
141      {
142        if($endianType==BYTE_ORDER_LITTLE_ENDIAN)
143          return(ord($data{0}) +
144                 ord($data{1})*256 +
145                 ord($data{2})*65536 +
146                 ord($data{3})*16777216);
147        else
148          return(ord($data{0})*16777216 +
149                 ord($data{1})*65536 +
150                 ord($data{2})*256 +
151                 ord($data{3}));
152      }
153      else
154      {
155        return(0);
156      }
157    }
158
159    /**
160     * Convert the given data into a signed Long integer (32bit)
161     *
162     * @param String $data       : representing the signed Long
163     * @param String $endianType : the byte order
164     * @return SLong
165     */
166    static public function toSLong($data, $endianType)
167    {
168      $unsigned = self::toULong($data, $endianType);
169      if($unsigned>2147483647)
170        return($unsigned-4294967296);
171      else
172        return($unsigned);
173    }
174
175    /**
176     * Convert the given data into an array of unsigned Long (2x32bit)
177     *
178     * @param String $data       : representing the unsigned Rational
179     * @param String $endianType : the byte order
180     * @return URational
181     */
182    static public function toURational($data, $endianType)
183    {
184      if(strlen($data)>=8)
185      {
186        return(
187          Array(
188            self::toULong($data, $endianType),
189            self::toULong(substr($data, 4), $endianType)
190          )
191        );
192      }
193      else
194      {
195        return(Array(0,0));
196      }
197    }
198
199    /**
200     * Convert the given data into an array of signed Long (2x32bit)
201     *
202     * @param String $data       : representing the signed Rational
203     * @param String $endianType : the byte order
204     * @return SRational
205     */
206    static public function toSRational($data, $endianType)
207    {
208      if(strlen($data)>=8)
209      {
210        return(
211          Array(
212            self::toSLong($data, $endianType),
213            self::toSLong(substr($data, 4), $endianType)
214          )
215        );
216      }
217      else
218      {
219        return(Array(0,0));
220      }
221    }
222
223    /**
224     * Convert a floating value exprimed in seconds into a "photographic"
225     * value
226     *
227     * example :
228     *  1.5   => "1.5s"
229     *  0.004 => "1/250s"     *
230     *
231     * @param Float $time : time to convert
232     * @return String
233     */
234    static public function toExposureTime($time)
235    {
236      if($time>=1 or $time==0)
237      {
238        return($time."s");
239      }
240      else
241      {
242        return(sprintf("1/%ds", 1/$time));
243      }
244    }
245
246    /**
247     * Convert a floating value in a f/x.y string
248     *
249     * example :
250     *  1.8 => "f/1.8"
251     *  8   => "f/8.0"
252     *
253     * @param Float $fNumber : fnumber
254     * @return String
255     */
256    static public function toFNumber($fNumber)
257    {
258      return(sprintf("f/%.1f", $fNumber));
259    }
260
261    /**
262     * Convert a string Date/Time into a DateTime object
263     *
264     * Example of valid string :
265     *  "2009:12:24 19:54"
266     *  "2009:12:24 19:54\x00"
267     *  "2009:12:24 19:54:38"
268     *  "2009:12:24 19:54:38\x00"
269     *  "2009-12-24 19:54"
270     *  "2009-12-24T19:54"
271     *  "2009-12-24 19:54:38"
272     *  "2009-12-24T19:54:38"
273     *  "2009-12-24 19:54Z"
274     *  "2009-12-24T19:54Z"
275     *  "2009-12-24 19:54:38Z"
276     *  "2009-12-24T19:54:38Z"
277     *  "2009-12-24 19:54+02:00"
278     *  "2009-12-24T19:54+02:00"
279     *  "2009-12-24 19:54:38+02:00"
280     *  "2009-12-24T19:54:38+02:00"
281     *  "20091224"
282     *
283     * returns null if date is not a valid date
284     *
285     * @param String $dateTime : date time in a valid format
286     * @return String
287     */
288    static public function toDateTime($dateTime)
289    {
290      if(preg_match('/^(\d{4}:\d{2}:\d{2}\s\d{2}:\d{2}(:\d{2}){0,1}\x00{0,1}|\d{4}-\d{2}-\d{2}(T|\s)\d{2}:\d{2}(:\d{2}){0,1}(Z|[+|-]\d{2}:\d{2}){0,1}|\d{4}\d{2}\d{2})/', $dateTime))
291      {
292        $returned=new DateTime($dateTime, new DateTimeZone("UTC"));
293      }
294      else
295      {
296        $returned=null;
297      }
298      return($returned);
299    }
300
301    /**
302     * Convert a floating value in a focal length string
303     *
304     * Example:
305     *  250 => "250.0mm"
306     *
307     * @param Float $focalLength : focal length in millimeters
308     * @return String
309     */
310    static public function toFocalLength($focalLength)
311    {
312      return(sprintf("%.1f mm", $focalLength));
313    }
314
315    /**
316     * Convert a floating value in an EV
317     *
318     * Example:
319     *  0.7 => "0.7 EV"
320     *
321     * @param Float $ev : EV
322     * @return String
323     */
324    static public function toEV($ev)
325    {
326      return(sprintf("%.1f EV", $ev));
327    }
328
329    /**
330     * Convert a floating value associated with a unit
331     *
332     * Example :
333     *  3.4 + "m" => "3.40 m"
334     *
335     * @param Float $distance : distance
336     * @param String $unit    : unit
337     * @return String
338     */
339    static public function toDistance($distance, $unit)
340    {
341      return(sprintf("%.2f ", $distance)).$unit;
342    }
343
344    /**
345     * Convert a null terminated string into a string
346     * or
347     * Convert multiples null terminated string into an array of string
348     *    ==> if strings are null (eq. "\x00") nothing is added to the array
349     *
350     * Example:
351     *  "test" => "test"
352     *  "test\x00" => "test"
353     *  "test1\x00test2\x00" => Array("test1", "test2")
354     *
355     * @param String $strings
356     * @return String or String[]
357     */
358    static public function toStrings($strings)
359    {
360      if(strpos($strings, chr(0))===false)
361        return($strings);
362
363      $occurs=preg_match_all('/(.*)\x00/U',$strings,$result);
364      if($occurs==0)
365      {
366        return("");
367      }
368      else
369      {
370        $returned=Array();
371        foreach($result[1] as $pop)
372        {
373          if($pop!="")
374          {
375            $returned[]=$pop;
376          }
377        }
378        if(count($returned)==1)
379        {
380          return($returned[0]);
381        }
382        elseif(count($returned)==0)
383        {
384          return("");
385        }
386        else
387        {
388          return($returned);
389        }
390      }
391    }
392
393    /**
394     * Convert 3 rationnals (EXIF GPS format) into a Degree, Minute, Second into
395     * a formatted string   dd° mm' ss.cs"
396     *
397     * Example:
398     *  48/1 + 1600/100 + 347/10 => "48° 16' 34.70""
399     *
400     * @param URational $degrees : degrees
401     * @param URational $minutes : minutes
402     * @param URational $seconds : seconds
403     * @return String
404     */
405    static public function toDMS($degrees, $minutes, $seconds)
406    {
407      if($degrees[1]==0) $degrees[1]=1;
408      if($minutes[1]==0) $minutes[1]=1;
409      if($seconds[1]==0) $seconds[1]=1;
410
411      $deg=$degrees[0]/$degrees[1];
412      $min=($minutes[0]/$minutes[1])-((int)$deg-$deg)*60;
413      $sec=($seconds[0]/$seconds[1])-((int)$min-$min)*60;
414
415      $returned=sprintf("%d° %d' %.2f\"", $deg, $min, $sec);
416
417      return($returned);
418    }
419
420
421    /**
422     * Dump the given data into an hex string
423     *
424     * @param $data            : data to be dumped (the dump is function of the
425     *                           data type)
426     * @param UByte $type      : the type of data (uses the ByteType values)
427     * @param UShort $maxItems : for arrays (or ASCII string), the number or
428     *                           items (chars) to dump
429     * @return String
430     */
431    static public function toHexDump($data, $type, $maxItems = 0)
432    {
433      $returned="";
434      if(is_array($data))
435      {
436        if($maxItems==0)
437        {
438          $maxItems=count($data);
439        }
440        elseif($maxItems>count($data))
441        {
442          $maxItems=count($data);
443        }
444        else
445        {
446          $returned.="[returns only the first $maxItems of ".count($data)." values] ";
447        }
448
449        $tmp=Array();
450        for($i=0;$i<$maxItems;$i++)
451        {
452          $tmp[]=self::toHexDump($data[$i], $type, $maxItems);
453        }
454        $returned.="[".implode(",", $tmp)."]";
455      }
456      else
457      {
458        switch($type)
459        {
460          case ByteType::UBYTE :
461          case ByteType::SBYTE :
462            $returned.=sprintf("0x%02x", $data);
463            break;
464          case ByteType::USHORT :
465          case ByteType::SSHORT :
466            $returned.=sprintf("0x%04x", $data);
467            break;
468          case ByteType::ULONG :
469          case ByteType::SLONG :
470            $returned.=sprintf("0x%08x", $data);
471            break;
472          case ByteType::URATIONAL :
473          case ByteType::SRATIONAL :
474            $returned.=sprintf("0x%08x", $data);
475            break;
476          case ByteType::FLOAT :
477          case ByteType::DOUBLE :
478          case ByteType::ASCII :
479          case ByteType::UNDEFINED :
480          default:
481            if($maxItems==0)
482            {
483              $maxItems=strlen($data);
484            }
485            elseif($maxItems>strlen($data))
486            {
487              $maxItems=strlen($data);
488            }
489            else
490            {
491              $returned.="[returns only the first $maxItems of ".strlen($data)." bytes] ";
492            }
493
494            $tmp=array();
495            for($i=0;$i<$maxItems;$i++)
496            {
497              $tmp[]=sprintf("%02x", ord($data{$i}));
498            }
499            $returned.=implode(" ", $tmp);
500            break;
501        }
502      }
503      return($returned);
504    }
505
506
507  }
508
509
510?>
Note: See TracBrowser for help on using the repository browser.