/** * Get the value of an entry as text. * * The value will be returned in a format suitable for presentation, * e.g., rationals will be returned as 'x/y', ASCII strings will be * returned as themselves etc. * * @param boolean some values can be returned in a long or more * brief form, and this parameter controls that. * * @return string the value as text. */ function getText($brief = false) { if (isset($this->value[0])) { $v = $this->value[0]; } switch ($this->tag) { case PelTag::FNUMBER: //CC (e->components, 1, v); return Pel::fmt('f/%.01f', $v[0] / $v[1]); case PelTag::APERTURE_VALUE: //CC (e->components, 1, v); //if (!v_rat.denominator) return (NULL); return Pel::fmt('f/%.01f', pow(2, $v[0] / $v[1] / 2)); case PelTag::FOCAL_LENGTH: //CC (e->components, 1, v); //if (!v_rat.denominator) return (NULL); return Pel::fmt('%.1f mm', $v[0] / $v[1]); case PelTag::SUBJECT_DISTANCE: //CC (e->components, 1, v); //if (!v_rat.denominator) return (NULL); return Pel::fmt('%.1f m', $v[0] / $v[1]); case PelTag::EXPOSURE_TIME: //CC (e->components, 1, v); //if (!v_rat.denominator) return (NULL); if ($v[0] / $v[1] < 1) { return Pel::fmt('1/%d sec.', $v[1] / $v[0]); } else { return Pel::fmt('%d sec.', $v[0] / $v[1]); } case PelTag::GPS_LATITUDE: case PelTag::GPS_LONGITUDE: $degrees = $this->value[0][0] / $this->value[0][1]; $minutes = $this->value[1][0] / $this->value[1][1]; $seconds = $this->value[2][0] / $this->value[2][1]; return sprintf('%s° %s\' %s" (%.2f°)', $degrees, $minutes, $seconds, $degrees + $minutes / 60 + $seconds / 3600); default: return parent::getText($brief); } }
/** * Make a new entry from a bunch of bytes. * * This method will create the proper subclass of {@link PelEntry} * corresponding to the {@link PelTag} and {@link PelFormat} given. * The entry will be initialized with the data given. * * Please note that the data you pass to this method should come * from an image, that is, it should be raw bytes. If instead you * want to create an entry for holding, say, an short integer, then * create a {@link PelEntryShort} object directly and load the data * into it. * * A {@link PelUnexpectedFormatException} is thrown if a mismatch is * discovered between the tag and format, and likewise a {@link * PelWrongComponentCountException} is thrown if the number of * components does not match the requirements of the tag. The * requirements for a given tag (if any) can be found in the * documentation for {@link PelTag}. * * @param PelTag the tag of the entry. * * @param PelFormat the format of the entry. * * @param int the components in the entry. * * @param PelDataWindow the data which will be used to construct the * entry. * * @return PelEntry a newly created entry, holding the data given. */ function newEntryFromData($tag, $format, $components, PelDataWindow $data) { /* First handle tags for which we have a specific PelEntryXXX * class. */ switch ($this->type) { case self::IFD0: case self::IFD1: case self::EXIF: case self::INTEROPERABILITY: switch ($tag) { case PelTag::DATE_TIME: case PelTag::DATE_TIME_ORIGINAL: case PelTag::DATE_TIME_DIGITIZED: if ($format != PelFormat::ASCII) { throw new PelUnexpectedFormatException($this->type, $tag, $format, PelFormat::ASCII); } if ($components != 20) { throw new PelWrongComponentCountException($this->type, $tag, $components, 20); } // TODO: handle timezones. return new PelEntryTime($tag, $data->getBytes(0, -1), PelEntryTime::EXIF_STRING); case PelTag::COPYRIGHT: if ($format != PelFormat::ASCII) { throw new PelUnexpectedFormatException($this->type, $tag, $format, PelFormat::ASCII); } $v = explode("", trim($data->getBytes(), ' ')); return new PelEntryCopyright($v[0], $v[1]); case PelTag::EXIF_VERSION: case PelTag::FLASH_PIX_VERSION: case PelTag::INTEROPERABILITY_VERSION: if ($format != PelFormat::UNDEFINED) { throw new PelUnexpectedFormatException($this->type, $tag, $format, PelFormat::UNDEFINED); } return new PelEntryVersion($tag, $data->getBytes() / 100); case PelTag::USER_COMMENT: if ($format != PelFormat::UNDEFINED) { throw new PelUnexpectedFormatException($this->type, $tag, $format, PelFormat::UNDEFINED); } if ($data->getSize() < 8) { return new PelEntryUserComment(); } else { return new PelEntryUserComment($data->getBytes(8), rtrim($data->getBytes(0, 8))); } case PelTag::XP_TITLE: case PelTag::XP_COMMENT: case PelTag::XP_AUTHOR: case PelTag::XP_KEYWORDS: case PelTag::XP_SUBJECT: if ($format != PelFormat::BYTE) { throw new PelUnexpectedFormatException($this->type, $tag, $format, PelFormat::BYTE); } $v = ''; for ($i = 0; $i < $components; $i++) { $b = $data->getByte($i); /* Convert the byte to a character if it is non-null --- * information about the character encoding of these entries * would be very nice to have! So far my tests have shown * that characters in the Latin-1 character set are stored in * a single byte followed by a NULL byte. */ if ($b != 0) { $v .= chr($b); } } return new PelEntryWindowsString($tag, $v); } case self::GPS: default: /* Then handle the basic formats. */ switch ($format) { case PelFormat::BYTE: $v = new PelEntryByte($tag); for ($i = 0; $i < $components; $i++) { $v->addNumber($data->getByte($i)); } return $v; case PelFormat::SBYTE: $v = new PelEntrySByte($tag); for ($i = 0; $i < $components; $i++) { $v->addNumber($data->getSByte($i)); } return $v; case PelFormat::ASCII: return new PelEntryAscii($tag, $data->getBytes(0, -1)); case PelFormat::SHORT: $v = new PelEntryShort($tag); for ($i = 0; $i < $components; $i++) { $v->addNumber($data->getShort($i * 2)); } return $v; case PelFormat::SSHORT: $v = new PelEntrySShort($tag); for ($i = 0; $i < $components; $i++) { $v->addNumber($data->getSShort($i * 2)); } return $v; case PelFormat::LONG: $v = new PelEntryLong($tag); for ($i = 0; $i < $components; $i++) { $v->addNumber($data->getLong($i * 4)); } return $v; case PelFormat::SLONG: $v = new PelEntrySLong($tag); for ($i = 0; $i < $components; $i++) { $v->addNumber($data->getSLong($i * 4)); } return $v; case PelFormat::RATIONAL: $v = new PelEntryRational($tag); for ($i = 0; $i < $components; $i++) { $v->addNumber($data->getRational($i * 8)); } return $v; case PelFormat::SRATIONAL: $v = new PelEntrySRational($tag); for ($i = 0; $i < $components; $i++) { $v->addNumber($data->getSRational($i * 8)); } return $v; case PelFormat::UNDEFINED: return new PelEntryUndefined($tag, $data->getBytes()); default: throw new PelException('Unsupported format: %s', PelFormat::getName($format)); } } }