Completed
Push — master ( 603564...3d1dbb )
by Michael
03:27
created

Image_Transform_Driver_GD::addBorders()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 65 and the first side effect is on line 29.

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.

Loading history...
2
3
/* vim: set expandtab tabstop=4 shiftwidth=4: */
4
5
/**
6
 * GD 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
 * @subpackage Image_Transform_Driver_GD
19
 * @author     Alan Knowles <[email protected]>
20
 * @author     Peter Bowyer <[email protected]>
21
 * @author     Philippe Jausions <[email protected]>
22
 * @copyright  2002-2005 The PHP Group
23
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
24
 * @version    CVS: $Id: GD.php 322661 2012-01-24 12:02:59Z clockwerx $
25
 * @link       http://pear.php.net/package/Image_Transform
26
 */
27
28
//require_once 'Image/Transform.php';
29
require_once XOOPS_ROOT_PATH . '/modules/extgallery/class/pear/Image/Transform.php';
30
31
/**
32
 * GD implementation for Image_Transform package
33
 *
34
 * Usage :
35
 *    $img    =& Image_Transform::factory('GD');
36
 *    $angle  = -78;
37
 *    $img->load('magick.png');
38
 *
39
 *    if ($img->rotate($angle, array(
40
 *               'autoresize' => true,
41
 *               'color_mask' => array(255, 0, 0)))) {
42
 *        $img->addText(array(
43
 *               'text' => 'Rotation ' . $angle,
44
 *               'x' => 0,
45
 *               'y' => 100,
46
 *               'font' => '/usr/share/fonts/default/TrueType/cogb____.ttf'));
47
 *        $img->display();
48
 *    } else {
49
 *        echo "Error";
50
 *    }
51
 *    $img->free();
52
 *
53
 * @category   Image
54
 * @package    Image_Transform
55
 * @subpackage Image_Transform_Driver_GD
56
 * @author     Alan Knowles <[email protected]>
57
 * @author     Peter Bowyer <[email protected]>
58
 * @author     Philippe Jausions <[email protected]>
59
 * @copyright  2002-2005 The PHP Group
60
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
61
 * @version    Release: @package_version@
62
 * @link       http://pear.php.net/package/Image_Transform
63
 * @since      PHP 4.0
64
 */
65
class Image_Transform_Driver_GD extends Image_Transform
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
66
{
67
    /**
68
     * Holds the image resource for manipulation
69
     *
70
     * @var resource $imageHandle
71
     * @access protected
72
     */
73
    var $imageHandle = null;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $imageHandle.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
74
75
    /**
76
     * Holds the original image file
77
     *
78
     * @var resource $imageHandle
79
     * @access protected
80
     */
81
    var $oldImage = null;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $oldImage.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
82
83
    /**
84
     * Check settings
85
     */
86
    function Image_Transform_Driver_GD()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
87
    {
88
        $this->__construct();
89
    } // End function Image
90
91
    /**
92
     * Check settings
93
     *
94
     * @since PHP 5
95
     */
96
    function __construct()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
97
    {
98
        if (!PEAR::loadExtension('gd')) {
99
            $this->isError(PEAR::raiseError("GD library is not available.",
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
100
                IMAGE_TRANSFORM_ERROR_UNSUPPORTED));
101
        } else {
102
            $types = ImageTypes();
103
            if ($types & IMG_PNG) {
104
                $this->_supported_image_types['png'] = 'rw';
105
            }
106
            if (($types & IMG_GIF)
107
                || function_exists('imagegif')) {
108
                $this->_supported_image_types['gif'] = 'rw';
109
            } elseif (function_exists('imagecreatefromgif')) {
110
                $this->_supported_image_types['gif'] = 'rw';
111
            }
112
            if ($types & IMG_JPG) {
113
                $this->_supported_image_types['jpeg'] = 'rw';
114
            }
115
            if ($types & IMG_WBMP) {
116
                $this->_supported_image_types['wbmp'] = 'rw';
117
            }
118
            if (!$this->_supported_image_types) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->_supported_image_types of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
119
                $this->isError(PEAR::raiseError("No supported image types available", IMAGE_TRANSFORM_ERROR_UNSUPPORTED));
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
120
            }
121
        }
122
123
    } // End function Image
