Conditions | 44 |
Paths | > 20000 |
Total Lines | 184 |
Code Lines | 113 |
Lines | 6 |
Ratio | 3.26 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | <?php |
||
40 | public static function resizeMulti(\Imagick $source, array $boxSizes, array $options = []) : array |
||
41 | { |
||
42 | //algorithm inspiration from http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html |
||
43 | //use of 2x2 binning is arguably the best quality one will get downsizing and is what lots of hardware does in the photography field, |
||
44 | //while being reasonably fast. Upsizing is more subjective but you can't get much better than bicubic which is what is used here. |
||
45 | |||
46 | $color = 'white'; |
||
47 | if (isset($options['color'])) { |
||
48 | $color = $options['color']; |
||
49 | if (!is_string($color)) { |
||
50 | throw new \InvalidArgumentException('$options["color"] was not a string'); |
||
51 | } |
||
52 | } |
||
53 | |||
54 | $upsize = false; |
||
55 | if (isset($options['upsize'])) { |
||
56 | $upsize = $options['upsize']; |
||
57 | if ($upsize !== true && $upsize !== false) { |
||
58 | throw new \InvalidArgumentException('$options["upsize"] was not a bool'); |
||
59 | } |
||
60 | } |
||
61 | |||
62 | $maxWidth = 10000; |
||
63 | if (isset($options['maxWidth'])) { |
||
64 | $maxWidth = $options['maxWidth']; |
||
65 | if (!is_int($maxWidth)) { |
||
66 | throw new \InvalidArgumentException('$options["maxWidth"] was not an int'); |
||
67 | } |
||
68 | } |
||
69 | |||
70 | $maxHeight = 10000; |
||
71 | if (isset($options['maxHeight'])) { |
||
72 | $maxHeight = $options['maxHeight']; |
||
73 | if (!is_int($maxHeight)) { |
||
74 | throw new \InvalidArgumentException('$options["maxHeight"] was not an int'); |
||
75 | } |
||
76 | } |
||
77 | |||
78 | foreach ($boxSizes as $boxSizeKey => $boxSize) { |
||
79 | View Code Duplication | if (!isset($boxSize['width']) || !is_int($boxSize['width'])) { |
|
|
|||
80 | throw new \InvalidArgumentException('a width in a $boxSizes value was not an int'); |
||
81 | } |
||
82 | |||
83 | View Code Duplication | if (!isset($boxSize['height']) || !is_int($boxSize['height'])) { |
|
84 | throw new \InvalidArgumentException('a height in a $boxSizes value was not an int'); |
||
85 | } |
||
86 | |||
87 | if ($boxSize['width'] > $maxWidth || $boxSize['width'] <= 0) { |
||
88 | throw new \InvalidArgumentException('a $boxSizes width was not between 0 and $options["maxWidth"]'); |
||
89 | } |
||
90 | |||
91 | if ($boxSize['height'] > $maxHeight || $boxSize['height'] <= 0) { |
||
92 | throw new \InvalidArgumentException('a $boxSizes height was not between 0 and $options["maxHeight"]'); |
||
93 | } |
||
94 | } |
||
95 | |||
96 | $results = []; |
||
97 | $cloneCache = []; |
||
98 | foreach ($boxSizes as $boxSizeKey => $boxSize) { |
||
99 | $boxWidth = $boxSize['width']; |
||
100 | $boxHeight = $boxSize['height']; |
||
101 | |||
102 | $clone = clone $source; |
||
103 | |||
104 | $orientation = $clone->getImageOrientation(); |
||
105 | switch ($orientation) { |
||
106 | case \Imagick::ORIENTATION_BOTTOMRIGHT: |
||
107 | $clone->rotateimage('#fff', 180); |
||
108 | $clone->stripImage(); |
||
109 | break; |
||
110 | case \Imagick::ORIENTATION_RIGHTTOP: |
||
111 | $clone->rotateimage('#fff', 90); |
||
112 | $clone->stripImage(); |
||
113 | break; |
||
114 | case \Imagick::ORIENTATION_LEFTBOTTOM: |
||
115 | $clone->rotateimage('#fff', -90); |
||
116 | $clone->stripImage(); |
||
117 | break; |
||
118 | } |
||
119 | |||
120 | $width = $clone->getImageWidth(); |
||
121 | $height = $clone->getImageHeight(); |
||
122 | |||
123 | //ratio over 1 is horizontal, under 1 is vertical |
||
124 | $boxRatio = $boxWidth / $boxHeight; |
||
125 | $originalRatio = $width / $height;//height should be positive since I didnt find a way you could get zero into imagick |
||
126 | |||
127 | $targetWidth = null; |
||
128 | $targetHeight = null; |
||
129 | $targetX = null; |
||
130 | $targetY = null; |
||
131 | if ($width < $boxWidth && $height < $boxHeight && !$upsize) { |
||
132 | $targetWidth = $width; |
||
133 | $targetHeight = $height; |
||
134 | $targetX = ($boxWidth - $width) / 2; |
||
135 | $targetY = ($boxHeight - $height) / 2; |
||
136 | } else { |
||
137 | //if box is more vertical than original |
||
138 | if ($boxRatio < $originalRatio) { |
||
139 | $targetWidth = $boxWidth; |
||
140 | $targetHeight = (int)((double)$boxWidth / $originalRatio); |
||
141 | $targetX = 0; |
||
142 | $targetY = ($boxHeight - $targetHeight) / 2; |
||
143 | } else { |
||
144 | $targetWidth = (int)((double)$boxHeight * $originalRatio); |
||
145 | $targetHeight = $boxHeight; |
||
146 | $targetX = ($boxWidth - $targetWidth) / 2; |
||
147 | $targetY = 0; |
||
148 | } |
||
149 | } |
||
150 | |||
151 | //do iterative downsize by halfs (2x2 binning is a common name) on dimensions that are bigger than target width and height |
||
152 | while (true) { |
||
153 | $widthReduced = false; |
||
154 | $widthIsHalf = false; |
||
155 | if ($width > $targetWidth) { |
||
156 | $width = (int)($width / 2); |
||
157 | $widthReduced = true; |
||
158 | $widthIsHalf = true; |
||
159 | if ($width < $targetWidth) { |
||
160 | $width = $targetWidth; |
||
161 | $widthIsHalf = false; |
||
162 | } |
||
163 | } |
||
164 | |||
165 | $heightReduced = false; |
||
166 | $heightIsHalf = false; |
||
167 | if ($height > $targetHeight) { |
||
168 | $height = (int)($height / 2); |
||
169 | $heightReduced = true; |
||
170 | $heightIsHalf = true; |
||
171 | if ($height < $targetHeight) { |
||
172 | $height = $targetHeight; |
||
173 | $heightIsHalf = false; |
||
174 | } |
||
175 | } |
||
176 | |||
177 | if (!$widthReduced && !$heightReduced) { |
||
178 | break; |
||
179 | } |
||
180 | |||
181 | $cacheKey = "{$width}x{$height}"; |
||
182 | if (isset($cloneCache[$cacheKey])) { |
||
183 | $clone = clone $cloneCache[$cacheKey]; |
||
184 | continue; |
||
185 | } |
||
186 | |||
187 | if ($clone->resizeImage($width, $height, \Imagick::FILTER_BOX, 1.0) !== true) { |
||
188 | //cumbersome to test |
||
189 | throw new \Exception('Imagick::resizeImage() did not return true');//@codeCoverageIgnore |
||
190 | } |
||
191 | |||
192 | if ($widthIsHalf && $heightIsHalf) { |
||
193 | $cloneCache[$cacheKey] = clone $clone; |
||
194 | } |
||
195 | } |
||
196 | |||
197 | if ($upsize && ($width < $targetWidth || $height < $targetHeight)) { |
||
198 | if ($clone->resizeImage($targetWidth, $targetHeight, \Imagick::FILTER_CUBIC, 1.0) !== true) { |
||
199 | //cumbersome to test |
||
200 | throw new \Exception('Imagick::resizeImage() did not return true');//@codeCoverageIgnore |
||
201 | } |
||
202 | } |
||
203 | |||
204 | //put image in box |
||
205 | $canvas = new \Imagick(); |
||
206 | if ($canvas->newImage($boxWidth, $boxHeight, $color) !== true) { |
||
207 | //cumbersome to test |
||
208 | throw new \Exception('Imagick::newImage() did not return true');//@codeCoverageIgnore |
||
209 | } |
||
210 | |||
211 | if ($canvas->compositeImage($clone, \Imagick::COMPOSITE_ATOP, $targetX, $targetY) !== true) { |
||
212 | //cumbersome to test |
||
213 | throw new \Exception('Imagick::compositeImage() did not return true');//@codeCoverageIgnore |
||
214 | } |
||
215 | |||
216 | //reason we are not supporting the options in self::write() here is because format, and strip headers are only relevant once written |
||
217 | //Imagick::stripImage() doesnt even have an effect until written |
||
218 | //also the user can just call that function with the resultant $canvas |
||
219 | $results[$boxSizeKey] = $canvas; |
||
220 | } |
||
221 | |||
222 | return $results; |
||
223 | } |
||
224 | |||
336 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.