Image_Transform_Driver_NetPBM::greyscale()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 4
nc 2
nop 0
dl 0
loc 8
rs 10
c 1
b 0
f 0
1
<?php
2
3
/* vim: set expandtab tabstop=4 shiftwidth=4: */
4
5
/**
6
 * NetPBM implementation for Image_Transform package
7
 *
8
 * PHP versions 4 and 5
9
 *
10
 * LICENSE: This source file is subject to version 3.0 of the PHP license
11
 * that is available through the world-wide-web at the following URI:
12
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
13
 * the PHP License and are unable to obtain it through the web, please
14
 * send a note to [email protected] so we can mail you a copy immediately.
15
 *
16
 * @category   Image
17
 * @package    Image_Transform
18
 * @author     Peter Bowyer <[email protected]>
19
 * @author     Philippe Jausions <[email protected]>
20
 * @copyright  2002-2005 The PHP Group
21
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
22
 * @version    CVS: $Id: NetPBM.php 236527 2007-05-28 16:36:09Z dufuz $
23
 * @link       http://pear.php.net/package/Image_Transform
24
 */
25
26
//require_once __DIR__ . '/Image/Transform.php';
27
//require_once __DIR__ . '/System.php';
28
require_once XOOPS_ROOT_PATH . '/modules/extgallery/class/pear/Image/Transform.php';
29
require_once XOOPS_ROOT_PATH . '/modules/extgallery/class/pear/System.php';
30
31
/**
32
 * NetPBM implementation for Image_Transform package
33
 *
34
 * @category   Image
35
 * @package    Image_Transform
36
 * @subpackage Image_Transform_Driver_NetPBM
37
 * @author     Peter Bowyer <[email protected]>
38
 * @author     Philippe Jausions <[email protected]>
39
 * @copyright  2002-2005 The PHP Group
40
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
41
 * @version    Release: @package_version@
42
 * @link       http://pear.php.net/package/Image_Transform
43
 * @link       http://netpbm.sourceforge.net/
44
 */
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()
57
    {
58
        $this->__construct();
59
    }
60
61
    // End function Image_NetPBM
62
63
    /**
64
     * Class Constructor
65
     */
66
    public function __construct()
67
    {
68
        if (!defined('IMAGE_TRANSFORM_NETPBM_PATH')) {
69
            $path = \dirname(System::which('pnmscale')) . DIRECTORY_SEPARATOR;
0 ignored issues
show
Bug introduced by
It seems like System::which('pnmscale') can also be of type false; however, parameter $path of dirname() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

69
            $path = \dirname(/** @scrutinizer ignore-type */ System::which('pnmscale')) . DIRECTORY_SEPARATOR;
Loading history...
70
            define('IMAGE_TRANSFORM_NETPBM_PATH', $path);
71
        }
72
        if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmscale' . (OS_WINDOWS ? '.exe' : ''))) {
73
            $this->isError(PEAR::raiseError('Couldn\'t find "pnmscale" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED));
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

73
            $this->isError(PEAR::/** @scrutinizer ignore-call */ raiseError('Couldn\'t find "pnmscale" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED));
Loading history...
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);
0 ignored issues
show
Bug introduced by
Are you sure $bgcolor of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

195
                $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmrotate', '-background=' . /** @scrutinizer ignore-type */ $bgcolor . ' -' . (float)$angle);
Loading history...
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) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $outputgamme does not exist. Did you maybe mean $outputgamma?
Loading history...
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)
313
    {
314
        if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'ppmlabel' . (OS_WINDOWS ? '.exe' : ''))) {
315
            return PEAR::raiseError('Couldn\'t find "ppmlabel" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
316
        }
317
318
        // we ignore 'resize_first' since the more logical approach would be
319
        // for the user to just call $this->_resize() _first_ ;)
320
        extract(array_merge($this->_get_default_text_params(), $params));
321
322
        $options = ['colorFont' => $color];
323
        $color   = $this->_getColor('colorFont', $options, [0, 0, 0]);
324
        $color   = $this->colorarray2colorhex($color);
325
326
        $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'ppmlabel', '-angle ' . ((int)$angle) . ' -colour ' . escapeshellarg($color) . ' -size ' . ((float)$size) . ' -x ' . ((int)$x) . ' -y ' . $y + $size . ' -text ' . escapeshellarg($text));
0 ignored issues
show
Bug introduced by
It seems like $color can also be of type false; however, parameter $arg of escapeshellarg() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

326
        $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'ppmlabel', '-angle ' . ((int)$angle) . ' -colour ' . escapeshellarg(/** @scrutinizer ignore-type */ $color) . ' -size ' . ((float)$size) . ' -x ' . ((int)$x) . ' -y ' . $y + $size . ' -text ' . escapeshellarg($text));
Loading history...
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     = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $arg is dead and can be removed.
Loading history...
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) {
0 ignored issues
show
introduced by
The condition null !== $quality is always true.
Loading history...
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)
501
    {
502
        $type    = $type ?? $this->type;
503
        $options = [];
504
        if (null !== $quality) {
505
            $options['quality'] = $quality;
506
        }
507
        $quality = $this->_getOption('quality', $options, 75);
508
509
        header('Content-type: ' . $this->getMimeType($type));
510
        $cmd = $this->_postProcess($type, $quality);
511
        passthru($cmd . ' 2>&1');
512
        if (!$this->keep_settings_on_save) {
513
            $this->free();
514
        }
515
516
        return true;
517
    }
518
519
    /**
520
     * Destroy image handle
521
     */
522
    public function free()
523
    {
524
        $this->command = [];
525
    }
526
} // End class ImageIM
527