124
125
    /**
126
     * Loads an image from file
127
     *
128
     * @param string $image filename
129
     * @return bool|PEAR_Error TRUE or a PEAR_Error object on error
130
     * @access public
131
     */
132
    function load($image)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
133
    {
134
        $this->free();
135
136
        $this->image = $image;
137
        $result = $this->_get_image_details($image);
138
        if (PEAR::isError($result)) {
139
            return $result;
140
        }
141
        if (!$this->supportsType($this->type, 'r')) {
142
            return PEAR::raiseError('Image type not supported for input',
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
143
                IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
144
        }
145
146
        $functionName = 'ImageCreateFrom' . $this->type;
147
        $this->imageHandle = $functionName($this->image);
148
        if (!$this->imageHandle) {
149
            $this->imageHandle = null;
150
            return PEAR::raiseError('Error while loading image file.',
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
151
                IMAGE_TRANSFORM_ERROR_IO);
152
        }
153
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type of the parent method Image_Transform::load of type PEAR_Error.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
154
155
    } // End load
156
157
    /**
158
     * Returns the GD image handle
159
     *
160
     * @return resource
161
     *
162
     * @access public
163
     */
164
    function getHandle()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
165
    {
166
        return $this->imageHandle;
167
    }//function getHandle()
168
169
    /**
170
     * Adds a border of constant width around an image
171
     *
172
     * @param int $border_width Width of border to add
173
     * @author Peter Bowyer
174
     * @return bool TRUE
175
     * @access public
176
     */
177
    function addBorder($border_width, $color = '')
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
178
    {
179
        $this->new_x = $this->img_x + 2 * $border_width;
180
        $this->new_y = $this->img_y + 2 * $border_width;
181
182
        $new_img = $this->_createImage($new_x, $new_y, $this->true_color);
0 ignored issues
show
Bug introduced by
The property true_color does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The variable $new_x does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $new_y does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
183
184
        $options = array('pencilColor', $color);
185
        $color = $this->_getColor('pencilColor', $options, array(0, 0, 0));
186
        if ($color) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $color of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
187
            if ($this->true_color) {
188
                $c = imagecolorresolve($this->imageHandle, $color[0], $color[1], $color[2]);
189
                imagefill($new_img, 0, 0, $c);
190
            } else {
191
                imagecolorset($new_img, imagecolorat($new_img, 0, 0), $color[0], $color[1], $color[2]);
192
            }
193
        }
194
        ImageCopy($new_img, $this->imageHandle, $border_width, $border_width, 0, 0, $this->img_x, $this->img_y);
195
        $this->imageHandle = $new_img;
196
        $this->resized = true;
197
198
        return true;
199
    }
200
201
    /**
202
     * addText
203
     *
204
     * @param   array   $params     Array contains options
205
     *                              array(
206
     *                                  'text'  The string to draw
207
     *                                  'x'     Horizontal position
208
     *                                  'y'     Vertical Position
209
     *                                  'color' Font color
210
     *                                  'font'  Font to be used
211
     *                                  'size'  Size of the fonts in pixel
212
     *                                  'resize_first'  Tell if the image has to be resized
213
     *                                                  before drawing the text
214
     *                              )
215
     *
216
     * @return bool|PEAR_Error TRUE or a PEAR_Error object on error
217
     */
218
    function addText($params)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
