/** * 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; }
/** * Turn this JPEG object into bytes. * * The bytes returned by this method is ready to be stored in a file * as a valid JPEG image. Use the {@link saveFile()} convenience * method to do this. * * @return string bytes representing this JPEG object, including all * its sections and their associated data. */ function getBytes() { $bytes = ''; foreach ($this->sections as $section) { $m = $section[0]; $c = $section[1]; /* Write the marker */ $bytes .= "ÿ" . PelJpegMarker::getBytes($m); /* Skip over empty markers. */ if ($m == PelJpegMarker::SOI || $m == PelJpegMarker::EOI) { continue; } $data = $c->getBytes(); $size = strlen($data) + 2; $bytes .= PelConvert::shortToBytes($size, PelConvert::BIG_ENDIAN); $bytes .= $data; /* In case of SOS, we need to write the JPEG data. */ if ($m == PelJpegMarker::SOS) { $bytes .= $this->jpeg_data->getBytes(); } } return $bytes; }
/** * Load and parse data. * * This will load the comment from the data window passed. */ function load(PelDataWindow $d) { $this->comment = $d->getBytes(); }
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); }