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

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

Optimize some memory leak and some bugged lines of code

  • Property svn:executable set to *
File size: 7.5 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      unset($this->fileName);
115    }
116
117    /**
118     * load a file
119     *
120     * @Param String $fileName
121     *
122     */
123    public function load($fileName)
124    {
125      /*
126       * initialize values
127       *
128       * if the file isn't a valid file, theses properties will not be in an
129       * uncertain state
130       */
131      $this->isLoaded=false;
132      $this->fileName="";
133      $this->isValid = false;
134      $this->appMarkerSegmentReader=Array();
135
136      /*
137       * if the file exist, try to open it
138       * determine if the file is a valid JPEG file
139       *
140       * if the file is valid, read the markers and close the file
141       */
142      if(file_exists($fileName))
143      {
144        $this->fileName=$fileName;
145
146        $this->fileHandler = fopen($fileName, "r");
147        if($this->fileHandler)
148        {
149          $this->isValid = $this->isAValidFile();
150
151          if($this->isValid)
152          {
153            $this->readAppMarkerSegments();
154            $this->isLoaded=true;
155          }
156
157          fclose($this->fileHandler);
158          return(true);
159        }
160        return(false);
161      }
162      return(false);
163    }
164
165    /**
166     *
167     * this function try to see if the given file is a valid jpg file (the file
168     * must begins with the SOI and ends with the EOI)
169     *
170     */
171    protected function isAValidFile()
172    {
173      fseek($this->fileHandler, -2, SEEK_END);
174      $header=fread($this->fileHandler, 2);
175      if(ConvertData::toUShort($header, BYTE_ORDER_BIG_ENDIAN) == self::JPEG_EOI)
176      {
177        /*
178         * the file ends with the good marker
179         */
180        fseek($this->fileHandler, 0);
181        $header=fread($this->fileHandler, 2);
182        if(ConvertData::toUShort($header, BYTE_ORDER_BIG_ENDIAN) == self::JPEG_SOI)
183        {
184          return(true);
185        }
186      }
187      return(false);
188    }
189
190    /**
191     *
192     * This function reads all the segment of the jpeg file
193     *
194     */
195    private function readAppMarkerSegments()
196    {
197      /*
198       * loop to read all markers
199       */
200      $offset=2;
201      while(true)
202      {
203        $marker=AppMarkerSegmentReader::read($this->fileHandler, $offset);
204        if($marker)
205        {
206          /*
207           * if there is a marker returned, push it on the markers array
208           */
209          $this->appMarkerSegmentReader[]=$marker;
210          $offset+=$marker->getLength();
211          unset($marker);
212        }
213        else
214        {
215          /*
216           * if there is no marker returned (end of file ?) stop markers loading
217           */
218          return(false);
219        }
220      }
221
222    }
223
224
225    /**
226     *
227     * returns the filename given to the object
228     *
229     */
230    public function getFileName()
231    {
232      return($this->fileName);
233    }
234
235    /**
236     *
237     * returns true if the given jpeg file has been succesfully loaded
238     *
239     */
240    public function isLoaded()
241    {
242      return($this->isLoaded);
243    }
244
245    /**
246     *
247     * returns true if the given jpeg file is a valid file
248     *
249     */
250    public function isValid()
251    {
252      return($this->isValid);
253    }
254
255    /**
256     *
257     * returns the number od segments loaded
258     *
259     */
260    public function countAppMarkerSegments()
261    {
262      return(count($this->appMarkerSegmentReader));
263    }
264
265    /**
266     *
267     * returns an array of AppMarkerSegments
268     *
269     * see the AppMarkerSegmentsReader.class.php for more informations
270     *
271     */
272    public function getAppMarkerSegments()
273    {
274      return($this->appMarkerSegmentReader);
275    }
276
277  }
278
279
280 ?>
Note: See TracBrowser for help on using the repository browser.