219
    {
220
        $this->oldImage = $this->imageHandle;
221
        $params = array_merge($this->_get_default_text_params(), $params);
222
        extract($params);
223
224
        $options = array('fontColor' => $color);
225
        $color = $this->_getColor('fontColor', $options, array(0, 0, 0));
226
227
        $c = imagecolorresolve ($this->imageHandle, $color[0], $color[1], $color[2]);
228
229
        if ('ttf' == substr($font, -3)) {
230
            ImageTTFText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);
231
        } else {
232
            ImagePSText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);
233
        }
234
235
        return true;
236
    } // End addText
237
238
    /**
239
     * Rotates image by the given angle
240
     *
241
     * Uses a fast rotation algorythm for custom angles
242
     * or lines copy for multiple of 90 degrees
243
     *
244
     * @param int   $angle   Rotation angle
245
     * @param array $options array(
0 ignored issues
show
Documentation introduced by
Should the type for parameter $options not be array|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
246
     *                             'canvasColor' => array(r ,g, b), named color or #rrggbb
247
     *                            )
248
     * @author Pierre-Alain Joye
249
     * @return bool|PEAR_Error TRUE or a PEAR_Error object on error
250
     * @access public
251
     */
252
    function rotate($angle, $options = null)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
253
    {
254
        if (($angle % 360) == 0) {
255
            return true;
256
        }
257
258
        $color_mask = $this->_getColor('canvasColor', $options,
0 ignored issues
show
Bug introduced by
It seems like $options defined by parameter $options on line 252 can also be of type null; however, Image_Transform::_getColor() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
259
                                        array(255, 255, 255));
260
261
        $mask = imagecolorresolve($this->imageHandle, $color_mask[0], $color_mask[1], $color_mask[2]);
262
263
        $this->oldImage = $this->imageHandle;
264
265
        // Multiply by -1 to change the sign, so the image is rotated clockwise
266
        $this->imageHandle = ImageRotate($this->imageHandle, $angle * -1, $mask);
267
        return true;
268
    }
269
270
    /**
271
     * Horizontal mirroring
272
     *
273
     * @return mixed TRUE or PEAR_Error object on error
274
     * @access public
275
     * @see flip()
276
     **/
277 View Code Duplication
    function mirror()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
278
    {
279
        $new_img = $this->_createImage();
280
        for ($x = 0; $x < $this->new_x; ++$x) {
281
            imagecopy($new_img, $this->imageHandle, $x, 0,
282
                $this->new_x - $x - 1, 0, 1, $this->new_y);
283
        }
284
        imagedestroy($this->imageHandle);
285
        $this->imageHandle = $new_img;
286
        return true;
287
    }
288
289
    /**
290
     * Vertical mirroring
291
     *
292
     * @return TRUE or PEAR Error object on error
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
293
     * @access public
294
     * @see mirror()
295
     **/
296 View Code Duplication
    function flip()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
297
    {
298
        $new_img = $this->_createImage();
299
        for ($y = 0; $y < $this->new_y; ++$y) {
300
            imagecopy($new_img, $this->imageHandle, 0, $y,
301
                0, $this->new_y - $y - 1, $this->new_x, 1);
302
        }
303
        imagedestroy($this->imageHandle);
304
        $this->imageHandle = $new_img;
305
306
        /* for very large images we may want to use the following
0 ignored issues
show
Unused Code Comprehensibility introduced by
44% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
307
           Needs to find out what is the threshhold
308
        for ($x = 0; $x < $this->new_x; ++$x) {
309
            for ($y1 = 0; $y1 < $this->new_y / 2; ++$y1) {
310
                $y2 = $this->new_y - 1 - $y1;
311
                $color1 = imagecolorat($this->imageHandle, $x, $y1);
312
                $color2 = imagecolorat($this->imageHandle, $x, $y2);
313
                imagesetpixel($this->imageHandle, $x, $y1, $color2);
314
                imagesetpixel($this->imageHandle, $x, $y2, $color1);
315
            }
316
        } */
317
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type of the parent method Image_Transform::flip of type TRUE.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
318
    }
