Source for file PelTiff.php

Documentation is available at PelTiff.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 Martin Geisler <gimpster@users.sourceforge.net>
  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. /* PelTiff.php,v 1.10 2004/07/21 16:18:02 gimpster Exp */
  25.  
  26.  
  27. /**
  28. * Classes for dealing with TIFF data.
  29. *
  30. * @author Martin Geisler <gimpster@users.sourceforge.net>
  31. * @version 1.10
  32. * @date 2004/07/21 16:18:02
  33. * @license http://www.gnu.org/licenses/gpl.html GNU General Public
  34. * License (GPL)
  35. * @package PEL
  36. */
  37.  
  38. /**#@+ Required class definitions. */
  39. ('PelDataWindow.php');
  40. require_once('PelIfd.php');
  41. require_once('Pel.php');
  42. /**#@-*/ * Class for handling TIFF data.
  43. *
  44. * EXIF data is actually an extension of the TIFF file format. TIFF
  45. * images consist of a number of {@link PelIfd Image File Directories}
  46. * (IFDs), each containing a number of {@link PelEntry entries}. The
  47. * IFDs are linked to each other --- one can get hold of the first one
  48. * with the {@link getIfd()} method.
  49. *
  50. * To parse a TIFF image for EXIF data one would do:
  51. *
  52. * <code>
  53. * $tiff = new PelTiff($data);
  54. * $ifd0 = $tiff->getIfd();
  55. * $exif = $ifd0->getSubIfd(PelTag::EXIF_IFD_POINTER);
  56. * $ifd1 = $ifd0->getNextIfd();
  57. * </code>
  58. *
  59. * Should one have some image data of an unknown type, then the {@link
  60. * PelTiff::isValid()} function is handy: it will quickly test if the
  61. * data could be valid TIFF data. The {@link PelJpeg::isValid()}
  62. * function does the same for JPEG images.
  63. *
  64. * @author Martin Geisler <gimpster@users.sourceforge.net>
  65. * @package PEL
  66. */
  67. class PelTiff {
  68.  
  69. /**
  70. * TIFF header.
  71. *
  72. * This must follow after the two bytes indicating the byte order.
  73. */
  74. const TIFF_HEADER = 0x002A;
  75.  
  76. /**
  77. * The first Image File Directory, if any.
  78. *
  79. * @var PelIfd
  80. */
  81. private $ifd = null;
  82.  
  83.  
  84. /**
  85. * Construct a new object for holding TIFF data.
  86. *
  87. * The new object will be empty, containing no {@link PelIfd}. Use
  88. * the {@link setIfd()} method to set the IFD explictly, or use the
  89. * {@link load()} method to load TIFF data from a {@link }
  90. * PelDataWindow}.
  91. */
  92. function __construct() {
  93.  
  94. }
  95.  
  96. /**
  97. * Load TIFF data.
  98. *
  99. * The data given will be parsed and an internal tree representation
  100. * will be built. If the data cannot be parsed correctly, a {@link }
  101. * PelInvalidDataException} is thrown, explaining the problem.
  102. *
  103. * @param PelDataWindow the data from which the object will be
  104. * constructed. This should be valid TIFF data, coming either
  105. * directly from a TIFF image or from the EXIF data in a JPEG image.
  106. */
  107. function load(PelDataWindow $d) {
  108. Pel::debug('Parsing %d bytes of TIFF data...', $d->getSize());
  109.  
  110. /* There must be at least 8 bytes available: 2 bytes for the byte
  111. * order, 2 bytes for the TIFF header, and 4 bytes for the offset
  112. * to the first IFD. */
  113. if ($d->getSize() < 8)
  114. throw new PelInvalidDataException('Expected at least 8 bytes of TIFF ' .
  115. 'data, found just %d bytes.',
  116. $d->getSize());
  117.  
  118. /* Byte order */
  119. if ($d->strcmp(0, 'II')) {
  120. Pel::debug('Found Intel byte order');
  121. $d->setByteOrder(PelConvert::LITTLE_ENDIAN);
  122. } elseif ($d->strcmp(0, 'MM')) {
  123. Pel::debug('Found Motorola byte order');
  124. $d->setByteOrder(PelConvert::BIG_ENDIAN);
  125. } else {
  126. throw new PelInvalidDataException('Unknown byte order found in TIFF ' .
  127. 'data: 0x%2X%2X',
  128. $d->getByte(0), $d->getByte(1));
  129. }
  130. /* Verify the TIFF header */
  131. if ($d->getShort(2) != self::TIFF_HEADER)
  132. throw new PelInvalidDataException('Missing TIFF magic value.');
  133.  
  134. /* IFD 0 offset */
  135. $offset = $d->getLong(4);
  136. Pel::debug('First IFD at offset %d.', $offset);
  137.  
  138. if ($offset > 0) {
  139. /* Parse the first IFD, this will automatically parse the
  140. * following IFDs and any sub IFDs. */
  141. $this->ifd = new PelIfd();
  142. $this->ifd->load($d, $offset);
  143. }
  144. }
  145.  
  146.  
  147. /**
  148. * Load data from a file into a TIFF object.
  149. *
  150. * @param string the filename. This must be a readable file.
  151. */
  152. function loadFile($filename) {
  153. $this->load(new PelDataWindow(file_get_contents($filename)));
  154. }
  155.  
  156.  
  157. /**
  158. * Set the first IFD.
  159. *
  160. * @param PelIfd the new first IFD.
  161. */
  162. function setIfd(PelIfd $ifd) {
  163. $this->ifd = $ifd;
  164. }
  165.  
  166.  
  167. /**
  168. * Return the first IFD.
  169. *
  170. * @return PelIfd the first IFD contained in the TIFF data, if any.
  171. * If there is no IFD null will be returned.
  172. */
  173. function getIfd() {
  174. return $this->ifd;
  175. }
  176.  
  177.  
  178. /**
  179. * Turn this object into bytes.
  180. *
  181. * TIFF images can have {@link PelConvert::LITTLE_ENDIAN}
  182. * little-endian} or {@link PelConvert::BIG_ENDIAN big-endian} byte
  183. * order, and so this method takes an argument specifying that.
  184. *
  185. * @param PelByteOrder the desired byte order of the TIFF data.
  186. * This should be one of {@link PelConvert::LITTLE_ENDIAN} or {@link }
  187. * PelConvert::BIG_ENDIAN}.
  188. *
  189. * @return string the bytes representing this object.
  190. */
  191. function getBytes($order = PelConvert::LITTLE_ENDIAN) {
  192. if ($order == PelConvert::LITTLE_ENDIAN)
  193. $bytes = 'II';
  194. else
  195. $bytes = 'MM';
  196. /* TIFF magic number --- fixed value. */
  197. $bytes .= PelConvert::shortToBytes(self::TIFF_HEADER, $order);
  198.  
  199. if ($this->ifd != null) {
  200. /* IFD 0 offset. We will always start IDF 0 at an offset of 8
  201. * bytes (2 bytes for byte order, another 2 bytes for the TIFF
  202. * header, and 4 bytes for the IFD 0 offset make 8 bytes
  203. * together).
  204. */
  205. $bytes .= PelConvert::longToBytes(8, $order);
  206. /* The argument specifies the offset of this IFD. The IFD will
  207. * use this to calculate offsets from the entries to their data,
  208. * all those offsets are absolute offsets counted from the
  209. * beginning of the data. */
  210. $bytes .= $this->ifd->getBytes(8, $order);
  211. } else {
  212. $bytes .= PelConvert::longToBytes(0, $order);
  213. }
  214.  
  215. return $bytes;
  216. }
  217.  
  218.  
  219. /**
  220. * Return a string representation of this object.
  221. *
  222. * @return string a string describing this object. This is mostly useful
  223. * for debugging.
  224. */
  225. function __toString() {
  226. $str = Pel::fmt("Dumping TIFF data...\n");
  227. if ($this->ifd != null)
  228. $str .= $this->ifd->__toString();
  229.  
  230. return $str;
  231. }
  232.  
  233.  
  234. /**
  235. * Check if data is valid TIFF data.
  236. *
  237. * This will read just enough data from the data window to determine
  238. * if the data could be a valid TIFF data. This means that the
  239. * check is more like a heuristic than a rigorous check.
  240. *
  241. * @param PelDataWindow the bytes that will be examined.
  242. *
  243. * @return boolean true if the data looks like valid TIFF data,
  244. * false otherwise.
  245. *
  246. * @see PelJpeg::isValid()
  247. */
  248. static function isValid(PelDataWindow $d) {
  249. /* First check that we have enough data. */
  250. if ($d->getSize() < 8)
  251. return false;
  252.  
  253. /* Byte order */
  254. if ($d->strcmp(0, 'II')) {
  255. $d->setByteOrder(PelConvert::LITTLE_ENDIAN);
  256. } elseif ($d->strcmp(0, 'MM')) {
  257. Pel::debug('Found Motorola byte order');
  258. $d->setByteOrder(PelConvert::BIG_ENDIAN);
  259. } else {
  260. return false;
  261. }
  262. /* Verify the TIFF header */
  263. return $d->getShort(2) == self::TIFF_HEADER;
  264. }
  265.  
  266. }

SourceForge.net Logo Documentation generated on Wed, 21 Jul 2004 19:13:25 +0200 by phpDocumentor 1.3.0RC3