Total Complexity | 139 |
Total Lines | 480 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like Image_Transform_Driver_NetPBM often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Image_Transform_Driver_NetPBM, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
45 | class Image_Transform_Driver_NetPBM extends Image_Transform |
||
46 | { |
||
47 | /** |
||
48 | * associative array commands to be executed |
||
49 | * @var array |
||
50 | */ |
||
51 | public $command = []; |
||
52 | |||
53 | /** |
||
54 | * Class Constructor |
||
55 | */ |
||
56 | public function Image_Transform_Driver_NetPBM() |
||
59 | } |
||
60 | |||
61 | // End function Image_NetPBM |
||
62 | |||
63 | /** |
||
64 | * Class Constructor |
||
65 | */ |
||
66 | public function __construct() |
||
74 | } |
||
75 | } |
||
76 | |||
77 | // End function Image_NetPBM |
||
78 | |||
79 | /** |
||
80 | * Load image |
||
81 | * |
||
82 | * @param mixed $image |
||
83 | * @return bool|PEAR_Error TRUE or a PEAR_Error object on error |
||
84 | * @access public |
||
85 | */ |
||
86 | public function load($image) |
||
87 | { |
||
88 | $this->image = $image; |
||
89 | $result = $this->_get_image_details($image); |
||
90 | if (PEAR::isError($result)) { |
||
91 | return $result; |
||
92 | } |
||
93 | |||
94 | return true; |
||
95 | } |
||
96 | |||
97 | // End load |
||
98 | |||
99 | /** |
||
100 | * Resize the image. |
||
101 | * |
||
102 | * @access private |
||
103 | * |
||
104 | * @param int $new_x New width |
||
105 | * @param int $new_y New height |
||
106 | * @param mixed $options Optional parameters |
||
107 | * |
||
108 | * @return true on success or PEAR Error object on error |
||
109 | * @see PEAR::isError() |
||
110 | */ |
||
111 | public function _resize($new_x, $new_y, $options = null) |
||
112 | { |
||
113 | // there's no technical reason why resize can't be called multiple |
||
114 | // times...it's just silly to do so |
||
115 | $scaleMethod = $this->_getOption('scaleMethod', $options, 'smooth'); |
||
116 | switch ($scaleMethod) { |
||
117 | case 'pixel': |
||
118 | $scale_x = $new_x / $this->img_x; |
||
119 | if ($scale_x == $new_y / $this->img_x |
||
120 | && $scale_x > 1 |
||
121 | && floor($scale_x) == $scale_x) { |
||
122 | if (System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmenlarge' . (OS_WINDOWS ? '.exe' : ''))) { |
||
123 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmenlarge', $scale_x); |
||
124 | } else { |
||
125 | return PEAR::raiseError('Couldn\'t find "pnmenlarge" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
126 | } |
||
127 | } else { |
||
128 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmscale', '-nomix -width ' . ((int)$new_x) . ' -height ' . ((int)$new_y)); |
||
129 | } |
||
130 | break; |
||
131 | case 'smooth': |
||
132 | default: |
||
133 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmscale', '-width ' . ((int)$new_x) . ' -height ' . ((int)$new_y)); |
||
134 | // Smooth things if scaling by a factor more than 3 |
||
135 | // (see pnmscale man page) |
||
136 | if ($new_x / $this->img_x > 3 |
||
137 | || $new_y / $this->img_y > 3) { |
||
138 | if (System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmsmooth' . (OS_WINDOWS ? '.exe' : ''))) { |
||
139 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmsmooth'); |
||
140 | } else { |
||
141 | return PEAR::raiseError('Couldn\'t find "pnmsmooth" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
142 | } |
||
143 | } |
||
144 | } // End [SWITCH] |
||
145 | |||
146 | $this->_set_new_x($new_x); |
||
147 | $this->_set_new_y($new_y); |
||
148 | |||
149 | return true; |
||
150 | } |
||
151 | |||
152 | // End resize |
||
153 | |||
154 | /** |
||
155 | * Rotates the image |
||
156 | * |
||
157 | * @param int $angle The angle to rotate the image through |
||
158 | * @param array $options |
||
159 | * @return bool|PEAR_Error TRUE on success, PEAR_Error object on error |
||
160 | */ |
||
161 | public function rotate($angle, $options = null) |
||
162 | { |
||
163 | if (!($angle == $this->_rotation_angle($angle))) { |
||
164 | // No rotation needed |
||
165 | return true; |
||
166 | } |
||
167 | |||
168 | // For pnmrotate, we want to limit rotations from -45 to +45 degrees |
||
169 | // even if acceptable range is -90 to +90 (see pnmrotate man page) |
||
170 | // Bring image to that range by using pamflip |
||
171 | if ($angle > 45 && $angle < 315) { |
||
172 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pamflip' . (OS_WINDOWS ? '.exe' : ''))) { |
||
173 | return PEAR::raiseError('Couldn\'t find "pamflip" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
174 | } |
||
175 | |||
176 | $quarters = floor(ceil($angle / 45) / 2); |
||
177 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pamflip', '-rotate' . (360 - $quarters * 90)); |
||
178 | $angle -= $quarters * 90; |
||
179 | } |
||
180 | |||
181 | if (0 != $angle) { |
||
182 | if ($angle > 45) { |
||
183 | $angle -= 360; |
||
184 | } |
||
185 | |||
186 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmrotate' . (OS_WINDOWS ? '.exe' : ''))) { |
||
187 | return PEAR::raiseError('Couldn\'t find "pnmrotate" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
188 | } |
||
189 | |||
190 | $bgcolor = $this->_getColor('canvasColor', $options, [255, 255, 255]); |
||
191 | $bgcolor = $this->colorarray2colorhex($bgcolor); |
||
192 | |||
193 | $scaleMethod = $this->_getOption('scaleMethod', $options, 'smooth'); |
||
194 | if ('pixel' != $scaleMethod) { |
||
195 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmrotate', '-background=' . $bgcolor . ' -' . (float)$angle); |
||
196 | } else { |
||
197 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmrotate', '-background=' . $bgcolor . ' -noantialias -' . (float)$angle); |
||
198 | } |
||
199 | } |
||
200 | |||
201 | return true; |
||
202 | } |
||
203 | |||
204 | // End rotate |
||
205 | |||
206 | /** |
||
207 | * Crop an image |
||
208 | * |
||
209 | * @param int $width Cropped image width |
||
210 | * @param int $height Cropped image height |
||
211 | * @param int $x positive X-coordinate to crop at |
||
212 | * @param int $y positive Y-coordinate to crop at |
||
213 | * |
||
214 | * @return mixed TRUE or a PEAR error object on error |
||
215 | * @todo keep track of the new cropped size |
||
216 | **/ |
||
217 | public function crop($width, $height, $x = 0, $y = 0) |
||
218 | { |
||
219 | // Sanity check |
||
220 | if (!$this->intersects($width, $height, $x, $y)) { |
||
221 | return PEAR::raiseError('Nothing to crop', IMAGE_TRANSFORM_ERROR_OUTOFBOUND); |
||
222 | } |
||
223 | if (0 != $x || 0 != $y |
||
224 | || $width != $this->img_x |
||
225 | || $height != $this->img_y) { |
||
226 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmcut' . (OS_WINDOWS ? '.exe' : ''))) { |
||
227 | return PEAR::raiseError('Couldn\'t find "pnmcut" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
228 | } |
||
229 | |||
230 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmcut', '-left ' . ((int)$x) . ' -top ' . ((int)$y) . ' -width ' . ((int)$width) . ' -height ' . ((int)$height)); |
||
231 | } |
||
232 | |||
233 | return true; |
||
234 | } |
||
235 | |||
236 | // End crop |
||
237 | |||
238 | /** |
||
239 | * Adjust the image gamma |
||
240 | * |
||
241 | * @param float $outputgamma |
||
242 | * |
||
243 | * @return mixed TRUE or a PEAR error object on error |
||
244 | */ |
||
245 | public function gamma($outputgamma = 1.0) |
||
246 | { |
||
247 | if (1.0 != $outputgamme) { |
||
248 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmgamma' . (OS_WINDOWS ? '.exe' : ''))) { |
||
249 | return PEAR::raiseError('Couldn\'t find "pnmgamma" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
250 | } |
||
251 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmgamma', (float)$outputgamma); |
||
252 | } |
||
253 | |||
254 | return true; |
||
255 | } |
||
256 | |||
257 | /** |
||
258 | * Vertical mirroring |
||
259 | * |
||
260 | * @return true or PEAR Error object on error |
||
261 | **@see mirror() |
||
262 | */ |
||
263 | public function flip() |
||
264 | { |
||
265 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pamflip' . (OS_WINDOWS ? '.exe' : ''))) { |
||
266 | return PEAR::raiseError('Couldn\'t find "pamflip" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
267 | } |
||
268 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pamflip', '-topbottom'); |
||
269 | |||
270 | return true; |
||
271 | } |
||
272 | |||
273 | /** |
||
274 | * Horizontal mirroring |
||
275 | * |
||
276 | * @return true or PEAR Error object on error |
||
277 | **@see flip() |
||
278 | */ |
||
279 | public function mirror() |
||
280 | { |
||
281 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pamflip' . (OS_WINDOWS ? '.exe' : ''))) { |
||
282 | return PEAR::raiseError('Couldn\'t find "pamflip" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
283 | } |
||
284 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pamflip', '-leftright'); |
||
285 | |||
286 | return true; |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * Converts an image into greyscale colors |
||
291 | * |
||
292 | * @access public |
||
293 | * @return mixed TRUE or a PEAR error object on error |
||
294 | **/ |
||
295 | public function greyscale() |
||
296 | { |
||
297 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'ppmtopgm' . (OS_WINDOWS ? '.exe' : ''))) { |
||
298 | return PEAR::raiseError('Couldn\'t find "ppmtopgm" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
299 | } |
||
300 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'ppmtopgm'); |
||
301 | |||
302 | return true; |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * adds text to an image |
||
307 | * |
||
308 | * @param mixed $params |
||
309 | * |
||
310 | * @return object |
||
311 | */ |
||
312 | public function addText($params) |
||
327 | } |
||
328 | |||
329 | // End addText |
||
330 | |||
331 | /** |
||
332 | * Image_Transform_Driver_NetPBM::_postProcess() |
||
333 | * |
||
334 | * @param $type |
||
335 | * @param $quality |
||
336 | * @return string A chain of shell command |
||
337 | * @link http://netpbm.sourceforge.net/doc/directory.html |
||
338 | */ |
||
339 | public function _postProcess($type, $quality) |
||
340 | { |
||
341 | array_unshift($this->command, $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, mb_strtolower($this->type) . 'topnm', escapeshellarg($this->image))); |
||
342 | $arg = ''; |
||
343 | $type = mb_strtolower($type); |
||
344 | $program = ''; |
||
345 | switch ($type) { |
||
346 | // ppmto* converters |
||
347 | case 'gif': |
||
348 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'ppmquant' . (OS_WINDOWS ? '.exe' : ''))) { |
||
349 | return PEAR::raiseError('Couldn\'t find "ppmquant" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
350 | } |
||
351 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'ppmquant', 256); |
||
352 | // no break |
||
353 | case 'acad': |
||
354 | case 'bmp': |
||
355 | case 'eyuv': |
||
356 | case 'ilbm': |
||
357 | case 'leaf': |
||
358 | case 'lj': |
||
359 | case 'mitsu': |
||
360 | case 'mpeg': |
||
361 | case 'neo': |
||
362 | case 'pcx': |
||
363 | case 'pi1': |
||
364 | case 'pict': |
||
365 | case 'pj': |
||
366 | case 'pjxl': |
||
367 | case 'puzz': |
||
368 | case 'sixel': |
||
369 | case 'tga': |
||
370 | case 'uil': |
||
371 | case 'xpm': |
||
372 | case 'yuv': |
||
373 | $program = 'ppmto' . $type; |
||
374 | break; |
||
375 | // Windows icon |
||
376 | case 'winicon': |
||
377 | case 'ico': |
||
378 | $type = 'winicon'; |
||
379 | $program = 'ppmto' . $type; |
||
380 | break; |
||
381 | // pbmto* converters |
||
382 | case 'ascii': |
||
383 | case 'text': |
||
384 | case 'txt': |
||
385 | $type = 'ascii'; |
||
386 | // no break |
||
387 | case 'atk': |
||
388 | case 'bbubg': |
||
389 | case 'epsi': |
||
390 | case 'epson': |
||
391 | case 'escp2': |
||
392 | case 'icon': // Sun icon |
||
393 | case 'gem': |
||
394 | case 'go': |
||
395 | case 'lj': |
||
396 | case 'ln03': |
||
397 | case 'lps': |
||
398 | case 'macp': |
||
399 | case 'mda': |
||
400 | case 'mgr': |
||
401 | case 'pi3': |
||
402 | case 'pk': |
||
403 | case 'plot': |
||
404 | case 'ptx': |
||
405 | case 'wbp': |
||
406 | case 'xbm': |
||
407 | case 'x10bm': |
||
408 | case 'ybm': |
||
409 | case 'zinc': |
||
410 | case '10x': |
||
411 | $program = 'pbmto' . $type; |
||
412 | break; |
||
413 | // pamto* converters |
||
414 | case 'jpc': |
||
415 | $type = 'jpeg2k'; |
||
416 | // no break |
||
417 | case 'html': |
||
418 | case 'pfm': |
||
419 | case 'tga': |
||
420 | $program = 'pamto' . $type; |
||
421 | break; |
||
422 | // pnmto* converters |
||
423 | case 'jpc': |
||
424 | $type = 'jpeg2k'; |
||
425 | break; |
||
426 | case 'wfa': |
||
427 | $type = 'fiasco'; |
||
428 | break; |
||
429 | case 'jpg': |
||
430 | $type = 'jpeg'; |
||
431 | // no break |
||
432 | case 'jpeg': |
||
433 | $arg = '--quality=' . $quality; |
||
434 | // no break |
||
435 | case 'jbig': |
||
436 | case 'fits': |
||
437 | case 'palm': |
||
438 | case 'pclxl': |
||
439 | case 'png': |
||
440 | case 'ps': |
||
441 | case 'rast': |
||
442 | case 'rle': |
||
443 | case 'sgi': |
||
444 | case 'sir': |
||
445 | case 'tiff': |
||
446 | case 'xwd': |
||
447 | $program = 'pnmto' . $type; |
||
448 | break; |
||
449 | } // switch |
||
450 | |||
451 | if ('' == $program) { |
||
452 | $program = 'pnmto' . $type; |
||
453 | } |
||
454 | |||
455 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . $program . (OS_WINDOWS ? '.exe' : ''))) { |
||
456 | return PEAR::raiseError("Couldn't find \"$program\" binary", IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
457 | } |
||
458 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, $program); |
||
459 | |||
460 | return implode('|', $this->command); |
||
461 | } |
||
462 | |||
463 | /** |
||
464 | * Save the image file |
||
465 | * |
||
466 | * @param string $filename the name of the file to write to |
||
467 | * @param string $type (jpeg,png...); |
||
468 | * @param int $quality 75 |
||
469 | * @return true or PEAR Error object on error |
||
470 | */ |
||
471 | public function save($filename, $type = null, $quality = 75) |
||
472 | { |
||
473 | $type = $type ?? $this->type; |
||
474 | $options = []; |
||
475 | if (null !== $quality) { |
||
476 | $options['quality'] = $quality; |
||
477 | } |
||
478 | $quality = $this->_getOption('quality', $options, $quality); |
||
479 | |||
480 | $nullDevice = OS_WINDOWS ? 'nul' : '/dev/null'; |
||
481 | |||
482 | $cmd = $this->_postProcess($type, $quality) . '> "' . $filename . '"'; |
||
483 | exec($cmd . ' 2> ' . $nullDevice, $res, $exit); |
||
484 | if (!$this->keep_settings_on_save) { |
||
485 | $this->free(); |
||
486 | } |
||
487 | |||
488 | return (0 == $exit) ? true : PEAR::raiseError(implode('. ', $res), IMAGE_TRANSFORM_ERROR_IO); |
||
489 | } |
||
490 | |||
491 | // End save |
||
492 | |||
493 | /** |
||
494 | * Display image without saving and lose changes |
||
495 | * |
||
496 | * @param string $type (jpeg,png...); |
||
497 | * @param int $quality 75 |
||
498 | * @return true or PEAR Error object on error |
||
499 | */ |
||
500 | public function display($type = null, $quality = null) |
||
517 | } |
||
518 | |||
519 | /** |
||
520 | * Destroy image handle |
||
521 | */ |
||
522 | public function free() |
||
523 | { |
||
524 | $this->command = []; |
||
527 |