Beispiel #1
0
 /**
  * Load and parse Exif data.
  *
  * This will populate the object with Exif data, contained as a
  * {@link PelTiff} object. This TIFF object can be accessed with
  * the {@link getTiff()} method.
  *
  * @param PelDataWindow $d
  */
 public function load(PelDataWindow $d)
 {
     Pel::debug('Parsing %d bytes of Exif data...', $d->getSize());
     /* There must be at least 6 bytes for the Exif header. */
     if ($d->getSize() < 6) {
         throw new PelInvalidDataException('Expected at least 6 bytes of Exif ' . 'data, found just %d bytes.', $d->getSize());
     }
     /* Verify the Exif header */
     if ($d->strcmp(0, self::EXIF_HEADER)) {
         $d->setWindowStart(strlen(self::EXIF_HEADER));
     } else {
         throw new PelInvalidDataException('Exif header not found.');
     }
     /* The rest of the data is TIFF data. */
     $this->tiff = new PelTiff();
     $this->tiff->load($d);
 }
Beispiel #2
0
 /**
  * Turn this directory into bytes.
  *
  * This directory will be turned into a byte string, with the
  * specified byte order.  The offsets will be calculated from the
  * offset given.
  *
  * @param int the offset of the first byte of this directory.
  *
  * @param PelByteOrder the byte order that should be used when
  * turning integers into bytes.  This should be one of {@link
  * PelConvert::LITTLE_ENDIAN} and {@link PelConvert::BIG_ENDIAN}.
  */
 function getBytes($offset, $order)
 {
     $bytes = '';
     $extra_bytes = '';
     Pel::debug('Bytes from IDF will start at offset %d within Exif data', $offset);
     $n = count($this->entries) + count($this->sub);
     if ($this->thumb_data != null) {
         /* We need two extra entries for the thumbnail offset and
          * length. */
         $n += 2;
     }
     $bytes .= PelConvert::shortToBytes($n, $order);
     /* Initialize offset of extra data.  This included the bytes
      * preceding this IFD, the bytes needed for the count of entries,
      * the entries themselves (and sub entries), the extra data in the
      * entries, and the IFD link.
      */
     $end = $offset + 2 + 12 * $n + 4;
     foreach ($this->entries as $tag => $entry) {
         /* Each entry is 12 bytes long. */
         $bytes .= PelConvert::shortToBytes($entry->getTag(), $order);
         $bytes .= PelConvert::shortToBytes($entry->getFormat(), $order);
         $bytes .= PelConvert::longToBytes($entry->getComponents(), $order);
         /*
          * Size? If bigger than 4 bytes, the actual data is not in
          * the entry but somewhere else.
          */
         $data = $entry->getBytes($order);
         $s = strlen($data);
         if ($s > 4) {
             Pel::debug('Data size %d too big, storing at offset %d instead.', $s, $end);
             $bytes .= PelConvert::longToBytes($end, $order);
             $extra_bytes .= $data;
             $end += $s;
         } else {
             Pel::debug('Data size %d fits.', $s);
             /* Copy data directly, pad with NULL bytes as necessary to
              * fill out the four bytes available.*/
             $bytes .= $data . str_repeat(chr(0), 4 - $s);
         }
     }
     if ($this->thumb_data != null) {
         Pel::debug('Appending %d bytes of thumbnail data at %d', $this->thumb_data->getSize(), $end);
         // TODO: make PelEntry a class that can be constructed with
         // arguments corresponding to the newt four lines.
         $bytes .= PelConvert::shortToBytes(PelTag::JPEG_INTERCHANGE_FORMAT_LENGTH, $order);
         $bytes .= PelConvert::shortToBytes(PelFormat::LONG, $order);
         $bytes .= PelConvert::longToBytes(1, $order);
         $bytes .= PelConvert::longToBytes($this->thumb_data->getSize(), $order);
         $bytes .= PelConvert::shortToBytes(PelTag::JPEG_INTERCHANGE_FORMAT, $order);
         $bytes .= PelConvert::shortToBytes(PelFormat::LONG, $order);
         $bytes .= PelConvert::longToBytes(1, $order);
         $bytes .= PelConvert::longToBytes($end, $order);
         $extra_bytes .= $this->thumb_data->getBytes();
         $end += $this->thumb_data->getSize();
     }
     /* Find bytes from sub IFDs. */
     $sub_bytes = '';
     foreach ($this->sub as $type => $sub) {
         if ($type == PelIfd::EXIF) {
             $tag = PelTag::EXIF_IFD_POINTER;
         } elseif ($type == PelIfd::GPS) {
             $tag = PelTag::GPS_INFO_IFD_POINTER;
         } elseif ($type == PelIfd::INTEROPERABILITY) {
             $tag = PelTag::INTEROPERABILITY_IFD_POINTER;
         }
         /* Make an aditional entry with the pointer. */
         $bytes .= PelConvert::shortToBytes($tag, $order);
         /* Next the format, which is always unsigned long. */
         $bytes .= PelConvert::shortToBytes(PelFormat::LONG, $order);
         /* There is only one component. */
         $bytes .= PelConvert::longToBytes(1, $order);
         $data = $sub->getBytes($end, $order);
         $s = strlen($data);
         $sub_bytes .= $data;
         $bytes .= PelConvert::longToBytes($end, $order);
         $end += $s;
     }
     /* Make link to next IFD, if any*/
     if ($this->isLastIFD()) {
         $link = 0;
     } else {
         $link = $end;
     }
     Pel::debug('Link to next IFD: %d', $link);
     $bytes .= PelConvert::longtoBytes($link, $order);
     $bytes .= $extra_bytes . $sub_bytes;
     if (!$this->isLastIfd()) {
         $bytes .= $this->next->getBytes($end, $order);
     }
     return $bytes;
 }