319
320
    /**
321
     * Crops image by size and start coordinates
322
     *
323
     * @param int width Cropped image width
324
     * @param int height Cropped image height
325
     * @param int x X-coordinate to crop at
326
     * @param int y Y-coordinate to crop at
327
     * @return bool|PEAR_Error TRUE or a PEAR_Error object on error
328
     * @access public
329
     */
330
    function crop($width, $height, $x = 0, $y = 0)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
331
    {
332
        // Sanity check
333
        if (!$this->intersects($width, $height, $x, $y)) {
334
            return PEAR::raiseError('Nothing to crop', IMAGE_TRANSFORM_ERROR_OUTOFBOUND);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
335
        }
336
        $x = min($this->new_x, max(0, $x));
337
        $y = min($this->new_y, max(0, $y));
338
        $width   = min($width,  $this->new_x - $x);
339
        $height  = min($height, $this->new_y - $y);
340
        $new_img = $this->_createImage($width, $height);
341
342
        if (!imagecopy($new_img, $this->imageHandle, 0, 0, $x, $y, $width, $height)) {
343
            imagedestroy($new_img);
344
            return PEAR::raiseError('Failed transformation: crop()',
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
345
                IMAGE_TRANSFORM_ERROR_FAILED);
346
        }
347
348
        $this->oldImage = $this->imageHandle;
349
        $this->imageHandle = $new_img;
350
        $this->resized = true;
351
352
        $this->new_x = $width;
353
        $this->new_y = $height;
354
        return true;
355
    }
356
357
    /**
358
     * Converts the image to greyscale
359
     *
360
     * @return bool|PEAR_Error TRUE or a PEAR_Error object on error
361
     * @access public
362
     */
363
    function greyscale() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
364
        imagecopymergegray($this->imageHandle, $this->imageHandle, 0, 0, 0, 0, $this->new_x, $this->new_y, 0);
365
        return true;
366
    }
367
368
    /**
369
     * Resize Action
370
     *
371
     * For GD 2.01+ the new copyresampled function is used
372
     * It uses a bicubic interpolation algorithm to get far
373
     * better result.
374
     *
375
     * @param int   $new_x   New width
376
     * @param int   $new_y   New height
377
     * @param array $options Optional parameters
0 ignored issues
show
Documentation introduced by
Should the type for parameter $options not be array|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
378
     * <ul>
379
     *  <li>'scaleMethod': "pixel" or "smooth"</li>
380
     * </ul>
381
     *
382
     * @return bool|PEAR_Error TRUE on success or PEAR_Error object on error
383
     * @access protected
384
     */
385
    function _resize($new_x, $new_y, $options = null)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
386
    {
387 View Code Duplication
        if ($this->resized === true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
388
            return PEAR::raiseError('You have already resized the image without saving it.  Your previous resizing will be overwritten', null, PEAR_ERROR_TRIGGER, E_USER_NOTICE);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
389
        }
390
391
        if ($this->new_x == $new_x && $this->new_y == $new_y) {
392
            return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type of the parent method Image_Transform::_resize of type PEAR_Error.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
393
        }
394
395
        $scaleMethod = $this->_getOption('scaleMethod', $options, 'smooth');
0 ignored issues
show
Bug introduced by
It seems like $options defined by parameter $options on line 385 can also be of type null; however, Image_Transform::_getOption() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
396
397
        // Make sure to get a true color image if doing resampled resizing
398
        // otherwise get the same type of image
399
        $trueColor = ($scaleMethod == 'pixel') ? null : true;
400
        $new_img = $this->_createImage($new_x, $new_y, $trueColor);
401
402
        $icr_res = null;
403
        if ($scaleMethod != 'pixel' && function_exists('ImageCopyResampled')) {
404
            $icr_res = ImageCopyResampled($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);
405
        }
406
        if (!$icr_res) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $icr_res of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
407
            ImageCopyResized($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);
408
        }
