* @version $Revision: 419 $ * @date $Date: 2006-02-20 17:22:36 +0100 (Mon, 20 Feb 2006) $ * @license http://www.gnu.org/licenses/gpl.html GNU General Public * License (GPL) * @package PEL */ /**#@+ Required class definitions. */ require_once('PelEntryLong.php'); /**#@-*/ /** * Class for holding unsigned rational numbers. * * This class can hold rational numbers, consisting of a numerator and * denominator both of which are of type unsigned long. Each rational * is represented by an array with just two entries: the numerator and * the denominator, in that order. * * The class can hold either just a single rational or an array of * rationals. The class will be used to manipulate any of the Exif * tags which can have format {@link PelFormat::RATIONAL} like in this * example: * * * $resolution = $ifd->getEntry(PelTag::X_RESOLUTION); * $resolution->setValue(array(1, 300)); * * * Here the x-resolution is adjusted to 1/300, which will be 300 DPI, * unless the {@link PelTag::RESOLUTION_UNIT resolution unit} is set * to something different than 2 which means inches. * * @author Martin Geisler * @package PEL */ class PelEntryRational extends PelEntryLong { /** * Make a new entry that can hold an unsigned rational. * * @param PelTag the tag which this entry represents. This should * be one of the constants defined in {@link PelTag}, e.g., {@link * PelTag::X_RESOLUTION}, or any other tag which can have format * {@link PelFormat::RATIONAL}. * * @param array $value... the rational(s) that this entry will * represent. The arguments passed must obey the same rules as the * argument to {@link setValue}, namely that each argument should be * an array with two entries, both of which must be within range of * an unsigned long (32 bit), that is between 0 and 4294967295 * (inclusive). If not, then a {@link PelOverflowException} will be * thrown. */ function __construct($tag /* $value... */) { $this->tag = $tag; $this->format = PelFormat::RATIONAL; $this->dimension = 2; $this->min = 0; $this->max = 4294967295; $value = func_get_args(); array_shift($value); $this->setValueArray($value); } /** * Format a rational number. * * The rational will be returned as a string with a slash '/' * between the numerator and denominator. * * @param array the rational which will be formatted. * * @param boolean not used. * * @return string the rational formatted as a string suitable for * display. */ function formatNumber($number, $brief = false) { return $number[0] . '/' . $number[1]; } /** * 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); } } } /** * Class for holding signed rational numbers. * * This class can hold rational numbers, consisting of a numerator and * denominator both of which are of type unsigned long. Each rational * is represented by an array with just two entries: the numerator and * the denominator, in that order. * * The class can hold either just a single rational or an array of * rationals. The class will be used to manipulate any of the Exif * tags which can have format {@link PelFormat::SRATIONAL}. * * @author Martin Geisler * @package PEL */ class PelEntrySRational extends PelEntrySLong { /** * Make a new entry that can hold a signed rational. * * @param PelTag the tag which this entry represents. This should * be one of the constants defined in {@link PelTag}, e.g., {@link * PelTag::SHUTTER_SPEED_VALUE}, or any other tag which can have * format {@link PelFormat::SRATIONAL}. * * @param array $value... the rational(s) that this entry will * represent. The arguments passed must obey the same rules as the * argument to {@link setValue}, namely that each argument should be * an array with two entries, both of which must be within range of * a signed long (32 bit), that is between -2147483648 and * 2147483647 (inclusive). If not, then a {@link * PelOverflowException} will be thrown. */ function __construct($tag /* $value... */) { $this->tag = $tag; $this->format = PelFormat::SRATIONAL; $this->dimension = 2; $this->min = -2147483648; $this->max = 2147483647; $value = func_get_args(); array_shift($value); $this->setValueArray($value); } /** * Format a rational number. * * The rational will be returned as a string with a slash '/' * between the numerator and denominator. Care is taken to display * '-1/2' instead of the ugly but mathematically equivalent '1/-2'. * * @param array the rational which will be formatted. * * @param boolean not used. * * @return string the rational formatted as a string suitable for * display. */ function formatNumber($number, $brief = false) { if ($number[1] < 0) /* Turn output like 1/-2 into -1/2. */ return (-$number[0]) . '/' . (-$number[1]); else return $number[0] . '/' . $number[1]; } /** * 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::SHUTTER_SPEED_VALUE: //CC (e->components, 1, v); //if (!v_srat.denominator) return (NULL); return Pel::fmt('%.0f/%.0f sec. (APEX: %d)', $v[0], $v[1], pow(sqrt(2), $v[0]/$v[1])); case PelTag::BRIGHTNESS_VALUE: //CC (e->components, 1, v); // // TODO: figure out the APEX thing, or remove this so that it is // handled by the default clause at the bottom. return sprintf('%d/%d', $v[0], $v[1]); //FIXME: How do I calculate the APEX value? case PelTag::EXPOSURE_BIAS_VALUE: //CC (e->components, 1, v); //if (!v_srat.denominator) return (NULL); return sprintf('%s%.01f', $v[0]*$v[1] > 0 ? '+' : '', $v[0]/$v[1]); default: return parent::getText($brief); } } } ?>