lsolesen\pel\PelIfd::getBytes PHP Method

getBytes() public method

This directory will be turned into a byte string, with the specified byte order. The offsets will be calculated from the offset given.
public getBytes ( integer $offset, PelByteOrder $order )
$offset integer the offset of the first byte of this directory.
$order 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}.
    public 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;
    }