409
        $this->oldImage = $this->imageHandle;
410
        $this->imageHandle = $new_img;
411
        $this->resized = true;
412
413
        $this->new_x = $new_x;
414
        $this->new_y = $new_y;
415
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type of the parent method Image_Transform::_resize of type PEAR_Error.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
416
    }
417
418
    /**
419
     * Adjusts the image gamma
420
     *
421
     * @param float $outputgamma
422
     *
423
     * @return bool|PEAR_Error TRUE or a PEAR_Error object on error
424
     * @access public
425
     */
426
    function gamma($outputgamma = 1.0)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
427
    {
428
        if ($outputgamma != 1.0) {
429
            ImageGammaCorrect($this->imageHandle, 1.0, $outputgamma);
430
        }
431
        return true;
432
    }
433
434
    /**
435
     * Helper method to save to a file or output the image
436
     *
437
     * @param string $filename the name of the file to write to (blank to output)
438
     * @param string $types    define the output format, default
0 ignored issues
show
Bug introduced by
There is no parameter named $types. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
439
     *                          is the current used format
440
     * @param int    $quality  output DPI, default is 75
0 ignored issues
show
Documentation introduced by
Should the type for parameter $quality not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
441
     *
442
     * @return bool|PEAR_Error TRUE on success or PEAR_Error object on error
443
     * @access protected
444
     */
445
    function _generate($filename, $type = '', $quality = null)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
