ff8c0611155a8acd271d318b919ed7da84d528c3
[yaffs-website] / lsolesen / pel / src / PelEntryRational.php
1 <?php
2
3 /**
4  * PEL: PHP Exif Library.
5  * A library with support for reading and
6  * writing all Exif headers in JPEG and TIFF images using PHP.
7  *
8  * Copyright (C) 2004, 2005, 2006 Martin Geisler.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program in the file COPYING; if not, write to the
22  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23  * Boston, MA 02110-1301 USA
24  */
25 namespace lsolesen\pel;
26
27 /**
28  * Classes used to manipulate rational numbers.
29  *
30  * @author Martin Geisler <mgeisler@users.sourceforge.net>
31  * @license http://www.gnu.org/licenses/gpl.html GNU General Public
32  *          License (GPL)
33  * @package PEL
34  */
35
36 /**
37  * Class for holding unsigned rational numbers.
38  *
39  * This class can hold rational numbers, consisting of a numerator and
40  * denominator both of which are of type unsigned long. Each rational
41  * is represented by an array with just two entries: the numerator and
42  * the denominator, in that order.
43  *
44  * The class can hold either just a single rational or an array of
45  * rationals. The class will be used to manipulate any of the Exif
46  * tags which can have format {@link PelFormat::RATIONAL} like in this
47  * example:
48  *
49  * <code>
50  * $resolution = $ifd->getEntry(PelTag::X_RESOLUTION);
51  * $resolution->setValue(array(1, 300));
52  * </code>
53  *
54  * Here the x-resolution is adjusted to 1/300, which will be 300 DPI,
55  * unless the {@link PelTag::RESOLUTION_UNIT resolution unit} is set
56  * to something different than 2 which means inches.
57  *
58  * @author Martin Geisler <mgeisler@users.sourceforge.net>
59  * @package PEL
60  */
61 class PelEntryRational extends PelEntryLong
62 {
63
64     /**
65      * Make a new entry that can hold an unsigned rational.
66      *
67      * @param
68      *            PelTag the tag which this entry represents. This should
69      *            be one of the constants defined in {@link PelTag}, e.g., {@link
70      *            PelTag::X_RESOLUTION}, or any other tag which can have format
71      *            {@link PelFormat::RATIONAL}.
72      *
73      * @param array $value...
74      *            the rational(s) that this entry will
75      *            represent. The arguments passed must obey the same rules as the
76      *            argument to {@link setValue}, namely that each argument should be
77      *            an array with two entries, both of which must be within range of
78      *            an unsigned long (32 bit), that is between 0 and 4294967295
79      *            (inclusive). If not, then a {@link PelOverflowException} will be
80      *            thrown.
81      */
82     public function __construct($tag, $value = null)
83     {
84         $this->tag = $tag;
85         $this->format = PelFormat::RATIONAL;
86         $this->dimension = 2;
87         $this->min = 0;
88         $this->max = 4294967295;
89
90         $value = func_get_args();
91         array_shift($value);
92         $this->setValueArray($value);
93     }
94
95     /**
96      * Format a rational number.
97      *
98      * The rational will be returned as a string with a slash '/'
99      * between the numerator and denominator.
100      *
101      * @param
102      *            array the rational which will be formatted.
103      *
104      * @param
105      *            boolean not used.
106      *
107      * @return string the rational formatted as a string suitable for
108      *         display.
109      */
110     public function formatNumber($number, $brief = false)
111     {
112         return $number[0] . '/' . $number[1];
113     }
114
115     /**
116      * Get the value of an entry as text.
117      *
118      * The value will be returned in a format suitable for presentation,
119      * e.g., rationals will be returned as 'x/y', ASCII strings will be
120      * returned as themselves etc.
121      *
122      * @param
123      *            boolean some values can be returned in a long or more
124      *            brief form, and this parameter controls that.
125      *
126      * @return string the value as text.
127      */
128     public function getText($brief = false)
129     {
130         if (isset($this->value[0])) {
131             $v = $this->value[0];
132         }
133
134         switch ($this->tag) {
135             case PelTag::FNUMBER:
136                 // CC (e->components, 1, v);
137                 return Pel::fmt('f/%.01f', $v[0] / $v[1]);
138
139             case PelTag::APERTURE_VALUE:
140                 // CC (e->components, 1, v);
141                 // if (!v_rat.denominator) return (NULL);
142                 return Pel::fmt('f/%.01f', pow(2, $v[0] / $v[1] / 2));
143
144             case PelTag::FOCAL_LENGTH:
145                 // CC (e->components, 1, v);
146                 // if (!v_rat.denominator) return (NULL);
147                 return Pel::fmt('%.1f mm', $v[0] / $v[1]);
148
149             case PelTag::SUBJECT_DISTANCE:
150                 // CC (e->components, 1, v);
151                 // if (!v_rat.denominator) return (NULL);
152                 return Pel::fmt('%.1f m', $v[0] / $v[1]);
153
154             case PelTag::EXPOSURE_TIME:
155                 // CC (e->components, 1, v);
156                 // if (!v_rat.denominator) return (NULL);
157                 if ($v[0] / $v[1] < 1) {
158                     return Pel::fmt('1/%d sec.', $v[1] / $v[0]);
159                 } else {
160                     return Pel::fmt('%d sec.', $v[0] / $v[1]);
161                 }
162                 break;
163             case PelTag::GPS_LATITUDE:
164             case PelTag::GPS_LONGITUDE:
165                 $degrees = $this->value[0][0] / $this->value[0][1];
166                 $minutes = $this->value[1][0] / $this->value[1][1];
167                 $seconds = $this->value[2][0] / $this->value[2][1];
168
169                 return sprintf('%s° %s\' %s" (%.2f°)', $degrees, $minutes, $seconds, $degrees + $minutes / 60 + $seconds / 3600);
170
171             default:
172                 return parent::getText($brief);
173         }
174     }
175 }