Exemple #1
0
 /**
  * Load TIFF data.
  *
  * The data given will be parsed and an internal tree representation
  * will be built.  If the data cannot be parsed correctly, a {@link
  * PelInvalidDataException} is thrown, explaining the problem.
  *
  * @param PelDataWindow the data from which the object will be
  * constructed.  This should be valid TIFF data, coming either
  * directly from a TIFF image or from the Exif data in a JPEG image.
  */
 function load(PelDataWindow $d)
 {
     Pel::debug('Parsing %d bytes of TIFF data...', $d->getSize());
     /* There must be at least 8 bytes available: 2 bytes for the byte
      * order, 2 bytes for the TIFF header, and 4 bytes for the offset
      * to the first IFD. */
     if ($d->getSize() < 8) {
         throw new PelInvalidDataException('Expected at least 8 bytes of TIFF ' . 'data, found just %d bytes.', $d->getSize());
     }
     /* Byte order */
     if ($d->strcmp(0, 'II')) {
         Pel::debug('Found Intel byte order');
         $d->setByteOrder(PelConvert::LITTLE_ENDIAN);
     } elseif ($d->strcmp(0, 'MM')) {
         Pel::debug('Found Motorola byte order');
         $d->setByteOrder(PelConvert::BIG_ENDIAN);
     } else {
         throw new PelInvalidDataException('Unknown byte order found in TIFF ' . 'data: 0x%2X%2X', $d->getByte(0), $d->getByte(1));
     }
     /* Verify the TIFF header */
     if ($d->getShort(2) != self::TIFF_HEADER) {
         throw new PelInvalidDataException('Missing TIFF magic value.');
     }
     /* IFD 0 offset */
     $offset = $d->getLong(4);
     Pel::debug('First IFD at offset %d.', $offset);
     if ($offset > 0) {
         /* Parse the first IFD, this will automatically parse the
          * following IFDs and any sub IFDs. */
         $this->ifd = new PelIfd(PelIfd::IFD0);
         $this->ifd->load($d, $offset);
     }
 }
Exemple #2
0
 /**
  * Load data into a Image File Directory (IFD).
  *
  * @param PelDataWindow the data window that will provide the data.
  *
  * @param int the offset within the window where the directory will
  * be found.
  */
 function load(PelDataWindow $d, $offset)
 {
     $thumb_offset = 0;
     $thumb_length = 0;
     Pel::debug('Constructing IFD at offset %d from %d bytes...', $offset, $d->getSize());
     /* Read the number of entries */
     $n = $d->getShort($offset);
     Pel::debug('Loading %d entries...', $n);
     $offset += 2;
     /* Check if we have enough data. */
     if ($offset + 12 * $n > $d->getSize()) {
         $n = floor(($offset - $d->getSize()) / 12);
         Pel::maybeThrow(new PelIfdException('Adjusted to: %d.', $n));
     }
     for ($i = 0; $i < $n; $i++) {
         // TODO: increment window start instead of using offsets.
         $tag = $d->getShort($offset + 12 * $i);
         Pel::debug('Loading entry with tag 0x%04X: %s (%d of %d)...', $tag, PelTag::getName($this->type, $tag), $i + 1, $n);
         switch ($tag) {
             case PelTag::EXIF_IFD_POINTER:
             case PelTag::GPS_INFO_IFD_POINTER:
             case PelTag::INTEROPERABILITY_IFD_POINTER:
                 $o = $d->getLong($offset + 12 * $i + 8);
                 Pel::debug('Found sub IFD at offset %d', $o);
                 /* Map tag to IFD type. */
                 if ($tag == PelTag::EXIF_IFD_POINTER) {
                     $type = PelIfd::EXIF;
                 } elseif ($tag == PelTag::GPS_INFO_IFD_POINTER) {
                     $type = PelIfd::GPS;
                 } elseif ($tag == PelTag::INTEROPERABILITY_IFD_POINTER) {
                     $type = PelIfd::INTEROPERABILITY;
                 }
                 $this->sub[$type] = new PelIfd($type);
                 $this->sub[$type]->load($d, $o);
                 break;
             case PelTag::JPEG_INTERCHANGE_FORMAT:
                 $thumb_offset = $d->getLong($offset + 12 * $i + 8);
                 $this->safeSetThumbnail($d, $thumb_offset, $thumb_length);
                 break;
             case PelTag::JPEG_INTERCHANGE_FORMAT_LENGTH:
                 $thumb_length = $d->getLong($offset + 12 * $i + 8);
                 $this->safeSetThumbnail($d, $thumb_offset, $thumb_length);
                 break;
             default:
                 $format = $d->getShort($offset + 12 * $i + 2);
                 $components = $d->getLong($offset + 12 * $i + 4);
                 /* The data size.  If bigger than 4 bytes, the actual data is
                  * not in the entry but somewhere else, with the offset stored
                  * in the entry.
                  */
                 $s = PelFormat::getSize($format) * $components;
                 if ($s > 0) {
                     $doff = $offset + 12 * $i + 8;
                     if ($s > 4) {
                         $doff = $d->getLong($doff);
                     }
                     $data = $d->getClone($doff, $s);
                 } else {
                     $data = new PelDataWindow();
                 }
                 try {
                     $entry = $this->newEntryFromData($tag, $format, $components, $data);
                     $this->addEntry($entry);
                 } catch (PelException $e) {
                     /* Throw the exception when running in strict mode, store
                      * otherwise. */
                     Pel::maybeThrow($e);
                 }
                 /* The format of the thumbnail is stored in this tag. */
                 //         TODO: handle TIFF thumbnail.
                 //         if ($tag == PelTag::COMPRESSION) {
                 //           $this->thumb_format = $data->getShort();
                 //         }
                 break;
         }
     }
     /* Offset to next IFD */
     $o = $d->getLong($offset + 12 * $n);
     Pel::debug('Current offset is %d, link at %d points to %d.', $offset, $offset + 12 * $n, $o);
     if ($o > 0) {
         /* Sanity check: we need 6 bytes  */
         if ($o > $d->getSize() - 6) {
             Pel::maybeThrow(new PelIfdException('Bogus offset to next IFD: ' . '%d > %d!', $o, $d->getSize() - 6));
         } else {
             if ($this->type == PelIfd::IFD1) {
                 // IFD1 shouldn't link further...
                 Pel::maybeThrow(new PelIfdException('IFD1 links to another IFD!'));
             }
             $this->next = new PelIfd(PelIfd::IFD1);
             $this->next->load($d, $o);
         }
     } else {
         Pel::debug('Last IFD.');
     }
 }