Source for file PelEntry.php

Documentation is available at PelEntry.php

  1. <?php
  2.  
  3. /* PEL: PHP EXIF Library. A library with support for reading and
  4. * writing all EXIF headers in JPEG and TIFF images using PHP.
  5. *
  6. * Copyright (C) 2004, 2005 Martin Geisler.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program in the file COPYING; if not, write to the
  20. * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  21. * Boston, MA 02111-1307 USA
  22. */
  23.  
  24. /* PelEntry.php,v 1.19 2005/02/10 21:22:39 gimpster Exp */
  25.  
  26.  
  27. /**
  28. * Classes for dealing with EXIF entries.
  29. *
  30. * This file defines two exception classes and the abstract class
  31. * {@link PelEntry} which provides the basic methods that all EXIF
  32. * entries will have. All EXIF entries will be represented by
  33. * descendants of the {@link PelEntry} class.
  34. *
  35. * @author Martin Geisler <gimpster@users.sourceforge.net>
  36. * @version 1.19
  37. * @date 2005/02/10 21:22:39
  38. * @license http://www.gnu.org/licenses/gpl.html GNU General Public
  39. * License (GPL)
  40. * @package PEL
  41. */
  42.  
  43. /**#@+ Required class definitions. */
  44. ('PelDataWindow.php');
  45. require_once('PelException.php');
  46. require_once('PelFormat.php');
  47. require_once('PelTag.php');
  48. require_once('Pel.php');
  49. /**#@-*/ * Exception indicating a problem with the entry.
  50. *
  51. * @author Martin Geisler <gimpster@users.sourceforge.net>
  52. * @package PEL
  53. * @subpackage Exception
  54. */
  55. class PelEntryException extends PelException {}
  56.  
  57.  
  58. /**
  59. * Exception indicating that an unexpected format was found.
  60. *
  61. * @author Martin Geisler <gimpster@users.sourceforge.net>
  62. * @package PEL
  63. * @subpackage Exception
  64. */
  65. class PelUnexpectedFormatException extends PelEntryException {
  66.  
  67. /**
  68. * Construct a new exception indicating an invalid format.
  69. *
  70. * @param PelTag the tag for which the violation was found.
  71. *
  72. * @param PelFormat the format found.
  73. *
  74. * @param PelFormat the expected format.
  75. */
  76. function __construct($tag, $found, $expected) {
  77. parent::__construct('Unexpected format found for %s tag: %s. ' .
  78. 'Expected %s instead.',
  79. PelTag::getName($tag),
  80. PelFormat::getName($found),
  81. PelFormat::getName($expected));
  82. }
  83. }
  84.  
  85.  
  86. /**
  87. * Exception indicating that an unexpected number of components was
  88. * found.
  89. *
  90. * @author Martin Geisler <gimpster@users.sourceforge.net>
  91. * @package PEL
  92. * @subpackage Exception
  93. */
  94. class PelWrongComponentCountException extends PelEntryException {
  95.  
  96. /**
  97. * Construct a new exception indicating a wrong number of
  98. * components.
  99. *
  100. * Some tags have strict limits as to the allowed number of
  101. * components, and this exception is thrown if the data violates
  102. * such a constraint.
  103. *
  104. * @param PelTag the tag for which the violation was found.
  105. *
  106. * @param int the number of components found.
  107. *
  108. * @param int the expected number of components.
  109. */
  110. function __construct($tag, $found, $expected) {
  111. parent::__construct('Wrong number of components found for %s tag: %d. ' .
  112. 'Expected %d.',
  113. PelTag::getName($tag), $found, $expected);
  114. }
  115. }
  116.  
  117.  
  118. /**
  119. * @author Martin Geisler <gimpster@users.sourceforge.net>
  120. * @package PEL
  121. */
  122. abstract class PelEntry {
  123.  
  124. /**
  125. * The bytes representing this entry.
  126. *
  127. * Subclasses must either override {@link getBytes()} or, if
  128. * possible, maintain this property so that it always contains a
  129. * true representation of the entry.
  130. *
  131. * @var string
  132. */
  133. protected $bytes = '';
  134.  
  135. /**
  136. * The {@link PelTag} of this entry.
  137. *
  138. * @var PelTag
  139. */
  140. protected $tag;
  141.  
  142. /**
  143. * The {@link PelFormat} of this entry.
  144. *
  145. * @var PelFormat
  146. */
  147. protected $format;
  148.  
  149. /**
  150. * The number of components of this entry.
  151. *
  152. * @var int
  153. */
  154. protected $components;
  155.  
  156.  
  157. /**
  158. * Make a new entry from a bunch of bytes.
  159. *
  160. * This factory method will create the proper subclass of {@link }
  161. * PelEntry} corresponding to the {@link PelTag} and {@link }
  162. * PelFormat} given.
  163. *
  164. * A {@link PelUnexpectedFormatException} is thrown if a mismatch is
  165. * discovered between the tag and format, and likewise a {@link }
  166. * PelWrongComponentCountException} is thrown if the number of
  167. * components does not match the requirements of the tag. The
  168. * requirements for a given tag (if any) can be found in the
  169. * documentation for {@link PelTag}.
  170. *
  171. * @param PelTag the tag of the entry.
  172. *
  173. * @param PelFormat the format of the entry.
  174. *
  175. * @param int the components in the entry.
  176. *
  177. * @param PelDataWindow the data which will be used to construct the
  178. * entry.
  179. *
  180. * @return PelEntry a newly created entry, holding the data given.
  181. */
  182. static function newFromData($tag, $format, $components, $data) {
  183.  
  184. /* First handle tags for which we have a specific PelEntryXXX
  185. * class. */
  186. switch ($tag) {
  187. case PelTag::DATE_TIME:
  188. case PelTag::DATE_TIME_ORIGINAL:
  189. case PelTag::DATE_TIME_DIGITIZED:
  190. if ($format != PelFormat::ASCII)
  191. throw new PelUnexpectedFormatException($tag, $format,
  192. PelFormat::ASCII);
  193.  
  194. if ($components != 20)
  195. throw new PelWrongComponentCountException($tag, $components, 20);
  196.  
  197. /* Split the string into year, month, date, hour, minute, and
  198. * second components. */
  199. $d = explode('-', strtr($data->getBytes(0, -1), '.: ', '---'));
  200. // TODO: handle timezones.
  201. require_once('PelEntryAscii.php');
  202. return new PelEntryTime($tag, gmmktime($d[3], $d[4], $d[5],
  203. $d[1], $d[2], $d[0]));
  204.  
  205. case PelTag::COPYRIGHT:
  206. if ($format != PelFormat::ASCII)
  207. throw new PelUnexpectedFormatException($tag, $format,
  208. PelFormat::ASCII);
  209. $v = explode("\0", trim($data->getBytes(), ' '));
  210. require_once('PelEntryAscii.php');
  211. return new PelEntryCopyright($v[0], $v[1]);
  212.  
  213. case PelTag::EXIF_VERSION:
  214. case PelTag::FLASH_PIX_VERSION:
  215. case PelTag::INTEROPERABILITY_VERSION:
  216. if ($format != PelFormat::UNDEFINED)
  217. throw new PelUnexpectedFormatException($tag, $format,
  218. PelFormat::UNDEFINED);
  219.  
  220. require_once('PelEntryUndefined.php');
  221. return new PelEntryVersion($tag, $data->getBytes() / 100);
  222.  
  223. case PelTag::USER_COMMENT:
  224. if ($format != PelFormat::UNDEFINED)
  225. throw new PelUnexpectedFormatException($tag, $format,
  226. PelFormat::UNDEFINED);
  227.  
  228. require_once('PelEntryUndefined.php');
  229. if ($data->getSize() < 8) {
  230. return new PelEntryUserComment();
  231. } else {
  232. return new PelEntryUserComment($data->getBytes(8),
  233. rtrim($data->getBytes(0, 8)));
  234. }
  235.  
  236. default:
  237. /* Then handle the formats. */
  238. switch ($format) {
  239. case PelFormat::BYTE:
  240. require_once('PelEntryByte.php');
  241. $v = new PelEntryByte($tag);
  242. for ($i = 0; $i < $components; $i++)
  243. $v->addNumber($data->getByte($i));
  244. return $v;
  245.  
  246. case PelFormat::SBYTE:
  247. require_once('PelEntryByte.php');
  248. $v = new PelEntrySByte($tag);
  249. for ($i = 0; $i < $components; $i++)
  250. $v->addNumber($data->getSByte($i));
  251. return $v;
  252.  
  253. case PelFormat::ASCII:
  254. require_once('PelEntryAscii.php');
  255. return new PelEntryAscii($tag, $data->getBytes(0, -1));
  256.  
  257. case PelFormat::SHORT:
  258. require_once('PelEntryShort.php');
  259. $v = new PelEntryShort($tag);
  260. for ($i = 0; $i < $components; $i++)
  261. $v->addNumber($data->getShort($i*2));
  262. return $v;
  263.  
  264. case PelFormat::SSHORT:
  265. require_once('PelEntryShort.php');
  266. $v = new PelEntrySShort($tag);
  267. for ($i = 0; $i < $components; $i++)
  268. $v->addNumber($data->getSShort($i*2));
  269. return $v;
  270.  
  271. case PelFormat::LONG:
  272. require_once('PelEntryLong.php');
  273. $v = new PelEntryLong($tag);
  274. for ($i = 0; $i < $components; $i++)
  275. $v->addNumber($data->getLong($i*4));
  276. return $v;
  277.  
  278. case PelFormat::SLONG:
  279. require_once('PelEntryLong.php');
  280. $v = new PelEntrySLong($tag);
  281. for ($i = 0; $i < $components; $i++)
  282. $v->addNumber($data->getSLong($i*4));
  283. return $v;
  284.  
  285. case PelFormat::RATIONAL:
  286. require_once('PelEntryRational.php');
  287. $v = new PelEntryRational($tag);
  288. for ($i = 0; $i < $components; $i++)
  289. $v->addNumber($data->getRational($i*8));
  290. return $v;
  291.  
  292. case PelFormat::SRATIONAL:
  293. require_once('PelEntryRational.php');
  294. $v = new PelEntrySRational($tag);
  295. for ($i = 0; $i < $components; $i++)
  296. $v->addNumber($data->getSRational($i*8));
  297. return $v;
  298.  
  299. case PelFormat::UNDEFINED:
  300. require_once('PelEntryUndefined.php');
  301. return new PelEntryUndefined($tag, $data->getBytes());
  302.  
  303. default:
  304. throw new PelException('Unsupported format: %s',
  305. PelFormat::getName($format));
  306. }
  307. }
  308. }
  309.  
  310.  
  311. /**
  312. * Return the tag of this entry.
  313. *
  314. * @return PelTag the tag of this entry.
  315. */
  316. function getTag() {
  317. return $this->tag;
  318. }
  319.  
  320.  
  321. /**
  322. * Return the format of this entry.
  323. *
  324. * @return PelFormat the format of this entry.
  325. */
  326. function getFormat() {
  327. return $this->format;
  328. }
  329.  
  330.  
  331. /**
  332. * Return the number of components of this entry.
  333. *
  334. * @return int the number of components of this entry.
  335. */
  336. function getComponents() {
  337. return $this->components;
  338. }
  339.  
  340.  
  341. /**
  342. * Turn this entry into bytes.
  343. *
  344. * @param PelByteOrder the desired byte order, which must be either
  345. * {@link Convert::LITTLE_ENDIAN} or {@link Convert::BIG_ENDIAN}.
  346. *
  347. * @return string bytes representing this entry.
  348. */
  349. function getBytes($o) {
  350. return $this->bytes;
  351. }
  352.  
  353. /**
  354. * Get the value of this entry as text.
  355. *
  356. * The value will be returned in a format suitable for presentation,
  357. * e.g., rationals will be returned as 'x/y', ASCII strings will be
  358. * returned as themselves etc.
  359. *
  360. * @param boolean some values can be returned in a long or more
  361. * brief form, and this parameter controls that.
  362. *
  363. * @return string the value as text.
  364. */
  365. abstract function getText($brief = false);
  366.  
  367.  
  368. /**
  369. /**
  370. * Get the value of this entry.
  371. *
  372. * The value returned will generally be the same as the one supplied
  373. * to the constructor or with {@link setValue()}. For a formatted
  374. * version of the value, one should use {@link getText()} instead.
  375. *
  376. * @return mixed the unformatted value.
  377. */
  378. abstract function getValue();
  379.  
  380.  
  381. /**
  382. /**
  383. * Set the value of this entry.
  384. *
  385. * The value should be in the same format as for the constructor.
  386. *
  387. * @param mixed the new value.
  388. *
  389. * @abstract
  390. */
  391. function setValue($value) {
  392. /* This (fake) abstract method is here to make it possible for the
  393. * documentation to refer to PelEntry::setValue().
  394. *
  395. * It cannot declared abstract in the proper PHP way, for then PHP
  396. * wont allow subclasses to define it with two arguments (which is
  397. * what PelEntryCopyright does).
  398. */
  399. throw new PelException('setValue() is abstract.');
  400. }
  401.  
  402.  
  403. /**
  404. * Turn this entry into a string.
  405. *
  406. * @return string a string representation of this entry. This is
  407. * mostly for debugging.
  408. */
  409. function __toString() {
  410. $str = Pel::fmt(" Tag: 0x%04X (%s)\n",
  411. $this->tag, PelTag::getName($this->tag));
  412. $str .= Pel::fmt(" Format : %d (%s)\n",
  413. $this->format, PelFormat::getName($this->format));
  414. $str .= Pel::fmt(" Components: %d\n", $this->components);
  415. if ($this->getTag() != PelTag::MAKER_NOTE)
  416. $str .= Pel::fmt(" Value : %s\n", print_r($this->getValue(), true));
  417. $str .= Pel::fmt(" Text : %s\n", $this->getText());
  418. return $str;
  419. }
  420. }
  421.  
  422. ?>

SourceForge.net Logo Documentation generated on Fri, 18 Feb 2005 01:43:11 +0100 by phpDocumentor 1.3.0RC3