Beispiel #3
0
 /**
  * Check if data is valid TIFF data.
  *
  * This will read just enough data from the data window to determine
  * if the data could be a valid TIFF data. This means that the
  * check is more like a heuristic than a rigorous check.
  *
  * @param PelDataWindow $d
  *            the bytes that will be examined.
  *
  * @return boolean true if the data looks like valid TIFF data,
  *         false otherwise.
  *
  * @see PelJpeg::isValid()
  */
 public static function isValid(PelDataWindow $d)
 {
     /* First check that we have enough data. */
     if ($d->getSize() < 8) {
         return false;
     }
     /* Byte order */
     if ($d->strcmp(0, 'II')) {
         $d->setByteOrder(PelConvert::LITTLE_ENDIAN);
     } elseif ($d->strcmp(0, 'MM')) {
         Pel::debug('Found Motorola byte order');
         $d->setByteOrder(PelConvert::BIG_ENDIAN);
     } else {
         return false;
     }
     /* Verify the TIFF header */
     return $d->getShort(2) == self::TIFF_HEADER;
 }
 /**
  * Load and parse data.
  *
  * This will load the comment from the data window passed.
  */
 function load(PelDataWindow $d)
 {
     $this->comment = $d->getBytes();
 }
Beispiel #5
0
 /**
  * Test data to see if it could be a valid JPEG image.
  *
  * The function will only look at the first few bytes of the data,
  * and try to determine if it could be a valid JPEG image based on
  * those bytes.  This means that the check is more like a heuristic
  * than a rigorous check.
  *
  * @param PelDataWindow the bytes that will be checked.
  *
  * @return boolean true if the bytes look like the beginning of a
  * JPEG image, false otherwise.
  *
  * @see PelTiff::isValid()
  */
 static function isValid(PelDataWindow $d)
 {
     /* JPEG data is stored in big-endian format. */
     $d->setByteOrder(PelConvert::BIG_ENDIAN);
     for ($i = 0; $i < 7; $i++) {
         if ($d->getByte($i) != 0xff) {
             break;
         }
     }
     return $d->getByte($i) == PelJpegMarker::SOI;
 }
Beispiel #6
0
 function testReadBigIntegers()
 {
     $window = new PelDataWindow("‰«Íï", PelConvert::BIG_ENDIAN);
     $this->assertEqual($window->getSize(), 4);
     $this->assertEqual($window->getBytes(), "‰«Íï");
     $this->assertEqual($window->getByte(0), 0x89);
     $this->assertEqual($window->getByte(1), 0xab);
     $this->assertEqual($window->getByte(2), 0xcd);
     $this->assertEqual($window->getByte(3), 0xef);
     $this->assertEqual($window->getShort(0), 0x89ab);
     $this->assertEqual($window->getShort(1), 0xabcd);
     $this->assertEqual($window->getShort(2), 0xcdef);
     $this->assertEqual($window->getLong(0), 0x89abcdef);
     $window->setByteOrder(PelConvert::LITTLE_ENDIAN);
     $this->assertEqual($window->getSize(), 4);
     $this->assertEqual($window->getBytes(), "‰«Íï");
     $this->assertEqual($window->getByte(0), 0x89);
     $this->assertEqual($window->getByte(1), 0xab);
     $this->assertEqual($window->getByte(2), 0xcd);
     $this->assertEqual($window->getByte(3), 0xef);
     $this->assertEqual($window->getShort(0), 0xab89);
     $this->assertEqual($window->getShort(1), 0xcdab);
     $this->assertEqual($window->getShort(2), 0xefcd);
     $this->assertEqual($window->getLong(0), 0xefcdab89);
 }