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

Documentation generated on Thu, 05 May 2011 07:19:30 +0200 by phpDocumentor 1.4.3