Total Complexity | 141 |
Total Lines | 482 |
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 = array(); |
||
52 | |||
53 | /** |
||
54 | * Class Constructor |
||
55 | */ |
||
56 | public function Image_Transform_Driver_NetPBM() |
||
57 | { |
||
58 | $this->__construct(); |
||
59 | } // End function Image_NetPBM |
||
60 | |||
61 | /** |
||
62 | * Class Constructor |
||
63 | */ |
||
64 | public function __construct() |
||
65 | { |
||
66 | if (!defined('IMAGE_TRANSFORM_NETPBM_PATH')) { |
||
67 | $path = dirname(System::which('pnmscale')) . DIRECTORY_SEPARATOR; |
||
68 | define('IMAGE_TRANSFORM_NETPBM_PATH', $path); |
||
69 | } |
||
70 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmscale' . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
71 | $this->isError(PEAR::raiseError('Couldn\'t find "pnmscale" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED)); |
||
72 | } |
||
73 | } // End function Image_NetPBM |
||
74 | |||
75 | /** |
||
76 | * Load image |
||
77 | * |
||
78 | * @param string filename |
||
79 | * @return bool|PEAR_Error TRUE or a PEAR_Error object on error |
||
80 | * @access public |
||
81 | */ |
||
82 | public function load($image) |
||
83 | { |
||
84 | $this->image = $image; |
||
85 | $result = $this->_get_image_details($image); |
||
86 | if (PEAR::isError($result)) { |
||
87 | return $result; |
||
88 | } |
||
89 | |||
90 | return true; |
||
91 | } // End load |
||
92 | |||
93 | /** |
||
94 | * Resize the image. |
||
95 | * |
||
96 | * @access private |
||
97 | * |
||
98 | * @param int $new_x New width |
||
99 | * @param int $new_y New height |
||
100 | * @param mixed $options Optional parameters |
||
101 | * |
||
102 | * @return true on success or PEAR Error object on error |
||
103 | * @see PEAR::isError() |
||
104 | */ |
||
105 | public function _resize($new_x, $new_y, $options = null) |
||
106 | { |
||
107 | // there's no technical reason why resize can't be called multiple |
||
108 | // times...it's just silly to do so |
||
109 | $scaleMethod = $this->_getOption('scaleMethod', $options, 'smooth'); |
||
110 | switch ($scaleMethod) { |
||
111 | case 'pixel': |
||
112 | $scale_x = $new_x / $this->img_x; |
||
113 | if ($scale_x == $new_y / $this->img_x |
||
114 | && $scale_x > 1 |
||
115 | && floor($scale_x) == $scale_x) { |
||
116 | if (System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmenlarge' . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
117 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmenlarge', $scale_x); |
||
118 | } else { |
||
119 | return PEAR::raiseError('Couldn\'t find "pnmenlarge" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
120 | } |
||
121 | } else { |
||
122 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmscale', '-nomix -width ' . ((int)$new_x) . ' -height ' . ((int)$new_y)); |
||
123 | } |
||
124 | break; |
||
125 | |||
126 | case 'smooth': |
||
127 | default: |
||
128 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmscale', '-width ' . ((int)$new_x) . ' -height ' . ((int)$new_y)); |
||
129 | // Smooth things if scaling by a factor more than 3 |
||
130 | // (see pnmscale man page) |
||
131 | if ($new_x / $this->img_x > 3 |
||
132 | || $new_y / $this->img_y > 3) { |
||
133 | if (System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmsmooth' . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
134 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmsmooth'); |
||
135 | } else { |
||
136 | return PEAR::raiseError('Couldn\'t find "pnmsmooth" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
137 | } |
||
138 | } |
||
139 | } // End [SWITCH] |
||
140 | |||
141 | $this->_set_new_x($new_x); |
||
142 | $this->_set_new_y($new_y); |
||
143 | |||
144 | return true; |
||
145 | } // End resize |
||
146 | |||
147 | /** |
||
148 | * Rotates the image |
||
149 | * |
||
150 | * @param int $angle The angle to rotate the image through |
||
151 | * @param array $options |
||
152 | * @return bool|PEAR_Error TRUE on success, PEAR_Error object on error |
||
153 | */ |
||
154 | public function rotate($angle, $options = null) |
||
155 | { |
||
156 | if (!($angle == $this->_rotation_angle($angle))) { |
||
157 | // No rotation needed |
||
158 | return true; |
||
159 | } |
||
160 | |||
161 | // For pnmrotate, we want to limit rotations from -45 to +45 degrees |
||
162 | // even if acceptable range is -90 to +90 (see pnmrotate man page) |
||
163 | // Bring image to that range by using pamflip |
||
164 | if ($angle > 45 && $angle < 315) { |
||
165 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pamflip' . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
166 | return PEAR::raiseError('Couldn\'t find "pamflip" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
167 | } |
||
168 | |||
169 | $quarters = floor(ceil($angle / 45) / 2); |
||
170 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pamflip', '-rotate' . (360 - $quarters * 90)); |
||
171 | $angle -= $quarters * 90; |
||
172 | } |
||
173 | |||
174 | if (0 != $angle) { |
||
175 | if ($angle > 45) { |
||
176 | $angle -= 360; |
||
177 | } |
||
178 | |||
179 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmrotate' . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
180 | return PEAR::raiseError('Couldn\'t find "pnmrotate" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
181 | } |
||
182 | |||
183 | $bgcolor = $this->_getColor('canvasColor', $options, array(255, 255, 255)); |
||
184 | $bgcolor = $this->colorarray2colorhex($bgcolor); |
||
185 | |||
186 | $scaleMethod = $this->_getOption('scaleMethod', $options, 'smooth'); |
||
187 | if ('pixel' != $scaleMethod) { |
||
188 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmrotate', '-background=' . $bgcolor . ' -' . (float)$angle); |
||
189 | } else { |
||
190 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmrotate', '-background=' . $bgcolor . ' -noantialias -' . (float)$angle); |
||
191 | } |
||
192 | } |
||
193 | |||
194 | return true; |
||
195 | } // End rotate |
||
196 | |||
197 | /** |
||
198 | * Crop an image |
||
199 | * |
||
200 | * @param int $width Cropped image width |
||
201 | * @param int $height Cropped image height |
||
202 | * @param int $x positive X-coordinate to crop at |
||
203 | * @param int $y positive Y-coordinate to crop at |
||
204 | * |
||
205 | * @return mixed TRUE or a PEAR error object on error |
||
206 | * @todo keep track of the new cropped size |
||
207 | **/ |
||
208 | public function crop($width, $height, $x = 0, $y = 0) |
||
209 | { |
||
210 | // Sanity check |
||
211 | if (!$this->intersects($width, $height, $x, $y)) { |
||
212 | return PEAR::raiseError('Nothing to crop', IMAGE_TRANSFORM_ERROR_OUTOFBOUND); |
||
213 | } |
||
214 | if (0 != $x || 0 != $y |
||
215 | || $width != $this->img_x |
||
216 | || $height != $this->img_y) { |
||
217 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmcut' . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
218 | return PEAR::raiseError('Couldn\'t find "pnmcut" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
219 | } |
||
220 | |||
221 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmcut', '-left ' . ((int)$x) . ' -top ' . ((int)$y) . ' -width ' . ((int)$width) . ' -height ' . ((int)$height)); |
||
222 | } |
||
223 | |||
224 | return true; |
||
225 | } // End crop |
||
226 | |||
227 | /** |
||
228 | * Adjust the image gamma |
||
229 | * |
||
230 | * @param float $outputgamma |
||
231 | * |
||
232 | * @return mixed TRUE or a PEAR error object on error |
||
233 | */ |
||
234 | public function gamma($outputgamma = 1.0) |
||
235 | { |
||
236 | if (1.0 != $outputgamme) { |
||
237 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmgamma' . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
238 | return PEAR::raiseError('Couldn\'t find "pnmgamma" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
239 | } |
||
240 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmgamma', (float)$outputgamma); |
||
241 | } |
||
242 | |||
243 | return true; |
||
244 | } |
||
245 | |||
246 | /** |
||
247 | * Vertical mirroring |
||
248 | * |
||
249 | * @see mirror() |
||
250 | * @return TRUE or PEAR Error object on error |
||
251 | **/ |
||
252 | public function flip() |
||
253 | { |
||
254 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pamflip' . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
255 | return PEAR::raiseError('Couldn\'t find "pamflip" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
256 | } |
||
257 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pamflip', '-topbottom'); |
||
258 | |||
259 | return true; |
||
260 | } |
||
261 | |||
262 | /** |
||
263 | * Horizontal mirroring |
||
264 | * |
||
265 | * @see flip() |
||
266 | * @return TRUE or PEAR Error object on error |
||
267 | **/ |
||
268 | public function mirror() |
||
269 | { |
||
270 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pamflip' . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
271 | return PEAR::raiseError('Couldn\'t find "pamflip" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
272 | } |
||
273 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pamflip', '-leftright'); |
||
274 | |||
275 | return true; |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * Converts an image into greyscale colors |
||
280 | * |
||
281 | * @access public |
||
282 | * @return mixed TRUE or a PEAR error object on error |
||
283 | **/ |
||
284 | public function greyscale() |
||
285 | { |
||
286 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'ppmtopgm' . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
287 | return PEAR::raiseError('Couldn\'t find "ppmtopgm" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
288 | } |
||
289 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'ppmtopgm'); |
||
290 | |||
291 | return true; |
||
292 | } |
||
293 | |||
294 | /** |
||
295 | * adds text to an image |
||
296 | * |
||
297 | * @param array options Array contains options |
||
298 | * array( |
||
299 | * 'text' // The string to draw |
||
300 | * 'x' // Horizontal position |
||
301 | * 'y' // Vertical Position |
||
302 | * 'color' // Font color |
||
303 | * 'font' // Font to be used |
||
304 | * 'size' // Size of the fonts in pixel |
||
305 | * 'resize_first' // Tell if the image has to be resized |
||
306 | * // before drawing the text |
||
307 | * ) |
||
308 | * |
||
309 | * @return void |
||
310 | */ |
||
311 | public function addText($params) |
||
326 | } // End addText |
||
327 | |||
328 | /** |
||
329 | * Image_Transform_Driver_NetPBM::_postProcess() |
||
330 | * |
||
331 | * @param $type |
||
332 | * @param $quality |
||
333 | * @return string A chain of shell command |
||
334 | * @link http://netpbm.sourceforge.net/doc/directory.html |
||
335 | */ |
||
336 | public function _postProcess($type, $quality) |
||
337 | { |
||
338 | array_unshift($this->command, $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, strtolower($this->type) . 'topnm', escapeshellarg($this->image))); |
||
339 | $arg = ''; |
||
340 | $type = strtolower($type); |
||
341 | $program = ''; |
||
342 | switch ($type) { |
||
343 | // ppmto* converters |
||
344 | case 'gif': |
||
345 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'ppmquant' . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
346 | return PEAR::raiseError('Couldn\'t find "ppmquant" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
347 | } |
||
348 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'ppmquant', 256); |
||
349 | // no break |
||
350 | case 'acad': |
||
351 | case 'bmp': |
||
352 | case 'eyuv': |
||
353 | case 'ilbm': |
||
354 | case 'leaf': |
||
355 | case 'lj': |
||
356 | case 'mitsu': |
||
357 | case 'mpeg': |
||
358 | case 'neo': |
||
359 | case 'pcx': |
||
360 | case 'pi1': |
||
361 | case 'pict': |
||
362 | case 'pj': |
||
363 | case 'pjxl': |
||
364 | case 'puzz': |
||
365 | case 'sixel': |
||
366 | case 'tga': |
||
367 | case 'uil': |
||
368 | case 'xpm': |
||
369 | case 'yuv': |
||
370 | $program = 'ppmto' . $type; |
||
371 | break; |
||
372 | |||
373 | // Windows icon |
||
374 | case 'winicon': |
||
375 | case 'ico': |
||
376 | $type = 'winicon'; |
||
377 | $program = 'ppmto' . $type; |
||
378 | break; |
||
379 | |||
380 | // pbmto* converters |
||
381 | case 'ascii': |
||
382 | case 'text': |
||
383 | case 'txt': |
||
384 | $type = 'ascii'; |
||
385 | // no break |
||
386 | case 'atk': |
||
387 | case 'bbubg': |
||
388 | case 'epsi': |
||
389 | case 'epson': |
||
390 | case 'escp2': |
||
391 | case 'icon': // Sun icon |
||
392 | case 'gem': |
||
393 | case 'go': |
||
394 | case 'lj': |
||
395 | case 'ln03': |
||
396 | case 'lps': |
||
397 | case 'macp': |
||
398 | case 'mda': |
||
399 | case 'mgr': |
||
400 | case 'pi3': |
||
401 | case 'pk': |
||
402 | case 'plot': |
||
403 | case 'ptx': |
||
404 | case 'wbp': |
||
405 | case 'xbm': |
||
406 | case 'x10bm': |
||
407 | case 'ybm': |
||
408 | case 'zinc': |
||
409 | case '10x': |
||
410 | $program = 'pbmto' . $type; |
||
411 | break; |
||
412 | |||
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 | |||
423 | // pnmto* converters |
||
424 | case 'jpc': |
||
425 | $type = 'jpeg2k'; |
||
426 | break; |
||
427 | case 'wfa': |
||
428 | $type = 'fiasco'; |
||
429 | break; |
||
430 | case 'jpg': |
||
431 | $type = 'jpeg'; |
||
432 | // no break |
||
433 | case 'jpeg': |
||
434 | $arg = '--quality=' . $quality; |
||
435 | // no break |
||
436 | case 'jbig': |
||
437 | case 'fits': |
||
438 | case 'palm': |
||
439 | case 'pclxl': |
||
440 | case 'png': |
||
441 | case 'ps': |
||
442 | case 'rast': |
||
443 | case 'rle': |
||
444 | case 'sgi': |
||
445 | case 'sir': |
||
446 | case 'tiff': |
||
447 | case 'xwd': |
||
448 | $program = 'pnmto' . $type; |
||
449 | break; |
||
450 | |||
451 | } // switch |
||
452 | |||
453 | if ('' == $program) { |
||
454 | $program = 'pnmto' . $type; |
||
455 | } |
||
456 | |||
457 | if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . $program . ((OS_WINDOWS) ? '.exe' : ''))) { |
||
458 | return PEAR::raiseError("Couldn't find \"$program\" binary", IMAGE_TRANSFORM_ERROR_UNSUPPORTED); |
||
459 | } |
||
460 | $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, $program); |
||
461 | |||
462 | return implode('|', $this->command); |
||
463 | } |
||
464 | |||
465 | /** |
||
466 | * Save the image file |
||
467 | * |
||
468 | * @param $filename string the name of the file to write to |
||
469 | * @param string $type (jpeg,png...); |
||
470 | * @param int $quality 75 |
||
471 | * @return TRUE or PEAR Error object on error |
||
472 | */ |
||
473 | public function save($filename, $type = null, $quality = 75) |
||
474 | { |
||
475 | $type = (is_null($type)) ? $this->type : $type; |
||
476 | $options = array(); |
||
477 | if (!is_null($quality)) { |
||
478 | $options['quality'] = $quality; |
||
479 | } |
||
480 | $quality = $this->_getOption('quality', $options, $quality); |
||
481 | |||
482 | $nullDevice = (OS_WINDOWS) ? 'nul' : '/dev/null'; |
||
483 | |||
484 | $cmd = $this->_postProcess($type, $quality) . '> "' . $filename . '"'; |
||
485 | exec($cmd . ' 2> ' . $nullDevice, $res, $exit); |
||
486 | if (!$this->keep_settings_on_save) { |
||
487 | $this->free(); |
||
488 | } |
||
489 | |||
490 | return (0 == $exit) ? true : PEAR::raiseError(implode('. ', $res), IMAGE_TRANSFORM_ERROR_IO); |
||
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 | * @return void |
||
523 | */ |
||
524 | public function free() |
||
525 | { |
||
529 |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.