446
    {
447
        $type = strtolower(($type == '') ? $this->type : $type);
448
        $options = (is_array($quality)) ? $quality : array();
449
        switch ($type) {
450
            case 'jpg':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
451
                $type = 'jpeg';
452
            case 'jpeg':
453
                if (is_numeric($quality)) {
454
                    $options['quality'] = $quality;
455
                }
456
                $quality = $this->_getOption('quality', $options, 75);
457
                break;
458
        }
459
        if (!$this->supportsType($type, 'w')) {
460
            return PEAR::raiseError('Image type not supported for output',
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
461
                IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
462
        }
463
464
        if ($filename == '') {
465
            header('Content-type: ' . $this->getMimeType($type));
466
            $action = 'output image';
467
        } else {
468
            $action = 'save image to file';
469
        }
470
471
        $functionName = 'image' . $type;
472
        switch ($type) {
473
            case 'jpeg':
474
                $result = $functionName($this->imageHandle, $filename, $quality);
475
                break;
476
            default:
477
                if ($filename == '') {
478
                    $result = $functionName($this->imageHandle);
479
                } else {
480
                    $result = $functionName($this->imageHandle, $filename);
481
                }
482
        }
483
        if (!$result) {
484
            return PEAR::raiseError('Couldn\'t ' . $action,
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
485
                IMAGE_TRANSFORM_ERROR_IO);
486
        }
487
        $this->imageHandle = $this->oldImage;
488
        if (!$this->keep_settings_on_save) {
489
            $this->free();
490
        }
491
        return true;
492
493
    } // End save
494
495
    /**
496
     * Displays image without saving and lose changes.
497
     *
498
     * This method adds the Content-type HTTP header
499
     *
500
     * @param string $type (JPEG, PNG...);
501
     * @param int    $quality 75
0 ignored issues
show
Documentation introduced by
Should the type for parameter $quality not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
502
     *
503
     * @return bool|PEAR_Error TRUE or PEAR_Error object on error
504
     * @access public
505
     */
506
    function display($type = '', $quality = null)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
507
    {
508
        return $this->_generate('', $type, $quality);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->_generate('', $type, $quality); of type boolean|PEAR_Error adds the type boolean to the return on line 508 which is incompatible with the return type of the parent method Image_Transform::display of type PEAR_Error.
Loading history...
509
    }
510
511
    /**
512
     * Saves the image to a file
513
     *
514
     * @param string $filename the name of the file to write to
515
     * @param string $type     the output format, default
516
     *                          is the current used format
517
     * @param int    $quality  default is 75
0 ignored issues
show
Documentation introduced by
Should the type for parameter $quality not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
518
     *
519
     * @return bool|PEAR_Error TRUE on success or PEAR_Error object on error
520
     * @access public
521
     */
522
    function save($filename, $type = '', $quality = null)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
523
    {
524
        if (!trim($filename)) {
525
            return PEAR::raiseError('Filename missing',
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
526
                IMAGE_TRANSFORM_ERROR_ARGUMENT);
527
        }
528
        return $this->_generate($filename, $type, $quality);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->_generate($filename, $type, $quality); of type boolean|PEAR_Error adds the type boolean to the return on line 528 which is incompatible with the return type of the parent method Image_Transform::save of type PEAR_Error.
Loading history...
529
    }
530
531
    /**
532
     * Destroys image handle
533
     *
534
     * @access public
535
     */
536
    function free()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
537
    {
538
        $this->resized = false;
539
        if (is_resource($this->imageHandle)) {
540
            ImageDestroy($this->imageHandle);
541
        }
542
        $this->imageHandle = null;
543
        if (is_resource($this->oldImage)){
544
            ImageDestroy($this->oldImage);
545
        }
546
        $this->oldImage = null;
547
    }
548
549
    /**
550
     * Returns a new image for temporary processing
551
     *
552
     * @param int $width width of the new image
553
     * @param int $height height of the new image
554
     * @param bool $trueColor force which type of image to create
0 ignored issues
show
Documentation introduced by
Should the type for parameter $trueColor not be boolean|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
555
     * @return resource a GD image resource
556
     * @access protected
557
     */
558
    function _createImage($width = -1, $height = -1, $trueColor = null)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
559
    {
560
        if ($width == -1) {
561
            $width = $this->new_x;
562
        }
563
        if ($height == -1) {
564
            $height = $this->new_y;
565
        }
566
567
        $new_img = null;
568
        if (is_null($trueColor)) {
569
            if (function_exists('imageistruecolor')) {
570
                $createtruecolor = imageistruecolor($this->imageHandle);
571
            } else {
572
                $createtruecolor = true;
573
            }
574
        } else {
575
            $createtruecolor = $trueColor;
576
        }
577
        if ($createtruecolor
578
            && function_exists('ImageCreateTrueColor')) {
579
            $new_img = @ImageCreateTrueColor($width, $height);
580
            //GIF Transparent Patch
581
            if ($this->type!='gif') {
582
                imagealphablending($new_img, false);
583
                imagesavealpha($new_img, true);
584
            }
585
            //End GIF Transparent Patch
586
        }
587
        if (!$new_img) {
588
            $new_img = ImageCreate($width, $height);
589
            imagepalettecopy($new_img, $this->imageHandle);
590
            $color = imagecolortransparent($this->imageHandle);
591
            if ($color != -1) {
592
                imagecolortransparent($new_img, $color);
593
                imagefill($new_img, 0, 0, $color);
594
            }
595
        }
596
        
597
        //GIF Transparent Patch
598
        if ($this->type=='gif') {
599
            $transparencyIndex = imagecolortransparent($this->imageHandle);
600
            $transparencyColor = array('red' => 255, 'green' => 255, 'blue' => 255);
601
            
602
            if ($transparencyIndex >= 0) {
603
                $transparencyColor = imagecolorsforindex($this->imageHandle, $transparencyIndex);   
604
            }
605
           
606
            $transparencyIndex = imagecolorallocate($new_img, $transparencyColor['red'], $transparencyColor['green'], $transparencyColor['blue']);
607
            imagefill($new_img, 0, 0, $transparencyIndex);
608
            imagecolortransparent($new_img, $transparencyIndex);
609
        }
610
        //End GIF Transparent Patch
611
        
612
        
613
        return $new_img;
614
    }
615
}