scratch – Blame information for rev 115

Subversion Repositories:
Rev:
Rev Author Line No. Line
115 office 1 <?php
2  
3 /*
4 * This file is part of PHP-FFmpeg.
5 *
6 * (c) Alchemy <dev.team@alchemy.fr>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11  
12 namespace FFMpeg\Coordinate;
13  
14 use FFMpeg\Exception\InvalidArgumentException;
15  
16 // see http://en.wikipedia.org/wiki/List_of_common_resolutions
17 class AspectRatio
18 {
19 // named 4:3 or 1.33:1 Traditional TV
20 const AR_4_3 = '4/3';
21 // named 16:9 or 1.77:1 HD video standard
22 const AR_16_9 = '16/9';
23  
24 // named 3:2 or 1.5:1 see http://en.wikipedia.org/wiki/135_film
25 const AR_3_2 = '3/2';
26 // named 5:3 or 1.66:1 see http://en.wikipedia.org/wiki/Super_16_mm
27 const AR_5_3 = '5/3';
28  
29 // mostly used in Photography
30 const AR_5_4 = '5/4';
31 const AR_1_1 = '1/1';
32  
33 // 1.85:1 US widescreen cinema standard see http://en.wikipedia.org/wiki/Widescreen#Film
34 const AR_1_DOT_85_1 = '1.85:1';
35 // 2.39:1 or 2.40:1 Current widescreen cinema standard see http://en.wikipedia.org/wiki/Anamorphic_format
36 const AR_2_DOT_39_1 = '2.39:1';
37  
38 // Rotated constants
39  
40 // Rotated 4:3
41 const AR_ROTATED_3_4 = '3/4';
42 // Rotated 16:9
43 const AR_ROTATED_9_16 = '9/16';
44  
45 // Rotated 3:2
46 const AR_ROTATED_2_3 = '2/3';
47 // Rotated 5:3
48 const AR_ROTATED_3_5 = '3/5';
49  
50 // Rotated 5:4
51 const AR_ROTATED_4_5 = '4/5';
52  
53 // Rotated 1.85
54 const AR_ROTATED_1_DOT_85 = '1/1.85';
55 // Rotated 2.39
56 const AR_ROTATED_2_DOT_39 = '1/2.39';
57  
58 /** @var float */
59 private $ratio;
60  
61 public function __construct($ratio)
62 {
63 $this->ratio = $ratio;
64 }
65  
66 /**
67 * Returns the value of the ratio.
68 *
69 * @return float
70 */
71 public function getValue()
72 {
73 return $this->ratio;
74 }
75  
76 /**
77 * Computes the best width for given height and modulus.
78 *
79 * @param Integer $height
80 * @param Integer $modulus
81 *
82 * @return Integer
83 */
84 public function calculateWidth($height, $modulus = 1)
85 {
86 $maxPossibleWidth = $this->getMultipleUp(ceil($this->ratio * $height), $modulus);
87 $minPossibleWidth = $this->getMultipleDown(floor($this->ratio * $height), $modulus);
88  
89 $maxRatioDiff = abs($this->ratio - ($maxPossibleWidth / $height));
90 $minRatioDiff = abs($this->ratio - ($minPossibleWidth / $height));
91  
92 return $maxRatioDiff < $minRatioDiff ? $maxPossibleWidth : $minPossibleWidth;
93 }
94  
95 /**
96 * Computes the best height for given width and modulus.
97 *
98 * @param Integer $width
99 * @param Integer $modulus
100 *
101 * @return Integer
102 */
103 public function calculateHeight($width, $modulus = 1)
104 {
105 $maxPossibleHeight = $this->getMultipleUp(ceil($width / $this->ratio), $modulus);
106 $minPossibleHeight = $this->getMultipleDown(floor($width / $this->ratio), $modulus);
107  
108 $maxRatioDiff = abs($this->ratio - ($width / $maxPossibleHeight));
109 $minRatioDiff = abs($this->ratio - ($width / $minPossibleHeight));
110  
111 return $maxRatioDiff < $minRatioDiff ? $maxPossibleHeight : $minPossibleHeight;
112 }
113  
114 private function getMultipleUp($value, $multiple)
115 {
116 while (0 !== $value % $multiple) {
117 $value++;
118 }
119  
120 return $value;
121 }
122  
123 private function getMultipleDown($value, $multiple)
124 {
125 while (0 !== $value % $multiple) {
126 $value--;
127 }
128  
129 return $value;
130 }
131  
132 /**
133 * Creates a ratio based on Dimension.
134 *
135 * The strategy parameter forces by default to use standardized ratios. If
136 * custom ratio need to be used, disable it.
137 *
138 * @param Dimension $dimension
139 * @param Boolean $forceStandards Whether to force or not standard ratios
140 *
141 * @return AspectRatio
142 *
143 * @throws InvalidArgumentException
144 */
145 public static function create(Dimension $dimension, $forceStandards = true)
146 {
147 $incoming = $dimension->getWidth() / $dimension->getHeight();
148  
149 if ($forceStandards) {
150 return new static(static::nearestStrategy($incoming));
151 } else {
152 return new static(static::customStrategy($incoming));
153 }
154 }
155  
156 private static function valueFromName($name)
157 {
158 switch ($name) {
159 case static::AR_4_3:
160 return 4 / 3;
161 case static::AR_16_9:
162 return 16 / 9;
163 case static::AR_1_1:
164 return 1 / 1;
165 case static::AR_1_DOT_85_1:
166 return 1.85;
167 case static::AR_2_DOT_39_1:
168 return 2.39;
169 case static::AR_3_2:
170 return 3 / 2;
171 case static::AR_5_3:
172 return 5 / 3;
173 case static::AR_5_4:
174 return 5 / 4;
175 case static::AR_ROTATED_3_4:
176 return 3 / 4;
177 case static::AR_ROTATED_9_16:
178 return 9 / 16;
179 case static::AR_ROTATED_2_3:
180 return 2 / 3;
181 case static::AR_ROTATED_3_5:
182 return 3 / 5;
183 case static::AR_ROTATED_4_5:
184 return 4 / 5;
185 case static::AR_ROTATED_1_DOT_85:
186 return 1 / 1.85;
187 case static::AR_ROTATED_2_DOT_39:
188 return 1 / 2.39;
189 default:
190 throw new InvalidArgumentException(sprintf('Unable to find value for %s', $name));
191 }
192 }
193  
194 private static function customStrategy($incoming)
195 {
196 $try = static::nearestStrategy($incoming);
197  
198 if (abs($try - $incoming) < $try * 0.05) {
199 return $try;
200 }
201  
202 return $incoming;
203 }
204  
205 private static function nearestStrategy($incoming)
206 {
207 $availables = array(
208 static::AR_4_3 => static::valueFromName(static::AR_4_3),
209 static::AR_16_9 => static::valueFromName(static::AR_16_9),
210 static::AR_1_1 => static::valueFromName(static::AR_1_1),
211 static::AR_1_DOT_85_1 => static::valueFromName(static::AR_1_DOT_85_1),
212 static::AR_2_DOT_39_1 => static::valueFromName(static::AR_2_DOT_39_1),
213 static::AR_3_2 => static::valueFromName(static::AR_3_2),
214 static::AR_5_3 => static::valueFromName(static::AR_5_3),
215 static::AR_5_4 => static::valueFromName(static::AR_5_4),
216  
217 // Rotated
218 static::AR_ROTATED_4_5 => static::valueFromName(static::AR_ROTATED_4_5),
219 static::AR_ROTATED_9_16 => static::valueFromName(static::AR_ROTATED_9_16),
220 static::AR_ROTATED_2_3 => static::valueFromName(static::AR_ROTATED_2_3),
221 static::AR_ROTATED_3_5 => static::valueFromName(static::AR_ROTATED_3_5),
222 static::AR_ROTATED_3_4 => static::valueFromName(static::AR_ROTATED_3_4),
223 static::AR_ROTATED_1_DOT_85 => static::valueFromName(static::AR_ROTATED_1_DOT_85),
224 static::AR_ROTATED_2_DOT_39 => static::valueFromName(static::AR_ROTATED_2_DOT_39),
225 );
226 asort($availables);
227  
228 $previous = $current = null;
229  
230 foreach ($availables as $name => $value) {
231 $current = $value;
232 if ($incoming <= $value) {
233 break;
234 }
235 $previous = $value;
236 }
237  
238 if (null === $previous) {
239 return $current;
240 }
241  
242 if (($current - $incoming) < ($incoming - $previous)) {
243 return $current;
244 }
245  
246 return $previous;
247 }
248 }