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

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

[Plugin:AMetaData] prepare the directory for a future plugin

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