lsolesen\pel\PelIfd::load PHP Method

load() public method

Load data into a Image File Directory (IFD).
public load ( lsolesen\pel\PelDataWindow $d, integer $offset )
$d lsolesen\pel\PelDataWindow the data window that will provide the data.
$offset integer the offset within the window where the directory will be found.
    public 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.');
        }
    }