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 PentaxReader class is the dedicated to read the specific Pentax 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 PentaxReader 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."Common/GlobalTags.class.php"); |
---|
57 | require_once(JPEG_METADATA_DIR."TagDefinitions/PentaxTags.class.php"); |
---|
58 | require_once(JPEG_METADATA_DIR."Readers/MakerNotesReader.class.php"); |
---|
59 | |
---|
60 | class PentaxReader extends MakerNotesReader |
---|
61 | { |
---|
62 | protected $schema = Schemas::EXIF; |
---|
63 | |
---|
64 | /** |
---|
65 | * The constructor needs, like the ancestor, the datas to be parsed |
---|
66 | * |
---|
67 | * Some datas are offset on extra data, and this offset can be (some time) |
---|
68 | * absolute inside the IFD, or relative. So, the offset of the IFD structure |
---|
69 | * is needed |
---|
70 | * |
---|
71 | * The byte order can be different from the TIFF byte order ! |
---|
72 | * |
---|
73 | * The constructor need the maker signature (see the MakerNotesSignatures |
---|
74 | * class for a list of known signatures) |
---|
75 | * |
---|
76 | * @param String $data |
---|
77 | * @param ULong $offset : offset of IFD block in the jpeg file |
---|
78 | * @param String $byteOrder |
---|
79 | * @param String $makerSignature : |
---|
80 | */ |
---|
81 | function __construct($data, $offset, $byteOrder, $makerSignature) |
---|
82 | { |
---|
83 | $this->maker = MAKER_PENTAX; |
---|
84 | switch($makerSignature) |
---|
85 | { |
---|
86 | case MakerNotesSignatures::PentaxHeader: |
---|
87 | $this->header = MakerNotesSignatures::PentaxHeader; |
---|
88 | $this->headerSize = MakerNotesSignatures::PentaxHeaderSize; |
---|
89 | break; |
---|
90 | case MakerNotesSignatures::Pentax2Header: |
---|
91 | $this->header = MakerNotesSignatures::Pentax2Header; |
---|
92 | $this->headerSize = MakerNotesSignatures::Pentax2HeaderSize; |
---|
93 | break; |
---|
94 | } |
---|
95 | |
---|
96 | parent::__construct($data, $offset, $byteOrder); |
---|
97 | } |
---|
98 | |
---|
99 | function __destruct() |
---|
100 | { |
---|
101 | parent::__destruct(); |
---|
102 | } |
---|
103 | |
---|
104 | /** |
---|
105 | * initialize the definition for Pentax exif tags |
---|
106 | */ |
---|
107 | protected function initializeTagDef() |
---|
108 | { |
---|
109 | $this->tagDef = new PentaxTags(); |
---|
110 | } |
---|
111 | |
---|
112 | /** |
---|
113 | * skip the IFD header |
---|
114 | */ |
---|
115 | protected function skipHeader($headerSize=0) |
---|
116 | { |
---|
117 | parent::skipHeader($this->headerSize); |
---|
118 | } |
---|
119 | |
---|
120 | /** |
---|
121 | * this function do the interpretation of specials tags |
---|
122 | * |
---|
123 | * the function return the interpreted value for the tag |
---|
124 | * |
---|
125 | * @param $tagId : the id of the tag |
---|
126 | * @param $values : 'raw' value to be interpreted |
---|
127 | * @param UByte $type : if needed (for IFD structure) the type of data |
---|
128 | * @param ULong $valueOffset : if needed, the offset of data in the jpeg file |
---|
129 | * @return String or Array or DateTime or Integer or Float... |
---|
130 | */ |
---|
131 | protected function processSpecialTag($tagId, $values, $type, $valuesOffset=0) |
---|
132 | { |
---|
133 | switch($tagId) |
---|
134 | { |
---|
135 | case 0x0000: // "Version" |
---|
136 | $returned=sprintf("%d.%d.%d.%d", $values[0], $values[1], $values[2], $values[3]); |
---|
137 | break; |
---|
138 | case 0x0002: // "PreviewResolution" |
---|
139 | $returned=sprintf("%dx%d", $values[0], $values[1]); |
---|
140 | break; |
---|
141 | case 0x0003: // "PreviewLength", |
---|
142 | case 0x0004: // "PreviewOffset", |
---|
143 | $returned=$values; |
---|
144 | break; |
---|
145 | case 0x0006: // "Date", |
---|
146 | $returned=sprintf("%04d/%02d/%02d", ConvertData::toUShort($values, BYTE_ORDER_BIG_ENDIAN), ConvertData::toUByte($values{2}), ConvertData::toUByte($values{3})); |
---|
147 | break; |
---|
148 | case 0x0007: // "Time", |
---|
149 | $returned=sprintf("%02d:%02d:%02d", ConvertData::toUByte($values{0}), ConvertData::toUByte($values{1}), ConvertData::toUByte($values{2})); |
---|
150 | break; |
---|
151 | case 0x000c: // "Flash", |
---|
152 | $tag=$this->tagDef->getTagById(0x000c); |
---|
153 | $returned=Array(); |
---|
154 | if(array_key_exists($values[0], $tag['tagValues.special'][0])) |
---|
155 | $returned[]=$tag['tagValues.special'][0][$values[0]]; |
---|
156 | if(array_key_exists($values[1], $tag['tagValues.special'][1])) |
---|
157 | $returned[]=$tag['tagValues.special'][1][$values[1]]; |
---|
158 | unset($tag); |
---|
159 | break; |
---|
160 | case 0x0012: // "ExposureTime", from exiftool |
---|
161 | $returned=ConvertData::toExposureTime($values/100000); |
---|
162 | break; |
---|
163 | case 0x0013: // "FNumber", |
---|
164 | $returned=ConvertData::toFNumber($values/10); |
---|
165 | break; |
---|
166 | case 0x0016: // "ExposureCompensation", |
---|
167 | $returned=sprintf("%.1f EV", ($values-50)/10); |
---|
168 | break; |
---|
169 | case 0x0018: // "AutoBracketing", |
---|
170 | /* |
---|
171 | * $values if an array |
---|
172 | * [0] : exposure compensation |
---|
173 | * [1] : bracketing mode |
---|
174 | */ |
---|
175 | if($values[0]<10) |
---|
176 | $returned=Array(($values[0]/3)." EV"); |
---|
177 | else |
---|
178 | $returned=Array(($values[0]-9.5)." EV"); |
---|
179 | |
---|
180 | if($values[1]==0) |
---|
181 | $returned[]="No extended bracketing"; |
---|
182 | else |
---|
183 | { |
---|
184 | $type = $values[1] >> 8; |
---|
185 | $range = $values[1] & 0xff; |
---|
186 | switch ($type) |
---|
187 | { |
---|
188 | case 1: |
---|
189 | $returned[]="WB-BA"; |
---|
190 | break; |
---|
191 | case 2: |
---|
192 | $returned[]="WB-GM"; |
---|
193 | break; |
---|
194 | case 3: |
---|
195 | $returned[]="Saturation"; |
---|
196 | break; |
---|
197 | case 4: |
---|
198 | $returned[]="Sharpness"; |
---|
199 | break; |
---|
200 | case 5: |
---|
201 | $returned[]="Contrast"; |
---|
202 | break; |
---|
203 | default: |
---|
204 | $returned[]="Unknown;".ConvertData::toHexDump($type, ByteType::USHORT); |
---|
205 | break; |
---|
206 | } |
---|
207 | $returned[]=$range; |
---|
208 | } |
---|
209 | break; |
---|
210 | case 0x001b: // "BlueBalance", |
---|
211 | case 0x001c: // "RedBalance", from exiftool |
---|
212 | $returned=sprintf("%d", $values/256+0.5); |
---|
213 | break; |
---|
214 | case 0x001d: // "FocalLength", |
---|
215 | /* note : in exiftool, the formula change with the camera model... ? */ |
---|
216 | $returned=($values/100)." mm"; |
---|
217 | break; |
---|
218 | case 0x001e: // "DigitalZoom", from exiftool |
---|
219 | $returned=($values/100); |
---|
220 | break; |
---|
221 | case 0x0025: // "HometownDST", |
---|
222 | case 0x0026: // "DestinationDST", |
---|
223 | $returned=($values==1)?"Yes":"No"; |
---|
224 | break; |
---|
225 | case 0x0027: // "DSPFirmwareVersion", |
---|
226 | case 0x0028: // "CPUFirmwareVersion", |
---|
227 | $returned=sprintf("%d.%d.%d.%d", 0xff-ConvertData::toUByte($values{0}), 0xff-ConvertData::toUByte($values{1}), 0xff-ConvertData::toUByte($values{2}), 0xff-ConvertData::toUByte($values{3})); |
---|
228 | break; |
---|
229 | case 0x002d: // "EffectiveLV", |
---|
230 | $returned=sprintf("%.1f", $values/1024); |
---|
231 | break; |
---|
232 | case 0x0039: // "RawImageSize", |
---|
233 | $returned=sprintf("%dx%d", $values[0], $values[1]); |
---|
234 | break; |
---|
235 | case 0x003e: // "PreviewImageBorders", |
---|
236 | $returned=ConvertData::toHexDump($values, ByteType::UBYTE); |
---|
237 | break; |
---|
238 | case 0x003f: // "LensType", |
---|
239 | $tag=$this->tagDef->getTagById(0x003f); |
---|
240 | $id=$values[1]+($values[0]<<8); |
---|
241 | if(!array_key_exists($id, $tag['tagValues.special'])) $id=0xffff; |
---|
242 | |
---|
243 | $returned=""; |
---|
244 | |
---|
245 | $lensesList=$tag['tagValues.special'][$id]; |
---|
246 | if(is_array($lensesList)) |
---|
247 | { |
---|
248 | foreach($lensesList as $lens) |
---|
249 | { |
---|
250 | /* |
---|
251 | * If there is more than one lens associated with a lens id |
---|
252 | * |
---|
253 | * 1/ try to found the min/max focals of the lens |
---|
254 | * 2/ try to found the min/max aperture of the lens |
---|
255 | * 3/ if focal is fixed, make min = max |
---|
256 | * 4/ if aperture is constant, make min)max |
---|
257 | * 5/ look if : min focal <= photo focal <= max focal and |
---|
258 | * photo aperture >= min aperture |
---|
259 | * if yes, the lens is returned, otherwise test next |
---|
260 | * lens |
---|
261 | */ |
---|
262 | preg_match("/.*\s(?:([0-9]+){1}(?:-([0-9]+))?)mm.*/i", $lens, $focals); |
---|
263 | preg_match("/.*\sF(?:([0-9\.]+){1}(?:-([0-9\.]+))?).*/i", $lens, $apertures); |
---|
264 | |
---|
265 | if(count($focals)==2) |
---|
266 | { |
---|
267 | //focal is not a zoom, min = max |
---|
268 | $focals[]=$focal[1]; |
---|
269 | } |
---|
270 | elseif(count($focals)==0) |
---|
271 | { |
---|
272 | $focal=Array(0,0,0); |
---|
273 | } |
---|
274 | |
---|
275 | |
---|
276 | if(count($apertures)==2) |
---|
277 | { |
---|
278 | //aperture is constant, min = max |
---|
279 | $apertures[]=$apertures[1]; |
---|
280 | } |
---|
281 | elseif(count($apertures)==0) |
---|
282 | { |
---|
283 | $apertures=Array(0,0,0); |
---|
284 | } |
---|
285 | |
---|
286 | $focal=GlobalTags::getExifFocal(); |
---|
287 | if($focal=="") $focal=-1; |
---|
288 | |
---|
289 | $aperture=GlobalTags::getExifAperture(); |
---|
290 | if($aperture=="") $aperture=-1; |
---|
291 | |
---|
292 | if($focals[1]<=$focal && $focal<=$focals[2] && $aperture>=$apertures[1] && $returned=="") |
---|
293 | { |
---|
294 | $returned=$lens; |
---|
295 | } |
---|
296 | |
---|
297 | unset($lens); |
---|
298 | unset($focals); |
---|
299 | unset($apertures); |
---|
300 | } |
---|
301 | if($returned=="") |
---|
302 | { |
---|
303 | // no lens seems to be valid, returns the lens list |
---|
304 | $returned=$lensesList; |
---|
305 | } |
---|
306 | } |
---|
307 | else |
---|
308 | { |
---|
309 | // not a list, just a single lens |
---|
310 | $returned=$lensesList; |
---|
311 | } |
---|
312 | |
---|
313 | unset($tag); |
---|
314 | unset($id); |
---|
315 | break; |
---|
316 | case 0x0040: // "SensitivityAdjust", from exiftool |
---|
317 | /* is the conversion perl => php is good !? */ |
---|
318 | $returned=sprintf("%.1f", ($values-50)/10+50); |
---|
319 | break; |
---|
320 | case 0x0047: // "Temperature", |
---|
321 | $returned=(($values>127)?256-$values:$values)."°C"; |
---|
322 | break; |
---|
323 | case 0x0048: // "AELock", |
---|
324 | case 0x0049: // "NoiseReduction", |
---|
325 | $returned=($values==1)?"On":"Off"; |
---|
326 | break; |
---|
327 | case 0x004d: // "FlashExposureCompensation", |
---|
328 | $returned=ConvertData::toEV($values/256); |
---|
329 | break; |
---|
330 | case 0x0050: // "ColorTemperature", from exiftool |
---|
331 | $returned=53190 -$values; |
---|
332 | break; |
---|
333 | |
---|
334 | /* theses tags decoding is not yet implemented |
---|
335 | * have to take a look on the algorithm in exiftool (it seems to work |
---|
336 | * but I don't understand everything...) |
---|
337 | */ |
---|
338 | |
---|
339 | case 0x0205: // "ShotInfo", |
---|
340 | case 0x0206: // "AEInfo", |
---|
341 | case 0x0207: // "LensInfo", |
---|
342 | case 0x0208: // "FlashInfo", |
---|
343 | case 0x0209: // "AEMeteringSegments", |
---|
344 | case 0x020a: // "FlashADump", |
---|
345 | case 0x020b: // "FlashBDump", |
---|
346 | case 0x020d: // "WB_RGGBLevelsDaylight", |
---|
347 | case 0x020e: // "WB_RGGBLevelsShade", |
---|
348 | case 0x020f: // "WB_RGGBLevelsCloudy", |
---|
349 | case 0x0210: // "WB_RGGBLevelsTungsten", |
---|
350 | case 0x0211: // "WB_RGGBLevelsFluorescentD", |
---|
351 | case 0x0212: // "WB_RGGBLevelsFluorescentN", |
---|
352 | case 0x0213: // "WB_RGGBLevelsFluorescentW", |
---|
353 | case 0x0214: // "WB_RGGBLevelsFlash", |
---|
354 | case 0x0215: // "CameraInfo", |
---|
355 | case 0x0216: // "BatteryInfo", |
---|
356 | case 0x021f: // "AFInfo", |
---|
357 | case 0x0222: // "ColorInfo", |
---|
358 | |
---|
359 | case 0x0029: // "FrameNumber", |
---|
360 | case 0x0041: // "DigitalFilter", |
---|
361 | case 0x005c: // "ShakeReduction", |
---|
362 | case 0x005d: // "ShutterCount", |
---|
363 | case 0x0200: // "BlackPoint", |
---|
364 | case 0x0201: // "WhitePoint", |
---|
365 | case 0x0203: // "ColorMatrixA", |
---|
366 | case 0x0204: // "ColorMatrixB", |
---|
367 | default: |
---|
368 | $returned="Not yet implemented;".ConvertData::toHexDump($tagId, ByteType::USHORT)." => ".ConvertData::toHexDump($values, $type); |
---|
369 | break; |
---|
370 | } |
---|
371 | return($returned); |
---|
372 | } |
---|
373 | } |
---|
374 | |
---|
375 | ?> |
---|