source: extensions/AMetaData/JpegMetaData/Readers/JpegReader.class.php @ 4705

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

Change Locale class by L10n class ; add Readers for Nikon and Canon cameras ; some bug corrected

  • Property svn:executable set to *
File size: 7.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 * The JpegReader is the class for reading a Jpeg file
35 *
36 * Datas provided by this class are less friendly than data provided by the
37 * JpegMetaData class, because here you have to know the Jpeg format to
38 * understand how to exploit datas
39 *
40 * -----------------------------------------------------------------------------
41 *
42 * .. Notes ..
43 *
44 * The JpegReader class use a dedicated AppMarkerSegmentReader class rather than
45 * the php "getimagesize()" function because the php function returns an
46 * associative array of markers like ("APP1" => "......", "APPx" => "......")
47 *
48 * Typically a jpeg file contains XMP data inside an APP1 marker, like the exif
49 * codes. So, when using the php function, APP1 with XMP values isn't present
50 * (only the first APP1 segment found and used for EXIF is present)
51 *
52 *
53 * A Jpeg file normally begins with the 2 bytes FFD8 (the SOI marker) and ends
54 * with the 2 bytes FFD9 (the EOI marker)
55 * Some file have extra data after the EOI marker ; for now, the class can't
56 * manage this kind of file.
57 *
58 * The class use the AppMarkerSegmentReader class to get the content of :
59 *  - APP1 marker  => Exif, XMP
60 *  - APP13 marker => Iptc
61 *
62 * This class provides theses public functions :
63 *  - load
64 *  - getFileName
65 *  - isLoaded
66 *  - isValid
67 *  - countAppMarkerSegments
68 *  - getAppMarkerSegments
69 *
70 *  Read the code for help
71 *
72 * -----------------------------------------------------------------------------
73 */
74
75  require_once(JPEG_METADATA_DIR."Readers/AppMarkerSegmentReader.class.php");
76
77  class JpegReader
78  {
79    /**
80     * start of image file tag
81     */
82    const JPEG_SOI = 0xFFD8;
83    /**
84     * end of image file tag
85     */
86    const JPEG_EOI = 0xFFD9;
87
88
89    private $fileName = "";
90    private $isLoaded = false;
91    private $isValid = false;
92    private $appMarkerSegmentReader = Array();
93
94    private $fileHandler = false;
95
96    /**
97     * the constructor need an optional filename
98     *
99     * if no filename is given, you can use the "load" function after the object
100     * is instancied
101     *
102     * @Param String $fileName (optional)
103     *
104     */
105    function __construct($fileName = "")
106    {
107      if($fileName!="") $this->load($fileName);
108    }
109
110    function __destruct()
111    {
112      unset($this->appMarkerSegmentReader);
113      unset($this->fileHandler);
114    }
115
116    /**
117     * load a file
118     *
119     * @Param String $fileName
120     *
121     */
122    public function load($fileName)
123    {
124      /*
125       * initialize values
126       *
127       * if the file isn't a valid file, theses properties will not be in an
128       * uncertain state
129       */
130      $this->isLoaded=false;
131      $this->fileName="";
132      $this->isValid = false;
133      $this->appMarkerSegmentReader=Array();
134
135      /*
136       * if the file exist, try to open it
137       * determine if the file is a valid JPEG file
138       *
139       * if the file is valid, read the markers and close the file
140       */
141      if(file_exists($fileName))
142      {
143        $this->fileName=$fileName;
144
145        $this->fileHandler = fopen($fileName, "r");
146        if($this->fileHandler)
147        {
148          $this->isValid = $this->isAValidFile();
149
150          if($this->isValid)
151          {
152            $this->readAppMarkerSegments();
153            $this->isLoaded=true;
154          }
155
156          fclose($this->fileHandler);
157          return(true);
158        }
159        return(false);
160      }
161      return(false);
162    }
163
164    /**
165     *
166     * this function try to see if the given file is a valid jpg file (the file
167     * must begins with the SOI and ends with the EOI)
168     *
169     */
170    protected function isAValidFile()
171    {
172      fseek($this->fileHandler, -2, SEEK_END);
173      $header=fread($this->fileHandler, 2);
174      if(ConvertData::toUShort($header, BYTE_ORDER_BIG_ENDIAN) == self::JPEG_EOI)
175      {
176        /*
177         * the file ends with the good marker
178         */
179        fseek($this->fileHandler, 0);
180        $header=fread($this->fileHandler, 2);
181        if(ConvertData::toUShort($header, BYTE_ORDER_BIG_ENDIAN) == self::JPEG_SOI)
182        {
183          return(true);
184        }
185      }
186      return(false);
187    }
188
189    /**
190     *
191     * This function reads all the segment of the jpeg file
192     *
193     */
194    private function readAppMarkerSegments()
195    {
196      /*
197       * loop to read all markers
198       */
199      $offset=2;
200      while(true)
201      {
202        $marker=AppMarkerSegmentReader::read($this->fileHandler, $offset);
203        if($marker)
204        {
205          /*
206           * if there is a marker returned, push it on the markers array
207           */
208          $this->appMarkerSegmentReader[]=$marker;
209          $offset+=$marker->getLength();
210        }
211        else
212        {
213          /*
214           * if there is no marker returned (end of file ?) stop markers loading
215           */
216          return(false);
217        }
218      }
219
220    }
221
222
223    /**
224     *
225     * returns the filename given to the object
226     *
227     */
228    public function getFileName()
229    {
230      return($this->fileName);
231    }
232
233    /**
234     *
235     * returns true if the given jpeg file has been succesfully loaded
236     *
237     */
238    public function isLoaded()
239    {
240      return($this->isLoaded);
241    }
242
243    /**
244     *
245     * returns true if the given jpeg file is a valid file
246     *
247     */
248    public function isValid()
249    {
250      return($this->isValid);
251    }
252
253    /**
254     *
255     * returns the number od segments loaded
256     *
257     */
258    public function countAppMarkerSegments()
259    {
260      return(count($this->appMarkerSegmentReader));
261    }
262
263    /**
264     *
265     * returns an array of AppMarkerSegments
266     *
267     * see the AppMarkerSegmentsReader.class.php for more informations
268     *
269     */
270    public function getAppMarkerSegments()
271    {
272      return($this->appMarkerSegmentReader);
273    }
274
275  }
276
277
278 ?>
Note: See TracBrowser for help on using the repository browser.