Completed
Push — master ( e7d60a...f2d2e3 )
by Michael
02:44
created

imageLib::addWatermark()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 51

Duplication

Lines 51
Ratio 100 %

Importance

Changes 0
Metric Value
cc 3
nc 4
nop 4
dl 51
loc 51
rs 9.069
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
# ========================================================================#
3
#
4
#  This work is licensed under the Creative Commons Attribution 3.0 Unported
5
#  License. To view a copy of this license,
6
#  visit http://creativecommons.org/licenses/by/3.0/ or send a letter to
7
#  Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
8
#  94041, USA.
9
#
10
#  All rights reserved.
11
#
12
#  Author:    Jarrod Oberto
13
#  Version:   1.5.2
14
#  Purpose:   Provide tools for image manipulation using GD
15
#  Param In:  See functions.
16
#  Param Out: Produces a resized image
17
#  Requires : Requires PHP GD library.
18
#  Usage Example:
19
#                     include("lib/php_image_magician.php");
20
#                     $magicianObj = new imageLib('images/car.jpg');
21
#                     $magicianObj -> resizeImage(150, 100, 0);
22
#                     $magicianObj -> saveImage('images/car_small.jpg', 100);
23
#
24
#        - See end of doc for more examples -
25
#
26
#  Supported file types include: jpg, png, gif, bmp, psd (read)
27
#
28
#
29
#
30
#  The following functions are taken from phpThumb() [available from
31
#    http://phpthumb.sourceforge.net], and are used with written permission
32
#  from James Heinrich.
33
#    - GD2BMPstring
34
#      - GetPixelColor
35
#      - LittleEndian2String
36
#
37
#  The following functions are from Marc Hibbins and are used with written
38
#  permission (are also under the Attribution-ShareAlike
39
#  [http://creativecommons.org/licenses/by-sa/3.0/] license.
40
#    -
41
#
42
#  PhpPsdReader is used with written permission from Tim de Koning.
43
#  [http://www.kingsquare.nl/phppsdreader]
44
#
45
#
46
#
47
#  Known issues & Limitations:
48
# -------------------------------
49
#  Not so much an issue, the image is destroyed on the deconstruct rather than
50
#  when we have finished with it. The reason for this is that we don't know
51
#  when we're finished with it as you can both save the image and display
52
#  it directly to the screen (imagedestroy($this->imageResized))
53
#
54
#  Opening BMP files is slow. A test with 884 bmp files processed in a loop
55
#  takes forever - over 5 min. This test inlcuded opening the file, then
56
#  getting and displaying its width and height.
57
#
58
#  $forceStretch:
59
# -------------------------------
60
#  On by default.
61
#  $forceStretch can be disabled by calling method setForceStretch with false
62
#  parameter. If disabled, if an images original size is smaller than the size
63
#  specified by the user, the original size will be used. This is useful when
64
#  dealing with small images.
65
#
66
#  If enabled, images smaller than the size specified will be stretched to
67
#  that size.
68
#
69
#  Tips:
70
# -------------------------------
71
#  * If you're resizing a transparent png and saving it as a jpg, set
72
#  $keepTransparency to false with: $magicianObj->setTransparency(false);
73
#
74
#  FEATURES:
75
#    * EASY TO USE
76
#    * BMP SUPPORT (read & write)
77
#    * PSD (photoshop) support (read)
78
#    * RESIZE IMAGES
79
#      - Preserve transparency (png, gif)
80
#      - Apply sharpening (jpg) (requires PHP >= 5.1.0)
81
#      - Set image quality (jpg, png)
82
#      - Resize modes:
83
#        - exact size
84
#        - resize by width (auto height)
85
#        - resize by height (auto width)
86
#        - auto (automatically determine the best of the above modes to use)
87
#        - crop - resize as best as it can then crop the rest
88
#      - Force stretching of smaller images (upscale)
89
#    * APPLY FILTERS
90
#      - Convert to grey scale
91
#      - Convert to black and white
92
#      - Convert to sepia
93
#      - Convert to negative
94
#    * ROTATE IMAGES
95
#      - Rotate using predefined "left", "right", or "180"; or any custom degree amount
96
#    * EXTRACT EXIF DATA (requires exif module)
97
#      - make
98
#      - model
99
#      - date
100
#      - exposure
101
#      - aperture
102
#      - f-stop
103
#      - iso
104
#      - focal length
105
#      - exposure program
106
#      - metering mode
107
#      - flash status
108
#      - creator
109
#      - copyright
110
#    * ADD WATERMARK
111
#      - Specify exact x, y placement
112
#      - Or, specify using one of the 9 pre-defined placements such as "tl"
113
#        (for top left), "m" (for middle), "br" (for bottom right)
114
#        - also specify padding from edge amount (optional).
115
#      - Set opacity of watermark (png).
116
#    * ADD BORDER
117
#    * USE HEX WHEN SPECIFYING COLORS (eg: #ffffff)
118
#    * SAVE IMAGE OR OUTPUT TO SCREEN
119
#
120
#
121
# ========================================================================#
122
123 View Code Duplication
class imageLib
0 ignored issues
show
Duplication introduced by
This class 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...
124
{
125
126
    private   $fileName;
127
    private   $image;
128
    protected $imageResized;
129
    private   $widthOriginal;     # Always be the original width
130
    private   $heightOriginal;
131
    private   $width;         # Current width (width after resize)
132
    private   $height;
133
    private   $imageSize;
134
    private   $fileExtension;
135
136
    private $isImage = false;
137
138
    private $debug      = true;
139
    private $errorArray = [];
140
141
    private $forceStretch        = true;
142
    private $aggresiveSharpening = false;
143
144
    private $transparentArray = ['.png', '.gif'];
145
    private $keepTransparency = true;
146
    private $fillColorArray   = ['r' => 255, 'g' => 255, 'b' => 255];
147
148
    private $sharpenArray = ['jpg'];
149
150
    private $psdReaderPath;
151
    private $filterOverlayPath;
152
153
    private $isInterlace;
154
155
    private $captionBoxPositionArray = [];
156
157
    private $fontDir = 'fonts';
158
159
    private $cropFromTopPercent = 10;
160
161
    ## --------------------------------------------------------
162
163
    public function __construct($fileName)
164
        # Author:     Jarrod Oberto
165
        # Date:       27-02-08
166
        # Purpose:    Constructor
167
        # Param in:   $fileName: File name and path.
168
        # Param out:  n/a
169
        # Reference:
170
        # Notes:
171
        #
172
    {
173
        if (!$this->testGDInstalled()) {
174
            if ($this->debug) {
175
                die('The GD Library is not installed.');
176
            } else {
177
                die();
178
            }
179
        }
180
181
        $this->initialise();
182
183
        // *** Save the image file name. Only store this incase you want to display it
184
        $this->fileName      = $fileName;
185
        $this->fileExtension = strtolower(strrchr($fileName, '.'));
186
187
        // *** Open up the file
188
        try {
189
            $this->image = $this->openImage($fileName);
190
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
191
        }
192
193
        // *** Assign here so we don't modify the original
194
        $this->imageResized = $this->image;
195
196
        // *** If file is an image
197
        $this->isImage = $this->testIsImage();
198
199
        if ($this->isImage) {
200
            // *** Get width and height
201
            $this->width          = imagesx($this->image);
202
            $this->widthOriginal  = imagesx($this->image);
203
            $this->height         = imagesy($this->image);
204
            $this->heightOriginal = imagesy($this->image);
205
206
            /*  Added 15-09-08
207
             *  Get the filesize using this build in method.
208
             *  Stores an array of size
209
             *
210
             *  $this->imageSize[1] = width
211
             *  $this->imageSize[2] = height
212
             *  $this->imageSize[3] = width x height
213
             *
214
             */
215
            $this->imageSize = getimagesize($this->fileName);
216
        } else {
217
            $this->errorArray[] = 'File is not an image';
218
        }
219
    }
220
221
    ## --------------------------------------------------------
222
223
    private function initialise()
224
    {
225
        $this->psdReaderPath     = __DIR__ . '/classPhpPsdReader.php';
226
        $this->filterOverlayPath = __DIR__ . '/filters';
227
228
        // *** Set if image should be interlaced or not.
229
        $this->isInterlace = false;
230
    }
231
232
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
233
        Resize
234
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
235
236
    public function resizeImage($newWidth, $newHeight, $option = 0, $sharpen = false, $autoRotate = true)
237
        # Author:     Jarrod Oberto
238
        # Date:       27-02-08
239
        # Purpose:    Resizes the image
240
        # Param in:   $newWidth:
241
        #             $newHeight:
242
        #             $option:     0 / exact = defined size;
243
        #                          1 / portrait = keep aspect set height;
244
        #                          2 / landscape = keep aspect set width;
245
        #                          3 / auto = auto;
246
        #                          4 / crop= resize and crop;
247
        #
248
        #         $option can also be an array containing options for
249
        #         cropping. E.G., array('crop', 'r')
250
        #
251
        #         This array only applies to 'crop' and the 'r' refers to
252
        #         "crop right". Other value include; tl, t, tr, l, m (default),
253
        #         r, bl, b, br, or you can specify your own co-ords (which
254
        #         isn't recommended.
255
        #
256
        #       $sharpen:    true: sharpen (jpg only);
257
        #                false: don't sharpen
258
        # Param out:  n/a
259
        # Reference:
260
        # Notes:      To clarify the $option input:
261
        #               0 = The exact height and width dimensions you set.
262
        #               1 = Whatever height is passed in will be the height that
263
        #                   is set. The width will be calculated and set automatically
264
        #                   to a the value that keeps the original aspect ratio.
265
        #               2 = The same but based on the width. We try make the image the
266
        #                  biggest size we can while stil fitting inside the box size
267
        #               3 = Depending whether the image is landscape or portrait, this
268
        #                   will automatically determine whether to resize via
269
        #                   dimension 1,2 or 0
270
        #               4 = Will resize and then crop the image for best fit
271
        #
272
        #       forceStretch can be applied to options 1,2,3 and 4
273
        #
274
    {
275
        // *** We can pass in an array of options to change the crop position
276
        $cropPos = 'm';
277
        if (is_array($option) && 'crop' === strtolower($option[0])) {
278
            $cropPos = $option[1];         # get the crop option
279
        } elseif (false !== strpos($option, '-')) {
280
            // *** Or pass in a hyphen seperated option
281
            $optionPiecesArray = explode('-', $option);
282
            $cropPos           = end($optionPiecesArray);
283
        }
284
285
        // *** Check the option is valid
286
        try {
287
            $option = $this->prepOption($option);
288
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
289
        }
290
291
        // *** Make sure the file passed in is valid
292
        if (!$this->image) {
293
            if ($this->debug) {
294
                die('file ' . $this->getFileName() . ' is missing or invalid');
295
            } else {
296
                die();
297
            }
298
        }
299
300
        // *** Get optimal width and height - based on $option
301
        $dimensionsArray = $this->getDimensions($newWidth, $newHeight, $option);
302
303
        $optimalWidth  = $dimensionsArray['optimalWidth'];
304
        $optimalHeight = $dimensionsArray['optimalHeight'];
305
306
        // *** Resample - create image canvas of x, y size
307
        $this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight);
308
        $this->keepTransparancy($optimalWidth, $optimalHeight, $this->imageResized);
309
        imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height);
310
311
        // *** If '4', then crop too
312
        if (4 == $option || 'crop' === $option) {
313
            if (($optimalWidth >= $newWidth && $optimalHeight >= $newHeight)) {
314
                $this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
315
            }
316
        }
317
318
        // *** If Rotate.
319
        if ($autoRotate) {
320
            try {
321
                $exifData = $this->getExif(false);
322
            } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
323
            }
324
            if (count($exifData) > 0) {
325
                switch ($exifData['orientation']) {
326
                    case 8:
327
                        $this->imageResized = imagerotate($this->imageResized, 90, 0);
328
                        break;
329
                    case 3:
330
                        $this->imageResized = imagerotate($this->imageResized, 180, 0);
331
                        break;
332
                    case 6:
333
                        $this->imageResized = imagerotate($this->imageResized, -90, 0);
334
                        break;
335
                }
336
            }
337
        }
338
339
        // *** Sharpen image (if jpg and the user wishes to do so)
340
        if ($sharpen && in_array($this->fileExtension, $this->sharpenArray)) {
341
            // *** Sharpen
342
            try {
343
                $this->sharpen();
344
            } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
345
            }
346
        }
347
    }
348
349
    ## --------------------------------------------------------
350
351
    public function cropImage($newWidth, $newHeight, $cropPos = 'm')
352
        # Author:     Jarrod Oberto
353
        # Date:       08-09-11
354
        # Purpose:    Crops the image
355
        # Param in:   $newWidth: crop with
356
        #             $newHeight: crop height
357
        #             $cropPos: Can be any of the following:
358
        #                   tl, t, tr, l, m, r, bl, b, br, auto
359
        #             Or:
360
        #                   a custom position such as '30x50'
361
        # Param out:  n/a
362
        # Reference:
363
        # Notes:
364
        #
365
    {
366
        // *** Make sure the file passed in is valid
367
        if (!$this->image) {
368
            if ($this->debug) {
369
                die('file ' . $this->getFileName() . ' is missing or invalid');
370
            } else {
371
                die();
372
            }
373
        }
374
375
        $this->imageResized = $this->image;
376
        $this->crop($this->width, $this->height, $newWidth, $newHeight, $cropPos);
377
    }
378
379
    ## --------------------------------------------------------
380
381
    private function keepTransparancy($width, $height, $im)
382
        # Author:     Jarrod Oberto
383
        # Date:       08-04-11
384
        # Purpose:    Keep transparency for png and gif image
385
        # Param in:
386
        # Param out:  n/a
387
        # Reference:
388
        # Notes:
389
        #
390
    {
391
        // *** If PNG, perform some transparency retention actions (gif untested)
392
        if (in_array($this->fileExtension, $this->transparentArray) && $this->keepTransparency) {
393
            imagealphablending($im, false);
394
            imagesavealpha($im, true);
395
            $transparent = imagecolorallocatealpha($im, 255, 255, 255, 127);
396
            imagefilledrectangle($im, 0, 0, $width, $height, $transparent);
397
        } else {
398
            $color = imagecolorallocate($im, $this->fillColorArray['r'], $this->fillColorArray['g'], $this->fillColorArray['b']);
399
            imagefilledrectangle($im, 0, 0, $width, $height, $color);
400
        }
401
    }
402
403
    ## --------------------------------------------------------
404
405
    private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos)
406
        # Author:     Jarrod Oberto
407
        # Date:       15-09-08
408
        # Purpose:    Crops the image
409
        # Param in:   $newWidth:
410
        #             $newHeight:
411
        # Param out:  n/a
412
        # Reference:
413
        # Notes:
414
        #
415
    {
416
        // *** Get cropping co-ordinates
417
        $cropArray  = $this->getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
418
        $cropStartX = $cropArray['x'];
419
        $cropStartY = $cropArray['y'];
420
421
        // *** Crop this bad boy
422
        $crop = imagecreatetruecolor($newWidth, $newHeight);
423
        $this->keepTransparancy($optimalWidth, $optimalHeight, $crop);
424
        imagecopyresampled($crop, $this->imageResized, 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight, $newWidth, $newHeight);
425
426
        $this->imageResized = $crop;
427
428
        // *** Set new width and height to our variables
429
        $this->width  = $newWidth;
430
        $this->height = $newHeight;
431
    }
432
433
    ## --------------------------------------------------------
434
435
    private function getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $pos = 'm')
436
        #
437
        # Author:   Jarrod Oberto
438
        # Date:   July 11
439
        # Purpose:  Set the cropping area.
440
        # Params in:
441
        # Params out: (array) the crop x and y co-ordinates.
442
        # Notes:    When specifying the exact pixel crop position (eg 10x15), be
443
        #       very careful as it's easy to crop out of the image leaving
444
        #       black borders.
445
        #
446
    {
447
        $pos = strtolower($pos);
448
449
        // *** If co-ords have been entered
450
        if (strstr($pos, 'x')) {
451
            $pos = str_replace(' ', '', $pos);
452
453
            $xyArray = explode('x', $pos);
454
            list($cropStartX, $cropStartY) = $xyArray;
455
        } else {
456
            switch ($pos) {
457
                case 'tl':
458
                    $cropStartX = 0;
459
                    $cropStartY = 0;
460
                    break;
461
462
                case 't':
463
                    $cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
464
                    $cropStartY = 0;
465
                    break;
466
467
                case 'tr':
468
                    $cropStartX = $optimalWidth - $newWidth;
469
                    $cropStartY = 0;
470
                    break;
471
472
                case 'l':
473
                    $cropStartX = 0;
474
                    $cropStartY = ($optimalHeight / 2) - ($newHeight / 2);
475
                    break;
476
477
                case 'm':
478
                    $cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
479
                    $cropStartY = ($optimalHeight / 2) - ($newHeight / 2);
480
                    break;
481
482
                case 'r':
483
                    $cropStartX = $optimalWidth - $newWidth;
484
                    $cropStartY = ($optimalHeight / 2) - ($newHeight / 2);
485
                    break;
486
487
                case 'bl':
488
                    $cropStartX = 0;
489
                    $cropStartY = $optimalHeight - $newHeight;
490
                    break;
491
492
                case 'b':
493
                    $cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
494
                    $cropStartY = $optimalHeight - $newHeight;
495
                    break;
496
497
                case 'br':
498
                    $cropStartX = $optimalWidth - $newWidth;
499
                    $cropStartY = $optimalHeight - $newHeight;
500
                    break;
501
502
                case 'auto':
503
                    // *** If image is a portrait crop from top, not center. v1.5
504
                    if ($optimalHeight > $optimalWidth) {
505
                        $cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
506
                        $cropStartY = ($this->cropFromTopPercent / 100) * $optimalHeight;
507
                    } else {
508
                        // *** Else crop from the center
509
                        $cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
510
                        $cropStartY = ($optimalHeight / 2) - ($newHeight / 2);
511
                    }
512
                    break;
513
514
                default:
515
                    // *** Default to center
516
                    $cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
517
                    $cropStartY = ($optimalHeight / 2) - ($newHeight / 2);
518
                    break;
519
            }
520
        }
521
522
        return ['x' => $cropStartX, 'y' => $cropStartY];
523
    }
524
525
    ## --------------------------------------------------------
526
527
    private function getDimensions($newWidth, $newHeight, $option)
528
        # Author:     Jarrod Oberto
529
        # Date:       17-11-09
530
        # Purpose:    Get new image dimensions based on user specificaions
531
        # Param in:   $newWidth:
532
        #             $newHeight:
533
        # Param out:  Array of new width and height values
534
        # Reference:
535
        # Notes:      If $option = 3 then this function is call recursivly
536
        #
537
        #       To clarify the $option input:
538
        #               0 = The exact height and width dimensions you set.
539
        #               1 = Whatever height is passed in will be the height that
540
        #                   is set. The width will be calculated and set automatically
541
        #                   to a the value that keeps the original aspect ratio.
542
        #               2 = The same but based on the width.
543
        #               3 = Depending whether the image is landscape or portrait, this
544
        #                   will automatically determine whether to resize via
545
        #                   dimension 1,2 or 0.
546
        #               4 = Resize the image as much as possible, then crop the
547
        #         remainder.
548
    {
549
        switch ((string)$option) {
550
            case '0':
551
            case 'exact':
552
                $optimalWidth  = $newWidth;
553
                $optimalHeight = $newHeight;
554
                break;
555
            case '1':
556
            case 'portrait':
557
                $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
558
                $optimalWidth    = $dimensionsArray['optimalWidth'];
559
                $optimalHeight   = $dimensionsArray['optimalHeight'];
560
                break;
561
            case '2':
562
            case 'landscape':
563
                $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
564
                $optimalWidth    = $dimensionsArray['optimalWidth'];
565
                $optimalHeight   = $dimensionsArray['optimalHeight'];
566
                break;
567
            case '3':
568
            case 'auto':
569
                $dimensionsArray = $this->getSizeByAuto($newWidth, $newHeight);
570
                $optimalWidth    = $dimensionsArray['optimalWidth'];
571
                $optimalHeight   = $dimensionsArray['optimalHeight'];
572
                break;
573
            case '4':
574
            case 'crop':
575
                $dimensionsArray = $this->getOptimalCrop($newWidth, $newHeight);
576
                $optimalWidth    = $dimensionsArray['optimalWidth'];
577
                $optimalHeight   = $dimensionsArray['optimalHeight'];
578
                break;
579
        }
580
581
        return ['optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight];
0 ignored issues
show
Bug introduced by
The variable $optimalWidth does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $optimalHeight does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
582
    }
583
584
    ## --------------------------------------------------------
585
586
    private function getSizeByFixedHeight($newWidth, $newHeight)
0 ignored issues
show
Unused Code introduced by
The parameter $newWidth is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
587
    {
588
        // *** If forcing is off...
589
        if (!$this->forceStretch) {
590
            // *** ...check if actual height is less than target height
591
            if ($this->height < $newHeight) {
592
                return ['optimalWidth' => $this->width, 'optimalHeight' => $this->height];
593
            }
594
        }
595
596
        $ratio = $this->width / $this->height;
597
598
        $newWidth = $newHeight * $ratio;
599
600
        //return $newWidth;
601
        return ['optimalWidth' => $newWidth, 'optimalHeight' => $newHeight];
602
    }
603
604
    ## --------------------------------------------------------
605
606
    private function getSizeByFixedWidth($newWidth, $newHeight)
0 ignored issues
show
Unused Code introduced by
The parameter $newHeight is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
607
    {
608
        // *** If forcing is off...
609
        if (!$this->forceStretch) {
610
            // *** ...check if actual width is less than target width
611
            if ($this->width < $newWidth) {
612
                return ['optimalWidth' => $this->width, 'optimalHeight' => $this->height];
613
            }
614
        }
615
616
        $ratio = $this->height / $this->width;
617
618
        $newHeight = $newWidth * $ratio;
619
620
        //return $newHeight;
621
        return ['optimalWidth' => $newWidth, 'optimalHeight' => $newHeight];
622
    }
623
624
    ## --------------------------------------------------------
625
626
    private function getSizeByAuto($newWidth, $newHeight)
627
        # Author:     Jarrod Oberto
628
        # Date:       19-08-08
629
        # Purpose:    Depending on the height, choose to resize by 0, 1, or 2
630
        # Param in:   The new height and new width
631
        # Notes:
632
        #
633
    {
634
        // *** If forcing is off...
635
        if (!$this->forceStretch) {
636
            // *** ...check if actual size is less than target size
637
            if ($this->width < $newWidth && $this->height < $newHeight) {
638
                return ['optimalWidth' => $this->width, 'optimalHeight' => $this->height];
639
            }
640
        }
641
642
        if ($this->height < $this->width) // *** Image to be resized is wider (landscape)
643
        {
644
            //$optimalWidth = $newWidth;
645
            //$optimalHeight= $this->getSizeByFixedWidth($newWidth);
646
647
            $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
648
            $optimalWidth    = $dimensionsArray['optimalWidth'];
649
            $optimalHeight   = $dimensionsArray['optimalHeight'];
650
        } elseif ($this->height > $this->width) // *** Image to be resized is taller (portrait)
651
        {
652
            //$optimalWidth = $this->getSizeByFixedHeight($newHeight);
653
            //$optimalHeight= $newHeight;
654
655
            $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
656
            $optimalWidth    = $dimensionsArray['optimalWidth'];
657
            $optimalHeight   = $dimensionsArray['optimalHeight'];
658
        } else // *** Image to be resizerd is a square
659
        {
660
            if ($newHeight < $newWidth) {
661
                //$optimalWidth = $newWidth;
662
                //$optimalHeight= $this->getSizeByFixedWidth($newWidth);
663
                $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
664
                $optimalWidth    = $dimensionsArray['optimalWidth'];
665
                $optimalHeight   = $dimensionsArray['optimalHeight'];
666
            } elseif ($newHeight > $newWidth) {
667
                //$optimalWidth = $this->getSizeByFixedHeight($newHeight);
668
                //$optimalHeight= $newHeight;
669
                $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
670
                $optimalWidth    = $dimensionsArray['optimalWidth'];
671
                $optimalHeight   = $dimensionsArray['optimalHeight'];
672
            } else {
673
                // *** Sqaure being resized to a square
674
                $optimalWidth  = $newWidth;
675
                $optimalHeight = $newHeight;
676
            }
677
        }
678
679
        return ['optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight];
680
    }
681
682
    ## --------------------------------------------------------
683
684
    private function getOptimalCrop($newWidth, $newHeight)
685
        # Author:     Jarrod Oberto
686
        # Date:       17-11-09
687
        # Purpose:    Get optimal crop dimensions
688
        # Param in:   width and height as requested by user (fig 3)
689
        # Param out:  Array of optimal width and height (fig 2)
690
        # Reference:
691
        # Notes:      The optimal width and height return are not the same as the
692
        #             same as the width and height passed in. For example:
693
        #
694
        #
695
        #   |-----------------|     |------------|       |-------|
696
        #   |                 | =>  |**|      |**|   =>  |       |
697
        #   |                 |     |**|      |**|       |       |
698
        #   |                 |     |------------|       |-------|
699
        #   |-----------------|
700
        #        original                optimal             crop
701
        #          size                   size               size
702
        #  Fig      1                      2                  3
703
        #
704
        #       300 x 250           150 x 125          150 x 100
705
        #
706
        #  The optimal size is the smallest size (that is closest to the crop size)
707
        #  while retaining proportion/ratio.
708
        #
709
        #  The crop size is the optimal size that has been cropped on one axis to
710
        #  make the image the exact size specified by the user.
711
        #
712
        #      * represent cropped area
713
        #
714
    {
715
        // *** If forcing is off...
716
        if (!$this->forceStretch) {
717
            // *** ...check if actual size is less than target size
718
            if ($this->width < $newWidth && $this->height < $newHeight) {
719
                return ['optimalWidth' => $this->width, 'optimalHeight' => $this->height];
720
            }
721
        }
722
723
        $heightRatio = $this->height / $newHeight;
724
        $widthRatio  = $this->width / $newWidth;
725
726
        if ($heightRatio < $widthRatio) {
727
            $optimalRatio = $heightRatio;
728
        } else {
729
            $optimalRatio = $widthRatio;
730
        }
731
732
        $optimalHeight = round($this->height / $optimalRatio);
733
        $optimalWidth  = round($this->width / $optimalRatio);
734
735
        return ['optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight];
736
    }
737
738
    ## --------------------------------------------------------
739
740
    private function sharpen()
741
        # Author:     Jarrod Oberto
742
        # Date:       08 04 2011
743
        # Purpose:    Sharpen image
744
        # Param in:   n/a
745
        # Param out:  n/a
746
        # Reference:
747
        # Notes:
748
        # Credit:   Incorporates Joe Lencioni (August 6, 2008) code
749
    {
750
        if (version_compare(PHP_VERSION, '5.1.0') >= 0) {
751
            // ***
752
            if ($this->aggresiveSharpening) { # A more aggressive sharpening solution
753
754
                $sharpenMatrix = [
755
                    [-1, -1, -1],
756
                    [-1, 16, -1],
757
                    [-1, -1, -1]
758
                ];
759
                $divisor       = 8;
760
                $offset        = 0;
761
762
                imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
763
            } else # More subtle and personally more desirable
764
            {
765
                $sharpness = $this->findSharp($this->widthOriginal, $this->width);
766
767
                $sharpenMatrix = [
768
                    [-1, -2, -1],
769
                    [-2, $sharpness + 12, -2], //Lessen the effect of a filter by increasing the value in the center cell
770
                    [-1, -2, -1]
771
                ];
772
                $divisor       = $sharpness; // adjusts brightness
773
                $offset        = 0;
774
                imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
775
            }
776
        } else {
777
            if ($this->debug) {
778
                die('Sharpening required PHP 5.1.0 or greater.');
779
            }
780
        }
781
    }
782
783
    ## --------------------------------------------------------
784
785
    private function sharpen2($level)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
786
    {
787
        $sharpenMatrix = [
0 ignored issues
show
Unused Code introduced by
$sharpenMatrix is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
788
            [$level, $level, $level],
789
            [$level, (8 * $level) + 1, $level], //Lessen the effect of a filter by increasing the value in the center cell
790
            [$level, $level, $level]
791
        ];
792
    }
793
794
    ## --------------------------------------------------------
795
796
    private function findSharp($orig, $final)
797
        # Author:     Ryan Rud (http://adryrun.com)
798
        # Purpose:    Find optimal sharpness
799
        # Param in:   n/a
800
        # Param out:  n/a
801
        # Reference:
802
        # Notes:
803
        #
804
    {
805
        $final = $final * (750.0 / $orig);
806
        $a     = 52;
807
        $b     = -0.27810650887573124;
808
        $c     = .00047337278106508946;
809
810
        $result = $a + $b * $final + $c * $final * $final;
811
812
        return max(round($result), 0);
813
    }
814
815
    ## --------------------------------------------------------
816
817
    private function prepOption($option)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
818
        # Author:     Jarrod Oberto
819
        # Purpose:    Prep option like change the passed in option to lowercase
820
        # Param in:   (str/int) $option: eg. 'exact', 'crop'. 0, 4
821
        # Param out:  lowercase string
822
        # Reference:
823
        # Notes:
824
        #
825
    {
826
        if (is_array($option)) {
827
            if ('crop' === strtolower($option[0]) && 2 == count($option)) {
828
                return 'crop';
829
            } else {
830
                die('Crop resize option array is badly formatted.');
831
            }
832
        } elseif (false !== strpos($option, 'crop')) {
833
            return 'crop';
834
        }
835
836
        if (is_string($option)) {
837
            return strtolower($option);
838
        }
839
840
        return $option;
841
    }
842
843
844
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
845
        Presets
846
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
847
848
    #
849
    # Preset are pre-defined templates you can apply to your image.
850
    #
851
    # These are inteded to be applied to thumbnail images.
852
    #
853
854
    public function borderPreset($preset)
855
    {
856
        switch ($preset) {
857
            case 'simple':
858
                $this->addBorder(7, '#fff');
0 ignored issues
show
Documentation introduced by
'#fff' is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
859
                $this->addBorder(6, '#f2f1f0');
0 ignored issues
show
Documentation introduced by
'#f2f1f0' is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
860
                $this->addBorder(2, '#fff');
0 ignored issues
show
Documentation introduced by
'#fff' is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
861
                $this->addBorder(1, '#ccc');
0 ignored issues
show
Documentation introduced by
'#ccc' is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
862
                break;
863
            default:
864
                break;
865
        }
866
    }
867
868
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
869
        Draw border
870
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
871
872
    public function addBorder($thickness = 1, $rgbArray = [255, 255, 255])
873
        # Author:     Jarrod Oberto
874
        # Date:       05-05-11
875
        # Purpose:    Add a border to the image
876
        # Param in:
877
        # Param out:
878
        # Reference:
879
        # Notes:    This border is added to the INSIDE of the image
880
        #
881
    {
882
        if ($this->imageResized) {
883
            $rgbArray = $this->formatColor($rgbArray);
884
            $r        = $rgbArray['r'];
885
            $g        = $rgbArray['g'];
886
            $b        = $rgbArray['b'];
887
888
            $x1 = 0;
889
            $y1 = 0;
890
            $x2 = imagesx($this->imageResized) - 1;
891
            $y2 = imagesy($this->imageResized) - 1;
892
893
            $rgbArray = imagecolorallocate($this->imageResized, $r, $g, $b);
894
895
            for ($i = 0; $i < $thickness; ++$i) {
896
                imagerectangle($this->imageResized, ++$x1, ++$y1, $x2--, $y2--, $rgbArray);
897
            }
898
        }
899
    }
900
901
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
902
        Gray Scale
903
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
904
905
    public function greyScale()
906
        # Author:     Jarrod Oberto
907
        # Date:       07-05-2011
908
        # Purpose:    Make image greyscale
909
        # Param in:   n/a
910
        # Param out:
911
        # Reference:
912
        # Notes:
913
        #
914
    {
915
        if ($this->imageResized) {
916
            imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
917
        }
918
    }
919
920
    ## --------------------------------------------------------
921
922
    public function greyScaleEnhanced()
923
        # Author:     Jarrod Oberto
924
        # Date:       07-05-2011
925
        # Purpose:    Make image greyscale
926
        # Param in:   n/a
927
        # Param out:
928
        # Reference:
929
        # Notes:
930
        #
931
    {
932
        if ($this->imageResized) {
933
            imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
934
            imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
935
            imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 2);
936
            try {
937
                $this->sharpen($this->width);
0 ignored issues
show
Unused Code introduced by
The call to imageLib::sharpen() has too many arguments starting with $this->width.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
938
            } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
939
            }
940
        }
941
    }
942
943
    ## --------------------------------------------------------
944
945
    public function greyScaleDramatic()
946
        # Alias of gd_filter_monopin
947
    {
948
        $this->gd_filter_monopin();
949
    }
950
951
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
952
        Black 'n White
953
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
954
955
    public function blackAndWhite()
956
        # Author:     Jarrod Oberto
957
        # Date:       07-05-2011
958
        # Purpose:    Make image black and white
959
        # Param in:   n/a
960
        # Param out:
961
        # Reference:
962
        # Notes:
963
        #
964
    {
965
        if ($this->imageResized) {
966
            imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
967
            imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -1000);
968
        }
969
    }
970
971
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
972
        Negative
973
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
974
975
    public function negative()
976
        # Author:     Jarrod Oberto
977
        # Date:       07-05-2011
978
        # Purpose:    Make image negative
979
        # Param in:   n/a
980
        # Param out:
981
        # Reference:
982
        # Notes:
983
        #
984
    {
985
        if ($this->imageResized) {
986
            imagefilter($this->imageResized, IMG_FILTER_NEGATE);
987
        }
988
    }
989
990
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
991
        Sepia
992
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
993
994
    public function sepia()
995
        # Author:     Jarrod Oberto
996
        # Date:       07-05-2011
997
        # Purpose:    Make image sepia
998
        # Param in:   n/a
999
        # Param out:
1000
        # Reference:
1001
        # Notes:
1002
        #
1003
    {
1004
        if ($this->imageResized) {
1005
            imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
1006
            imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -10);
1007
            imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -20);
1008
            imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, 30, -15);
1009
        }
1010
    }
1011
1012
    ## --------------------------------------------------------
1013
1014
    public function sepia2()
1015
    {
1016
        if ($this->imageResized) {
1017
            $total = imagecolorstotal($this->imageResized);
1018
            for ($i = 0; $i < $total; ++$i) {
1019
                $index = imagecolorsforindex($this->imageResized, $i);
1020
                $red   = ($index['red'] * 0.393 + $index['green'] * 0.769 + $index['blue'] * 0.189) / 1.351;
1021
                $green = ($index['red'] * 0.349 + $index['green'] * 0.686 + $index['blue'] * 0.168) / 1.203;
1022
                $blue  = ($index['red'] * 0.272 + $index['green'] * 0.534 + $index['blue'] * 0.131) / 2.140;
1023
                imagecolorset($this->imageResized, $i, $red, $green, $blue);
1024
            }
1025
        }
1026
    }
1027
1028
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1029
        Vintage
1030
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1031
1032
    public function vintage()
1033
        # Alias of gd_filter_monopin
1034
    {
1035
        $this->gd_filter_vintage();
1036
    }
1037
1038
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1039
        Presets By Marc Hibbins
1040
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1041
1042
    /** Apply 'Monopin' preset */
1043
    public function gd_filter_monopin()
1044
    {
1045
        if ($this->imageResized) {
1046
            imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
1047
            imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -15);
1048
            imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
1049
            $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 100);
1050
        }
1051
    }
1052
1053
    ## --------------------------------------------------------
1054
1055
    public function gd_filter_vintage()
1056
    {
1057
        if ($this->imageResized) {
1058
            $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 45);
1059
            imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 20);
1060
            imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -35);
1061
            imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, -10, 35);
1062
            imagefilter($this->imageResized, IMG_FILTER_SMOOTH, 7);
1063
            $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'scratch', 10);
1064
        }
1065
    }
1066
1067
    ## --------------------------------------------------------
1068
1069
    /** Apply a PNG overlay
1070
     * @param $im
1071
     * @param $type
1072
     * @param $amount
1073
     * @return mixed
1074
     */
1075
    private function gd_apply_overlay($im, $type, $amount)
1076
        #
1077
        # Original Author:    Marc Hibbins
1078
        # License:  Attribution-ShareAlike 3.0
1079
        # Purpose:
1080
        # Params in:
1081
        # Params out:
1082
        # Notes:
1083
        #
1084
    {
1085
        $width  = imagesx($im);
1086
        $height = imagesy($im);
1087
        $filter = imagecreatetruecolor($width, $height);
1088
1089
        imagealphablending($filter, false);
1090
        imagesavealpha($filter, true);
1091
1092
        $transparent = imagecolorallocatealpha($filter, 255, 255, 255, 127);
1093
        imagefilledrectangle($filter, 0, 0, $width, $height, $transparent);
1094
1095
        // *** Resize overlay
1096
        $overlay = $this->filterOverlayPath . '/' . $type . '.png';
1097
        $png     = imagecreatefrompng($overlay);
1098
        imagecopyresampled($filter, $png, 0, 0, 0, 0, $width, $height, imagesx($png), imagesy($png));
1099
1100
        $comp = imagecreatetruecolor($width, $height);
1101
        imagecopy($comp, $im, 0, 0, 0, 0, $width, $height);
1102
        imagecopy($comp, $filter, 0, 0, 0, 0, $width, $height);
1103
        imagecopymerge($im, $comp, 0, 0, 0, 0, $width, $height, $amount);
1104
1105
        imagedestroy($comp);
1106
        return $im;
1107
    }
1108
1109
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1110
        Colorise
1111
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1112
1113
    public function image_colorize($rgb)
1114
    {
1115
        imagetruecolortopalette($this->imageResized, true, 256);
1116
        $numColors = imagecolorstotal($this->imageResized);
1117
1118
        for ($x = 0; $x < $numColors; ++$x) {
1119
            list($r, $g, $b) = array_values(imagecolorsforindex($this->imageResized, $x));
1120
1121
            // calculate grayscale in percent
1122
            $grayscale = ($r + $g + $b) / 3 / 0xff;
1123
1124
            imagecolorset(
1125
                $this->imageResized,
1126
                $x,
1127
                $grayscale * $rgb[0],
1128
                $grayscale * $rgb[1],
1129
                $grayscale * $rgb[2]
1130
            );
1131
        }
1132
1133
        return true;
1134
    }
1135
1136
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1137
        Reflection
1138
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1139
1140
    public function addReflection($reflectionHeight = 50, $startingTransparency = 30, $inside = false, $bgColor = '#fff', $stretch = false, $divider = 0)
1141
    {
1142
        // *** Convert color
1143
        $rgbArray = $this->formatColor($bgColor);
1144
        $r        = $rgbArray['r'];
1145
        $g        = $rgbArray['g'];
1146
        $b        = $rgbArray['b'];
1147
1148
        $im = $this->imageResized;
1149
        $li = imagecreatetruecolor($this->width, 1);
1150
1151
        $bgc = imagecolorallocate($li, $r, $g, $b);
1152
        imagefilledrectangle($li, 0, 0, $this->width, 1, $bgc);
1153
1154
        $bg = imagecreatetruecolor($this->width, $reflectionHeight);
1155
        $wh = imagecolorallocate($im, 255, 255, 255);
1156
1157
        $im = imagerotate($im, -180, $wh);
1158
        imagecopyresampled($bg, $im, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
1159
1160
        $im = $bg;
1161
1162
        $bg = imagecreatetruecolor($this->width, $reflectionHeight);
1163
1164
        for ($x = 0; $x < $this->width; ++$x) {
1165
            imagecopy($bg, $im, $x, 0, $this->width - $x - 1, 0, 1, $reflectionHeight);
1166
        }
1167
        $im = $bg;
1168
1169
        $transaprencyAmount = $this->invertTransparency($startingTransparency, 100);
0 ignored issues
show
Unused Code introduced by
$transaprencyAmount is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1170
1171
        // *** Fade
1172
        if ($stretch) {
1173
            $step = 100 / ($reflectionHeight + $startingTransparency);
1174
        } else {
1175
            $step = 100 / $reflectionHeight;
1176
        }
1177
        for ($i = 0; $i <= $reflectionHeight; ++$i) {
1178
            if ($startingTransparency > 100) {
1179
                $startingTransparency = 100;
1180
            }
1181
            if ($startingTransparency < 1) {
1182
                $startingTransparency = 1;
1183
            }
1184
            imagecopymerge($bg, $li, 0, $i, 0, 0, $this->width, 1, $startingTransparency);
1185
            $startingTransparency += $step;
1186
        }
1187
1188
        // *** Apply fade
1189
        imagecopymerge($im, $li, 0, 0, 0, 0, $this->width, $divider, 100); // Divider
1190
1191
        // *** width, height of reflection.
1192
        $x = imagesx($im);
1193
        $y = imagesy($im);
1194
1195
        // *** Determines if the reflection should be displayed inside or outside the image
1196
        if ($inside) {
1197
            // Create new blank image with sizes.
1198
            $final = imagecreatetruecolor($this->width, $this->height);
1199
1200
            imagecopymerge($final, $this->imageResized, 0, 0, 0, $reflectionHeight, $this->width, $this->height - $reflectionHeight, 100);
1201
            imagecopymerge($final, $im, 0, $this->height - $reflectionHeight, 0, 0, $x, $y, 100);
1202
        } else {
1203
            // Create new blank image with sizes.
1204
            $final = imagecreatetruecolor($this->width, $this->height + $y);
1205
1206
            imagecopymerge($final, $this->imageResized, 0, 0, 0, 0, $this->width, $this->height, 100);
1207
            imagecopymerge($final, $im, 0, $this->height, 0, 0, $x, $y, 100);
1208
        }
1209
1210
        $this->imageResized = $final;
1211
1212
        imagedestroy($li);
1213
        imagedestroy($im);
1214
    }
1215
1216
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1217
        Rotate
1218
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1219
1220
    public function rotate($value = 90, $bgColor = 'transparent')
1221
        # Author:     Jarrod Oberto
1222
        # Date:       07-05-2011
1223
        # Purpose:    Rotate image
1224
        # Param in:   (mixed) $degrees: (int) number of degress to rotate image
1225
        #             (str) param "left": rotate left
1226
        #             (str) param "right": rotate right
1227
        #             (str) param "upside": upside-down image
1228
        # Param out:
1229
        # Reference:
1230
        # Notes:    The default direction of imageRotate() is counter clockwise.
1231
        #
1232
    {
1233
        if ($this->imageResized) {
1234
            if (is_int($value)) {
1235
                $degrees = $value;
1236
            }
1237
1238
            // *** Convert color
1239
            $rgbArray = $this->formatColor($bgColor);
1240
            $r        = $rgbArray['r'];
1241
            $g        = $rgbArray['g'];
1242
            $b        = $rgbArray['b'];
1243
            if (isset($rgbArray['a'])) {
1244
                $a = $rgbArray['a'];
1245
            }
1246
1247
            if (is_string($value)) {
1248
                $value = strtolower($value);
1249
1250
                switch ($value) {
1251
                    case 'left':
1252
                        $degrees = 90;
1253
                        break;
1254
                    case 'right':
1255
                        $degrees = 270;
1256
                        break;
1257
                    case 'upside':
1258
                        $degrees = 180;
1259
                        break;
1260
                    default:
1261
                        break;
1262
                }
1263
            }
1264
1265
            // *** The default direction of imageRotate() is counter clockwise
1266
            //   * This makes it clockwise
1267
            $degrees = 360 - $degrees;
0 ignored issues
show
Bug introduced by
The variable $degrees does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1268
1269
            // *** Create background color
1270
            $bg = imagecolorallocatealpha($this->imageResized, $r, $g, $b, $a);
0 ignored issues
show
Bug introduced by
The variable $a does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1271
1272
            // *** Fill with background
1273
            imagefill($this->imageResized, 0, 0, $bg);
1274
1275
            // *** Rotate
1276
            $this->imageResized = imagerotate($this->imageResized, $degrees, $bg); // Rotate 45 degrees and allocated the transparent colour as the one to make transparent (obviously)
1277
1278
            // Ensure alpha transparency
1279
            ImageSaveAlpha($this->imageResized, true);
1280
        }
1281
    }
1282
1283
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1284
        Round corners
1285
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1286
1287
    public function roundCorners($radius = 5, $bgColor = 'transparent')
1288
        # Author:     Jarrod Oberto
1289
        # Date:       19-05-2011
1290
        # Purpose:    Create rounded corners on your image
1291
        # Param in:   (int) radius = the amount of curvature
1292
        #             (mixed) $bgColor = the corner background color
1293
        # Param out:  n/a
1294
        # Reference:
1295
        # Notes:
1296
        #
1297
    {
1298
        // *** Check if the user wants transparency
1299
        $isTransparent = false;
1300
        if (!is_array($bgColor)) {
1301
            if ('transparent' === strtolower($bgColor)) {
1302
                $isTransparent = true;
1303
            }
1304
        }
1305
1306
        // *** If we use transparency, we need to color our curved mask with a unique color
1307
        if ($isTransparent) {
1308
            $bgColor = $this->findUnusedGreen();
1309
        }
1310
1311
        // *** Convert color
1312
        $rgbArray = $this->formatColor($bgColor);
1313
        $r        = $rgbArray['r'];
1314
        $g        = $rgbArray['g'];
1315
        $b        = $rgbArray['b'];
1316
        if (isset($rgbArray['a'])) {
1317
            $a = $rgbArray['a'];
0 ignored issues
show
Unused Code introduced by
$a is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1318
        }
1319
1320
        // *** Create top-left corner mask (square)
1321
        $cornerImg = imagecreatetruecolor($radius, $radius);
1322
        //$cornerImg = imagecreate($radius, $radius);
1323
1324
        //imagealphablending($cornerImg, true);
1325
        //imagesavealpha($cornerImg, true);
1326
1327
        //imagealphablending($this->imageResized, false);
1328
        //imagesavealpha($this->imageResized, true);
1329
1330
        // *** Give it a color
1331
        $maskColor = imagecolorallocate($cornerImg, 0, 0, 0);
1332
1333
        // *** Replace the mask color (black) to transparent
1334
        imagecolortransparent($cornerImg, $maskColor);
1335
1336
        // *** Create the image background color
1337
        $imagebgColor = imagecolorallocate($cornerImg, $r, $g, $b);
1338
1339
        // *** Fill the corner area to the user defined color
1340
        imagefill($cornerImg, 0, 0, $imagebgColor);
1341
1342
        imagefilledellipse($cornerImg, $radius, $radius, $radius * 2, $radius * 2, $maskColor);
1343
1344
        // *** Map to top left corner
1345
        imagecopymerge($this->imageResized, $cornerImg, 0, 0, 0, 0, $radius, $radius, 100); #tl
1346
1347
        // *** Map rounded corner to other corners by rotating and applying the mask
1348
        $cornerImg = imagerotate($cornerImg, 90, 0);
1349
        imagecopymerge($this->imageResized, $cornerImg, 0, $this->height - $radius, 0, 0, $radius, $radius, 100); #bl
1350
1351
        $cornerImg = imagerotate($cornerImg, 90, 0);
1352
        imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, $this->height - $radius, 0, 0, $radius, $radius, 100); #br
1353
1354
        $cornerImg = imagerotate($cornerImg, 90, 0);
1355
        imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, 0, 0, 0, $radius, $radius, 100); #tr
1356
1357
        // *** If corners are to be transparent, we fill our chromakey color as transparent.
1358
        if ($isTransparent) {
1359
            //imagecolortransparent($this->imageResized, $imagebgColor);
1360
            $this->imageResized = $this->transparentImage($this->imageResized);
1361
            imagesavealpha($this->imageResized, true);
1362
        }
1363
    }
1364
1365
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1366
        Shadow
1367
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1368
1369
    public function addShadow($shadowAngle = 45, $blur = 15, $bgColor = 'transparent')
1370
        #
1371
        # Author:   Jarrod Oberto (Adapted from Pascal Naidon)
1372
        # Ref:    http://www.les-stooges.org/pascal/webdesign/vignettes/index.php?la=en
1373
        # Purpose:  Add a drop shadow to your image
1374
        # Params in:  (int) $angle: the angle of the shadow
1375
        #       (int) $blur: the blur distance
1376
        #       (mixed) $bgColor: the color of the background
1377
        # Params out:
1378
        # Notes:
1379
        #
1380
    {
1381
        // *** A higher number results in a smoother shadow
1382
        define('STEPS', $blur * 2);
1383
1384
        // *** Set the shadow distance
1385
        $shadowDistance = $blur * 0.25;
1386
1387
        // *** Set blur width and height
1388
        $blurWidth = $blurHeight = $blur;
1389
1390
        if (0 == $shadowAngle) {
1391
            $distWidth  = 0;
1392
            $distHeight = 0;
1393
        } else {
1394
            $distWidth  = $shadowDistance * cos(deg2rad($shadowAngle));
1395
            $distHeight = $shadowDistance * sin(deg2rad($shadowAngle));
1396
        }
1397
1398
        // *** Convert color
1399
        if ('transparent' !== strtolower($bgColor)) {
1400
            $rgbArray = $this->formatColor($bgColor);
1401
            $r0       = $rgbArray['r'];
1402
            $g0       = $rgbArray['g'];
1403
            $b0       = $rgbArray['b'];
1404
        }
1405
1406
        $image  = $this->imageResized;
1407
        $width  = $this->width;
1408
        $height = $this->height;
1409
1410
        $newImage = imagecreatetruecolor($width, $height);
1411
        imagecopyresampled($newImage, $image, 0, 0, 0, 0, $width, $height, $width, $height);
1412
1413
        // *** RGB
1414
        $rgb    = imagecreatetruecolor($width + $blurWidth, $height + $blurHeight);
1415
        $colour = imagecolorallocate($rgb, 0, 0, 0);
1416
        imagefilledrectangle($rgb, 0, 0, $width + $blurWidth, $height + $blurHeight, $colour);
1417
        $colour = imagecolorallocate($rgb, 255, 255, 255);
1418
        //imagefilledrectangle($rgb, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-$distWidth, $height+$blurWidth*0.5-$distHeight, $colour);
1419
        imagefilledrectangle($rgb, $blurWidth * 0.5 - $distWidth, $blurHeight * 0.5 - $distHeight, $width + $blurWidth * 0.5 - $distWidth, $height + $blurWidth * 0.5 - $distHeight, $colour);
1420
        //imagecopymerge($rgb, $newImage, 1+$blurWidth*0.5-$distWidth, 1+$blurHeight*0.5-$distHeight, 0,0, $width, $height, 100);
1421
        imagecopymerge($rgb, $newImage, $blurWidth * 0.5 - $distWidth, $blurHeight * 0.5 - $distHeight, 0, 0, $width + $blurWidth, $height + $blurHeight, 100);
1422
1423
        // *** Shadow (alpha)
1424
        $shadow = imagecreatetruecolor($width + $blurWidth, $height + $blurHeight);
1425
        imagealphablending($shadow, false);
1426
        $colour = imagecolorallocate($shadow, 0, 0, 0);
1427
        imagefilledrectangle($shadow, 0, 0, $width + $blurWidth, $height + $blurHeight, $colour);
1428
1429
        for ($i = 0; $i <= STEPS; ++$i) {
1430
            $t         = ((1.0 * $i) / STEPS);
1431
            $intensity = 255 * $t * $t;
1432
1433
            $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
1434
            $points = [
1435
                $blurWidth * $t,
1436
                $blurHeight,     // Point 1 (x, y)
1437
                $blurWidth,
1438
                $blurHeight * $t,  // Point 2 (x, y)
1439
                $width,
1440
                $blurHeight * $t,  // Point 3 (x, y)
1441
                $width + $blurWidth * (1 - $t),
1442
                $blurHeight,     // Point 4 (x, y)
1443
                $width + $blurWidth * (1 - $t),
1444
                $height,     // Point 5 (x, y)
1445
                $width,
1446
                $height + $blurHeight * (1 - $t),  // Point 6 (x, y)
1447
                $blurWidth,
1448
                $height + $blurHeight * (1 - $t),  // Point 7 (x, y)
1449
                $blurWidth * $t,
1450
                $height      // Point 8 (x, y)
1451
            ];
1452
            imagepolygon($shadow, $points, 8, $colour);
1453
        }
1454
1455
        for ($i = 0; $i <= STEPS; ++$i) {
1456
            $t         = ((1.0 * $i) / STEPS);
1457
            $intensity = 255 * $t * $t;
1458
1459
            $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
1460
            imagefilledarc($shadow, $blurWidth - 1, $blurHeight - 1, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 180, 268, $colour, IMG_ARC_PIE);
1461
            imagefilledarc($shadow, $width, $blurHeight - 1, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 270, 358, $colour, IMG_ARC_PIE);
1462
            imagefilledarc($shadow, $width, $height, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 0, 90, $colour, IMG_ARC_PIE);
1463
            imagefilledarc($shadow, $blurWidth - 1, $height, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 90, 180, $colour, IMG_ARC_PIE);
1464
        }
1465
1466
        $colour = imagecolorallocate($shadow, 255, 255, 255);
1467
        imagefilledrectangle($shadow, $blurWidth, $blurHeight, $width, $height, $colour);
1468
        imagefilledrectangle($shadow, $blurWidth * 0.5 - $distWidth, $blurHeight * 0.5 - $distHeight, $width + $blurWidth * 0.5 - 1 - $distWidth, $height + $blurHeight * 0.5 - 1 - $distHeight, $colour);
1469
1470
        // *** The magic
1471
        imagealphablending($rgb, false);
1472
1473
        for ($theX = 0; $theX < imagesx($rgb); $theX++) {
1474
            for ($theY = 0; $theY < imagesy($rgb); $theY++) {
1475
                // *** Get the RGB values for every pixel of the RGB image
1476
                $colArray = imagecolorat($rgb, $theX, $theY);
1477
                $r        = ($colArray >> 16) & 0xFF;
1478
                $g        = ($colArray >> 8) & 0xFF;
1479
                $b        = $colArray & 0xFF;
1480
1481
                // *** Get the alpha value for every pixel of the shadow image
1482
                $colArray = imagecolorat($shadow, $theX, $theY);
1483
                $a        = $colArray & 0xFF;
1484
                $a        = 127 - floor($a / 2);
1485
                $t        = $a / 128.0;
1486
1487
                // *** Create color
1488
                if ('transparent' === strtolower($bgColor)) {
1489
                    $myColour = imagecolorallocatealpha($rgb, $r, $g, $b, $a);
1490
                } else {
1491
                    $myColour = imagecolorallocate($rgb, $r * (1.0 - $t) + $r0 * $t, $g * (1.0 - $t) + $g0 * $t, $b * (1.0 - $t) + $b0 * $t);
0 ignored issues
show
Bug introduced by
The variable $r0 does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $g0 does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $b0 does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1492
                }
1493
1494
                // *** Add color to new rgb image
1495
                imagesetpixel($rgb, $theX, $theY, $myColour);
1496
            }
1497
        }
1498
1499
        imagealphablending($rgb, true);
1500
        imagesavealpha($rgb, true);
1501
1502
        $this->imageResized = $rgb;
1503
1504
        imagedestroy($image);
1505
        imagedestroy($newImage);
1506
        imagedestroy($shadow);
1507
    }
1508
1509
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1510
        Add Caption Box
1511
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1512
1513
    public function addCaptionBox($side = 'b', $thickness = 50, $padding = 0, $bgColor = '#000', $transaprencyAmount = 30)
1514
        #
1515
        # Author:   Jarrod Oberto
1516
        # Date:   26 May 2011
1517
        # Purpose:  Add a caption box
1518
        # Params in:  (str) $side: the side to add the caption box (t, r, b, or l).
1519
        #       (int) $thickness: how thick you want the caption box to be.
1520
        #       (mixed) $bgColor: The color of the caption box.
1521
        #       (int) $transaprencyAmount: The amount of transparency to be
1522
        #       applied.
1523
        # Params out: n/a
1524
        # Notes:
1525
        #
1526
    {
1527
        $side = strtolower($side);
1528
1529
        // *** Convert color
1530
        $rgbArray = $this->formatColor($bgColor);
1531
        $r        = $rgbArray['r'];
1532
        $g        = $rgbArray['g'];
1533
        $b        = $rgbArray['b'];
1534
1535
        $positionArray = $this->calculateCaptionBoxPosition($side, $thickness, $padding);
1536
1537
        // *** Store incase we want to use method addTextToCaptionBox()
1538
        $this->captionBoxPositionArray = $positionArray;
1539
1540
        $transaprencyAmount = $this->invertTransparency($transaprencyAmount, 127, false);
1541
        $transparent        = imagecolorallocatealpha($this->imageResized, $r, $g, $b, $transaprencyAmount);
1542
        imagefilledrectangle($this->imageResized, $positionArray['x1'], $positionArray['y1'], $positionArray['x2'], $positionArray['y2'], $transparent);
1543
    }
1544
1545
    ## --------------------------------------------------------
1546
1547
    public function addTextToCaptionBox($text, $fontColor = '#fff', $fontSize = 12, $angle = 0, $font = null)
1548
        #
1549
        # Author:   Jarrod Oberto
1550
        # Date:   03 Aug 11
1551
        # Purpose:  Simplify adding text to a caption box by automatically
1552
        #       locating the center of the caption box
1553
        # Params in:  The usually text paams (less a couple)
1554
        # Params out: n/a
1555
        # Notes:
1556
        #
1557
    {
1558
        // *** Get the caption box measurements
1559
        if (4 == count($this->captionBoxPositionArray)) {
1560
            $x1 = $this->captionBoxPositionArray['x1'];
1561
            $x2 = $this->captionBoxPositionArray['x2'];
1562
            $y1 = $this->captionBoxPositionArray['y1'];
1563
            $y2 = $this->captionBoxPositionArray['y2'];
1564
        } else {
1565
            if ($this->debug) {
1566
                die('No caption box found.');
1567
            } else {
1568
                return false;
1569
            }
1570
        }
1571
1572
        // *** Get text font
1573
        try {
1574
            $font = $this->getTextFont($font);
1575
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1576
        }
1577
1578
        // *** Get text size
1579
        $textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text);
1580
        $textWidth     = $textSizeArray['width'];
1581
        $textHeight    = $textSizeArray['height'];
1582
1583
        // *** Find the width/height middle points
1584
        $boxXMiddle = (($x2 - $x1) / 2);
1585
        $boxYMiddle = (($y2 - $y1) / 2);
1586
1587
        // *** Box middle - half the text width/height
1588
        $xPos = ($x1 + $boxXMiddle) - ($textWidth / 2);
1589
        $yPos = ($y1 + $boxYMiddle) - ($textHeight / 2);
1590
1591
        $pos = $xPos . 'x' . $yPos;
1592
1593
        $this->addText($text, $pos, $padding = 0, $fontColor, $fontSize, $angle, $font);
1594
    }
1595
1596
    ## --------------------------------------------------------
1597
1598
    private function calculateCaptionBoxPosition($side, $thickness, $padding)
1599
    {
1600
        $positionArray = [];
1601
1602
        switch ($side) {
1603
            case 't':
1604
                $positionArray['x1'] = 0;
1605
                $positionArray['y1'] = $padding;
1606
                $positionArray['x2'] = $this->width;
1607
                $positionArray['y2'] = $thickness + $padding;
1608
                break;
1609
            case 'r':
1610
                $positionArray['x1'] = $this->width - $thickness - $padding;
1611
                $positionArray['y1'] = 0;
1612
                $positionArray['x2'] = $this->width - $padding;
1613
                $positionArray['y2'] = $this->height;
1614
                break;
1615
            case 'b':
1616
                $positionArray['x1'] = 0;
1617
                $positionArray['y1'] = $this->height - $thickness - $padding;
1618
                $positionArray['x2'] = $this->width;
1619
                $positionArray['y2'] = $this->height - $padding;
1620
                break;
1621
            case 'l':
1622
                $positionArray['x1'] = $padding;
1623
                $positionArray['y1'] = 0;
1624
                $positionArray['x2'] = $thickness + $padding;
1625
                $positionArray['y2'] = $this->height;
1626
                break;
1627
1628
            default:
1629
                break;
1630
        }
1631
1632
        return $positionArray;
1633
    }
1634
1635
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1636
        Get EXIF Data
1637
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1638
1639
    public function getExif($debug = true)
1640
        # Author:     Jarrod Oberto
1641
        # Date:       07-05-2011
1642
        # Purpose:    Get image EXIF data
1643
        # Param in:   n/a
1644
        # Param out:  An associate array of EXIF data
1645
        # Reference:
1646
        # Notes:
1647
        # 23 May 13 : added orientation flag -jco
1648
        #
1649
    {
1650
        if (!$this->debug || !$debug) {
1651
            $debug = false;
1652
        }
1653
1654
        // *** Check all is good - check the EXIF library exists and the file exists, too.
1655
        if (!$this->testEXIFInstalled()) {
1656
            if ($debug) {
1657
                die('The EXIF Library is not installed.');
1658
            } else {
1659
                return [];
1660
            }
1661
        }
1662
        if (!file_exists($this->fileName)) {
1663
            if ($debug) {
1664
                die('Image not found.');
1665
            } else {
1666
                return [];
1667
            }
1668
        }
1669
        if ('.jpg' !== $this->fileExtension) {
1670
            if ($debug) {
1671
                die('Metadata not supported for this image type.');
1672
            } else {
1673
                return [];
1674
            }
1675
        }
1676
        $exifData = exif_read_data($this->fileName, 'IFD0');
1677
1678
        // *** Format the apperture value
1679
        $ev            = isset($exifData['ApertureValue']) ? $exifData['ApertureValue'] : '';
1680
        $apPeicesArray = explode('/', $ev);
1681
        if (2 == count($apPeicesArray)) {
1682
            $apertureValue = round($apPeicesArray[0] / $apPeicesArray[1], 2, PHP_ROUND_HALF_DOWN) . ' EV';
1683
        } else {
1684
            $apertureValue = '';
1685
        }
1686
1687
        // *** Format the focal length
1688
        $focalLength   = isset($exifData['FocalLength']) ? $exifData['FocalLength'] : '';
1689
        $flPeicesArray = explode('/', $focalLength);
1690
        if (2 == count($flPeicesArray)) {
1691
            $focalLength = $flPeicesArray[0] / $flPeicesArray[1] . '.0 mm';
1692
        } else {
1693
            $focalLength = '';
1694
        }
1695
1696
        // *** Format fNumber
1697
        $fNumber       = isset($exifData['FNumber']) ? $exifData['FNumber'] : '';
1698
        $fnPeicesArray = explode('/', $fNumber);
1699
        if (2 == count($fnPeicesArray)) {
1700
            $fNumber = $fnPeicesArray[0] / $fnPeicesArray[1];
1701
        } else {
1702
            $fNumber = '';
1703
        }
1704
1705
        // *** Resolve ExposureProgram
1706
        if (isset($exifData['ExposureProgram'])) {
1707
            $ep = $exifData['ExposureProgram'];
1708
        }
1709
        if (isset($ep)) {
1710
            $ep = $this->resolveExposureProgram($ep);
1711
        }
1712
1713
        // *** Resolve MeteringMode
1714
        $mm = isset($exifData['MeteringMode']) ? $exifData['MeteringMode'] : '';
1715
        $mm = $this->resolveMeteringMode($mm);
1716
1717
        // *** Resolve Flash
1718
        $flash = isset($exifData['Flash']) ? $exifData['Flash'] : '';
1719
        $flash = $this->resolveFlash($flash);
1720
1721
        if (isset($exifData['Make'])) {
1722
            $exifDataArray['make'] = $exifData['Make'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$exifDataArray was never initialized. Although not strictly required by PHP, it is generally a good practice to add $exifDataArray = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1723
        } else {
1724
            $exifDataArray['make'] = '';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$exifDataArray was never initialized. Although not strictly required by PHP, it is generally a good practice to add $exifDataArray = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1725
        }
1726
1727
        if (isset($exifData['Model'])) {
1728
            $exifDataArray['model'] = $exifData['Model'];
1729
        } else {
1730
            $exifDataArray['model'] = '';
1731
        }
1732
1733
        if (isset($exifData['DateTime'])) {
1734
            $exifDataArray['date'] = $exifData['DateTime'];
1735
        } else {
1736
            $exifDataArray['date'] = '';
1737
        }
1738
1739
        if (isset($exifData['ExposureTime'])) {
1740
            $exifDataArray['exposure time'] = $exifData['ExposureTime'] . ' sec.';
1741
        } else {
1742
            $exifDataArray['exposure time'] = '';
1743
        }
1744
1745
        if ('' != $apertureValue) {
1746
            $exifDataArray['aperture value'] = $apertureValue;
1747
        } else {
1748
            $exifDataArray['aperture value'] = '';
1749
        }
1750
1751
        if (isset($exifData['COMPUTED']['ApertureFNumber'])) {
1752
            $exifDataArray['f-stop'] = $exifData['COMPUTED']['ApertureFNumber'];
1753
        } else {
1754
            $exifDataArray['f-stop'] = '';
1755
        }
1756
1757
        if (isset($exifData['FNumber'])) {
1758
            $exifDataArray['fnumber'] = $exifData['FNumber'];
1759
        } else {
1760
            $exifDataArray['fnumber'] = '';
1761
        }
1762
1763
        if ('' != $fNumber) {
1764
            $exifDataArray['fnumber value'] = $fNumber;
1765
        } else {
1766
            $exifDataArray['fnumber value'] = '';
1767
        }
1768
1769
        if (isset($exifData['ISOSpeedRatings'])) {
1770
            $exifDataArray['iso'] = $exifData['ISOSpeedRatings'];
1771
        } else {
1772
            $exifDataArray['iso'] = '';
1773
        }
1774
1775
        if ('' != $focalLength) {
1776
            $exifDataArray['focal length'] = $focalLength;
1777
        } else {
1778
            $exifDataArray['focal length'] = '';
1779
        }
1780
1781
        if (isset($ep)) {
1782
            $exifDataArray['exposure program'] = $ep;
1783
        } else {
1784
            $exifDataArray['exposure program'] = '';
1785
        }
1786
1787
        if ('' != $mm) {
1788
            $exifDataArray['metering mode'] = $mm;
1789
        } else {
1790
            $exifDataArray['metering mode'] = '';
1791
        }
1792
1793
        if ('' != $flash) {
1794
            $exifDataArray['flash status'] = $flash;
1795
        } else {
1796
            $exifDataArray['flash status'] = '';
1797
        }
1798
1799
        if (isset($exifData['Artist'])) {
1800
            $exifDataArray['creator'] = $exifData['Artist'];
1801
        } else {
1802
            $exifDataArray['creator'] = '';
1803
        }
1804
1805
        if (isset($exifData['Copyright'])) {
1806
            $exifDataArray['copyright'] = $exifData['Copyright'];
1807
        } else {
1808
            $exifDataArray['copyright'] = '';
1809
        }
1810
1811
        // *** Orientation
1812
        if (isset($exifData['Orientation'])) {
1813
            $exifDataArray['orientation'] = $exifData['Orientation'];
1814
        } else {
1815
            $exifDataArray['orientation'] = '';
1816
        }
1817
1818
        return $exifDataArray;
1819
    }
1820
1821
    ## --------------------------------------------------------
1822
1823
    private function resolveExposureProgram($ep)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1824
    {
1825
        switch ($ep) {
1826
            case 0:
1827
                $ep = '';
1828
                break;
1829
            case 1:
1830
                $ep = 'manual';
1831
                break;
1832
            case 2:
1833
                $ep = 'normal program';
1834
                break;
1835
            case 3:
1836
                $ep = 'aperture priority';
1837
                break;
1838
            case 4:
1839
                $ep = 'shutter priority';
1840
                break;
1841
            case 5:
1842
                $ep = 'creative program';
1843
                break;
1844
            case 6:
1845
                $ep = 'action program';
1846
                break;
1847
            case 7:
1848
                $ep = 'portrait mode';
1849
                break;
1850
            case 8:
1851
                $ep = 'landscape mode';
1852
                break;
1853
1854
            default:
1855
                break;
1856
        }
1857
1858
        return $ep;
1859
    }
1860
1861
    ## --------------------------------------------------------
1862
1863
    private function resolveMeteringMode($mm)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1864
    {
1865
        switch ($mm) {
1866
            case 0:
1867
                $mm = 'unknown';
1868
                break;
1869
            case 1:
1870
                $mm = 'average';
1871
                break;
1872
            case 2:
1873
                $mm = 'center weighted average';
1874
                break;
1875
            case 3:
1876
                $mm = 'spot';
1877
                break;
1878
            case 4:
1879
                $mm = 'multi spot';
1880
                break;
1881
            case 5:
1882
                $mm = 'pattern';
1883
                break;
1884
            case 6:
1885
                $mm = 'partial';
1886
                break;
1887
            case 255:
1888
                $mm = 'other';
1889
                break;
1890
1891
            default:
1892
                break;
1893
        }
1894
1895
        return $mm;
1896
    }
1897
1898
    ## --------------------------------------------------------
1899
1900
    private function resolveFlash($flash)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1901
    {
1902
        switch ($flash) {
1903
            case 0:
1904
                $flash = 'flash did not fire';
1905
                break;
1906
            case 1:
1907
                $flash = 'flash fired';
1908
                break;
1909
            case 5:
1910
                $flash = 'strobe return light not detected';
1911
                break;
1912
            case 7:
1913
                $flash = 'strobe return light detected';
1914
                break;
1915
            case 9:
1916
                $flash = 'flash fired, compulsory flash mode';
1917
                break;
1918
            case 13:
1919
                $flash = 'flash fired, compulsory flash mode, return light not detected';
1920
                break;
1921
            case 15:
1922
                $flash = 'flash fired, compulsory flash mode, return light detected';
1923
                break;
1924
            case 16:
1925
                $flash = 'flash did not fire, compulsory flash mode';
1926
                break;
1927
            case 24:
1928
                $flash = 'flash did not fire, auto mode';
1929
                break;
1930
            case 25:
1931
                $flash = 'flash fired, auto mode';
1932
                break;
1933
            case 29:
1934
                $flash = 'flash fired, auto mode, return light not detected';
1935
                break;
1936
            case 31:
1937
                $flash = 'flash fired, auto mode, return light detected';
1938
                break;
1939
            case 32:
1940
                $flash = 'no flash function';
1941
                break;
1942
            case 65:
1943
                $flash = 'flash fired, red-eye reduction mode';
1944
                break;
1945
            case 69:
1946
                $flash = 'flash fired, red-eye reduction mode, return light not detected';
1947
                break;
1948
            case 71:
1949
                $flash = 'flash fired, red-eye reduction mode, return light detected';
1950
                break;
1951
            case 73:
1952
                $flash = 'flash fired, compulsory flash mode, red-eye reduction mode';
1953
                break;
1954
            case 77:
1955
                $flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light not detected';
1956
                break;
1957
            case 79:
1958
                $flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light detected';
1959
                break;
1960
            case 89:
1961
                $flash = 'flash fired, auto mode, red-eye reduction mode';
1962
                break;
1963
            case 93:
1964
                $flash = 'flash fired, auto mode, return light not detected, red-eye reduction mode';
1965
                break;
1966
            case 95:
1967
                $flash = 'flash fired, auto mode, return light detected, red-eye reduction mode';
1968
                break;
1969
1970
            default:
1971
                break;
1972
        }
1973
1974
        return $flash;
1975
    }
1976
1977
1978
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1979
        Get IPTC Data
1980
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1981
1982
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1983
        Write IPTC Data
1984
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1985
1986
    public function writeIPTCcaption($value)
1987
        # Caption
1988
    {
1989
        $this->writeIPTC(120, $value);
1990
    }
1991
1992
    ## --------------------------------------------------------
1993
1994
    public function writeIPTCwriter($value)
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1995
    {
1996
        //$this->writeIPTC(65, $value);
1997
    }
1998
1999
    ## --------------------------------------------------------
2000
2001
    private function writeIPTC($dat, $value)
2002
    {
2003
        # LIMIT TO JPG
2004
2005
        $caption_block = $this->iptc_maketag(2, $dat, $value);
2006
        $image_string  = iptcembed($caption_block, $this->fileName);
2007
        file_put_contents('iptc.jpg', $image_string);
2008
    }
2009
2010
    ## --------------------------------------------------------
2011
2012
    private function iptc_maketag($rec, $dat, $val)
2013
        # Author:   Thies C. Arntzen
2014
        # Purpose:    Function to format the new IPTC text
2015
        # Param in:   $rec: Application record. (We’re working with #2)
2016
        #       $dat: Index. (120 for caption, 118 for contact. See the IPTC IIM
2017
        #         specification:
2018
        #         http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf
2019
        #       $val: Value/data/text. Make sure this is within the length
2020
        #         constraints of the IPTC IIM specification
2021
        # Ref:      http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/
2022
        #       http://php.net/manual/en/function.iptcembed.php
2023
        #
2024
    {
2025
        $len = strlen($val);
2026
        if ($len < 0x8000) {
2027
            return chr(0x1c) . chr($rec) . chr($dat) . chr($len >> 8) . chr($len & 0xff) . $val;
2028
        } else {
2029
            return chr(0x1c) . chr($rec) . chr($dat) . chr(0x80) . chr(0x04) . chr(($len >> 24) & 0xff) . chr(($len >> 16) & 0xff) . chr(($len >> 8) & 0xff) . chr(($len) & 0xff) . $val;
2030
        }
2031
    }
2032
2033
2034
2035
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2036
        Write XMP Data
2037
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2038
2039
    //http://xmpphptoolkit.sourceforge.net/
2040
2041
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2042
        Add Text
2043
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2044
2045
    public function addText($text, $pos = '20x20', $padding = 0, $fontColor = '#fff', $fontSize = 12, $angle = 0, $font = null)
2046
        # Author:     Jarrod Oberto
2047
        # Date:       18-11-09
2048
        # Purpose:    Add text to an image
2049
        # Param in:
2050
        # Param out:
2051
        # Reference:  http://php.net/manual/en/function.imagettftext.php
2052
        # Notes:      Make sure you supply the font.
2053
        #
2054
    {
2055
        // *** Convert color
2056
        $rgbArray = $this->formatColor($fontColor);
2057
        $r        = $rgbArray['r'];
2058
        $g        = $rgbArray['g'];
2059
        $b        = $rgbArray['b'];
2060
2061
        // *** Get text font
2062
        try {
2063
            $font = $this->getTextFont($font);
2064
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
2065
        }
2066
2067
        // *** Get text size
2068
        $textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text);
2069
        $textWidth     = $textSizeArray['width'];
2070
        $textHeight    = $textSizeArray['height'];
2071
2072
        // *** Find co-ords to place text
2073
        $posArray = $this->calculatePosition($pos, $padding, $textWidth, $textHeight, false);
2074
        $x        = $posArray['width'];
2075
        $y        = $posArray['height'];
2076
2077
        $fontColor = imagecolorallocate($this->imageResized, $r, $g, $b);
2078
2079
        // *** Add text
2080
        imagettftext($this->imageResized, $fontSize, $angle, $x, $y, $fontColor, $font, $text);
2081
    }
2082
2083
    ## --------------------------------------------------------
2084
2085
    private function getTextFont($font)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
2086
    {
2087
        // *** Font path (shou
2088
        $fontPath = __DIR__ . '/' . $this->fontDir;
2089
2090
        // *** The below is/may be needed depending on your version (see ref)
2091
        putenv('GDFONTPATH=' . realpath('.'));
2092
2093
        // *** Check if the passed in font exsits...
2094
        if (null == $font || !file_exists($font)) {
2095
            // *** ...If not, default to this font.
2096
            $font = $fontPath . '/arimo.ttf';
2097
2098
            // *** Check our default font exists...
2099
            if (!file_exists($font)) {
2100
                // *** If not, return false
2101
                if ($this->debug) {
2102
                    die('Font not found');
2103
                } else {
2104
                    return false;
2105
                }
2106
            }
2107
        }
2108
2109
        return $font;
2110
    }
2111
2112
    ## --------------------------------------------------------
2113
2114
    private function getTextSize($fontSize, $angle, $font, $text)
2115
    {
2116
        // *** Define box (so we can get the width)
2117
        $box = @imagettfbbox($fontSize, $angle, $font, $text);
2118
2119
        // ***  Get width of text from dimensions
2120
        $textWidth = abs($box[4] - $box[0]);
2121
2122
        // ***  Get height of text from dimensions (should also be same as $fontSize)
2123
        $textHeight = abs($box[5] - $box[1]);
2124
2125
        return ['height' => $textHeight, 'width' => $textWidth];
2126
    }
2127
2128
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2129
        Add Watermark
2130
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2131
2132
    public function addWatermark($watermarkImage, $pos, $padding = 0, $opacity = 0)
2133
        # Author:     Jarrod Oberto
2134
        # Date:       18-11-09
2135
        # Purpose:    Add watermark image
2136
        # Param in:   (str) $watermark: The watermark image
2137
        #             (str) $pos: Could be a pre-determined position such as:
2138
        #                 tl = top left,
2139
        #                 t  = top (middle),
2140
        #                 tr = top right,
2141
        #                 l  = left,
2142
        #                 m  = middle,
2143
        #                 r  = right,
2144
        #                 bl = bottom left,
2145
        #                 b  = bottom (middle),
2146
        #                 br = bottom right
2147
        #               Or, it could be a co-ordinate position such as: 50x100
2148
        #
2149
        #             (int) $padding: If using a pre-determined position you can
2150
        #               adjust the padding from the edges by passing an amount
2151
        #               in pixels. If using co-ordinates, this value is ignored.
2152
        # Param out:
2153
        # Reference:  http://www.php.net/manual/en/image.examples-watermark.php
2154
        # Notes:      Based on example in reference.
2155
        #
2156
        #
2157
    {
2158
        // Load the stamp and the photo to apply the watermark to
2159
        try {
2160
            $stamp = $this->openImage($watermarkImage);
2161
        } catch (Exception $e) {
2162
        }    # stamp
2163
        $im = $this->imageResized;            # photo
2164
2165
        // *** Get stamps width and height
2166
        $sx = imagesx($stamp);
2167
        $sy = imagesy($stamp);
2168
2169
        // *** Find co-ords to place image
2170
        $posArray = $this->calculatePosition($pos, $padding, $sx, $sy);
2171
        $x        = $posArray['width'];
2172
        $y        = $posArray['height'];
2173
2174
        // *** Set watermark opacity
2175
        if ('.png' === strtolower(strrchr($watermarkImage, '.'))) {
2176
            $opacity = $this->invertTransparency($opacity, 100);
2177
            $this->filterOpacity($stamp, $opacity);
2178
        }
2179
2180
        // Copy the watermark image onto our photo
2181
        imagecopy($im, $stamp, $x, $y, 0, 0, imagesx($stamp), imagesy($stamp));
2182
    }
2183
2184
    ## --------------------------------------------------------
2185
2186
    private function calculatePosition($pos, $padding, $assetWidth, $assetHeight, $upperLeft = true)
2187
        #
2188
        # Author:   Jarrod Oberto
2189
        # Date:   08-05-11
2190
        # Purpose:  Calculate the x, y pixel cordinates of the asset to place
2191
        # Params in:  (str) $pos: Either something like: "tl", "l", "br" or an
2192
        #         exact position like: "100x50"
2193
        #       (int) $padding: The amount of padding from the edge. Only
2194
        #         used for the predefined $pos.
2195
        #       (int) $assetWidth: The width of the asset to add to the image
2196
        #       (int) $assetHeight: The height of the asset to add to the image
2197
        #       (bol) $upperLeft: if true, the asset will be positioned based
2198
        #         on the upper left x, y coords. If false, it means you're
2199
        #         using the lower left as the basepoint and this will
2200
        #         convert it to the upper left position
2201
        # Params out:
2202
        # NOTE: this is done from the UPPER left corner!! But will convert lower
2203
        #   left basepoints to upper left if $upperleft is set to false
2204
        #
2205
        #
2206
    {
2207
        $pos = strtolower($pos);
2208
2209
        // *** If co-ords have been entered
2210
        if (strstr($pos, 'x')) {
2211
            $pos = str_replace(' ', '', $pos);
2212
2213
            $xyArray = explode('x', $pos);
2214
            list($width, $height) = $xyArray;
2215
        } else {
2216
            switch ($pos) {
2217
                case 'tl':
2218
                    $width  = 0 + $padding;
2219
                    $height = 0 + $padding;
2220
                    break;
2221
2222
                case 't':
2223
                    $width  = ($this->width / 2) - ($assetWidth / 2);
2224
                    $height = 0 + $padding;
2225
                    break;
2226
2227
                case 'tr':
2228
                    $width  = $this->width - $assetWidth - $padding;
2229
                    $height = 0 + $padding;
2230
                    break;
2231
2232
                case 'l':
2233
                    $width  = 0 + $padding;
2234
                    $height = ($this->height / 2) - ($assetHeight / 2);
2235
                    break;
2236
2237
                case 'm':
2238
                    $width  = ($this->width / 2) - ($assetWidth / 2);
2239
                    $height = ($this->height / 2) - ($assetHeight / 2);
2240
                    break;
2241
2242
                case 'r':
2243
                    $width  = $this->width - $assetWidth - $padding;
2244
                    $height = ($this->height / 2) - ($assetHeight / 2);
2245
                    break;
2246
2247
                case 'bl':
2248
                    $width  = 0 + $padding;
2249
                    $height = $this->height - $assetHeight - $padding;
2250
                    break;
2251
2252
                case 'b':
2253
                    $width  = ($this->width / 2) - ($assetWidth / 2);
2254
                    $height = $this->height - $assetHeight - $padding;
2255
                    break;
2256
2257
                case 'br':
2258
                    $width  = $this->width - $assetWidth - $padding;
2259
                    $height = $this->height - $assetHeight - $padding;
2260
                    break;
2261
2262
                default:
2263
                    $width  = 0;
2264
                    $height = 0;
2265
                    break;
2266
            }
2267
        }
2268
2269
        if (!$upperLeft) {
2270
            $height = $height + $assetHeight;
2271
        }
2272
2273
        return ['width' => $width, 'height' => $height];
2274
    }
2275
2276
    ## --------------------------------------------------------
2277
2278
    private function filterOpacity(&$img, $opacity = 75)
2279
        #
2280
        # Author:     aiden dot mail at freemail dot hu
2281
        # Author date:  29-03-08 08:16
2282
        # Date added:   08-05-11
2283
        # Purpose:    Change opacity of image
2284
        # Params in:    $img: Image resource id
2285
        #         (int) $opacity: the opacity amount: 0-100, 100 being not opaque.
2286
        # Params out:   (bool) true on success, else false
2287
        # Ref:      http://www.php.net/manual/en/function.imagefilter.php#82162
2288
        # Notes:      png only
2289
        #
2290
    {
2291
        if (!isset($opacity)) {
2292
            return false;
2293
        }
2294
2295
        if (100 == $opacity) {
2296
            return true;
2297
        }
2298
2299
        $opacity /= 100;
2300
2301
        //get image width and height
2302
        $w = imagesx($img);
2303
        $h = imagesy($img);
2304
2305
        //turn alpha blending off
2306
        imagealphablending($img, false);
2307
2308
        //find the most opaque pixel in the image (the one with the smallest alpha value)
2309
        $minalpha = 127;
2310
        for ($x = 0; $x < $w; ++$x) {
2311
            for ($y = 0; $y < $h; ++$y) {
2312
                $alpha = (imagecolorat($img, $x, $y) >> 24) & 0xFF;
2313
                if ($alpha < $minalpha) {
2314
                    $minalpha = $alpha;
2315
                }
2316
            }
2317
        }
2318
2319
        //loop through image pixels and modify alpha for each
2320
        for ($x = 0; $x < $w; ++$x) {
2321
            for ($y = 0; $y < $h; ++$y) {
2322
                //get current alpha value (represents the TANSPARENCY!)
2323
                $colorxy = imagecolorat($img, $x, $y);
2324
                $alpha   = ($colorxy >> 24) & 0xFF;
2325
                //calculate new alpha
2326
                if (127 !== $minalpha) {
2327
                    $alpha = 127 + 127 * $opacity * ($alpha - 127) / (127 - $minalpha);
2328
                } else {
2329
                    $alpha += 127 * $opacity;
2330
                }
2331
                //get the color index with new alpha
2332
                $alphacolorxy = imagecolorallocatealpha($img, ($colorxy >> 16) & 0xFF, ($colorxy >> 8) & 0xFF, $colorxy & 0xFF, $alpha);
2333
                //set pixel with the new color + opacity
2334
                if (!imagesetpixel($img, $x, $y, $alphacolorxy)) {
2335
                    return false;
2336
                }
2337
            }
2338
        }
2339
2340
        return true;
2341
    }
2342
2343
    ## --------------------------------------------------------
2344
2345
    private function openImage($file)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
2346
        # Author:     Jarrod Oberto
2347
        # Date:       27-02-08
2348
        # Purpose:
2349
        # Param in:
2350
        # Param out:  n/a
2351
        # Reference:
2352
        # Notes:
2353
        #
2354
    {
2355
        if (!file_exists($file) && !$this->checkStringStartsWith('http://', $file)) {
2356
            if ($this->debug) {
2357
                die('Image not found.');
2358
            } else {
2359
                die();
2360
            }
2361
        }
2362
2363
        // *** Get extension
2364
        $extension = strrchr($file, '.');
2365
        $extension = strtolower($extension);
2366
2367
        switch ($extension) {
2368
            case '.jpg':
2369
            case '.jpeg':
2370
                $img = @imagecreatefromjpeg($file);
2371
                break;
2372
            case '.gif':
2373
                $img = @imagecreatefromgif($file);
2374
                break;
2375
            case '.png':
2376
                $img = @imagecreatefrompng($file);
2377
                break;
2378
            case '.bmp':
2379
                $img = @$this->ImageCreateFromBMP($file);
2380
                break;
2381
            case '.psd':
2382
                $img = @$this->imagecreatefrompsd($file);
2383
                break;
2384
2385
            // ... etc
2386
2387
            default:
2388
                $img = false;
2389
                break;
2390
        }
2391
2392
        return $img;
2393
    }
2394
2395
    ## --------------------------------------------------------
2396
2397
    public function reset()
2398
        #
2399
        # Author:   Jarrod Oberto
2400
        # Date:   30-08-11
2401
        # Purpose:  Reset the resource (allow further editing)
2402
        # Params in:
2403
        # Params out:
2404
        # Notes:
2405
        #
2406
    {
2407
        $this->__destruct();
2408
        $this->image        = null;
2409
        $this->imageResized = null;
2410
        gc_collect_cycles();
2411
        try {
2412
            $this->__construct($this->fileName);
2413
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
2414
        }
2415
    }
2416
2417
    ## --------------------------------------------------------
2418
2419
    public function saveImage($savePath, $imageQuality = '100')
2420
        # Author:     Jarrod Oberto
2421
        # Date:       27-02-08
2422
        # Purpose:    Saves the image
2423
        # Param in:   $savePath: Where to save the image including filename:
2424
        #             $imageQuality: image quality you want the image saved at 0-100
2425
        # Param out:  n/a
2426
        # Reference:
2427
        # Notes:      * gif doesn't have a quality parameter
2428
        #             * jpg has a quality setting 0-100 (100 being the best)
2429
        #             * png has a quality setting 0-9 (0 being the best)
2430
        #
2431
        #             * bmp files have no native support for bmp files. We use a
2432
        #               third party class to save as bmp.
2433
    {
2434
        // *** Perform a check or two.
2435
        if (!is_resource($this->imageResized)) {
2436
            if ($this->debug) {
2437
                die('saveImage: This is not a resource.');
2438
            } else {
2439
                die();
2440
            }
2441
        }
2442
        $fileInfoArray = pathinfo($savePath);
2443
        clearstatcache();
2444
        if (!is_writable($fileInfoArray['dirname'])) {
2445
            if ($this->debug) {
2446
                die('The path is not writable. Please check your permissions.');
2447
            } else {
2448
                die();
2449
            }
2450
        }
2451
2452
        // *** Get extension
2453
        $extension = strrchr($savePath, '.');
2454
        $extension = strtolower($extension);
2455
2456
        $error = '';
2457
2458
        switch ($extension) {
2459
            case '.jpg':
2460
            case '.jpeg':
2461
                $this->checkInterlaceImage($this->isInterlace);
2462
                if (imagetypes() & IMG_JPG) {
2463
                    imagejpeg($this->imageResized, $savePath, $imageQuality);
2464
                } else {
2465
                    $error = 'jpg';
2466
                }
2467
                break;
2468
2469
            case '.gif':
2470
                $this->checkInterlaceImage($this->isInterlace);
2471
                if (imagetypes() & IMG_GIF) {
2472
                    imagegif($this->imageResized, $savePath);
2473
                } else {
2474
                    $error = 'gif';
2475
                }
2476
                break;
2477
2478
            case '.png':
2479
                // *** Scale quality from 0-100 to 0-9
2480
                $scaleQuality = round(($imageQuality / 100) * 9);
2481
2482
                // *** Invert qualit setting as 0 is best, not 9
2483
                $invertScaleQuality = 9 - $scaleQuality;
2484
2485
                $this->checkInterlaceImage($this->isInterlace);
2486
                if (imagetypes() & IMG_PNG) {
2487
                    imagepng($this->imageResized, $savePath, $invertScaleQuality);
2488
                } else {
2489
                    $error = 'png';
2490
                }
2491
                break;
2492
2493
            case '.bmp':
2494
                file_put_contents($savePath, $this->GD2BMPstring($this->imageResized));
2495
                break;
2496
2497
            // ... etc
2498
2499
            default:
2500
2501
                // *** No extension - No save.
2502
                $this->errorArray[] = 'This file type (' . $extension . ') is not supported. File not saved.';
2503
                break;
2504
        }
2505
2506
        //imagedestroy($this->imageResized);
2507
2508
        // *** Display error if a file type is not supported.
2509
        if ('' != $error) {
2510
            $this->errorArray[] = $error . ' support is NOT enabled. File not saved.';
2511
        }
2512
    }
2513
2514
    ## --------------------------------------------------------
2515
2516
    public function displayImage($fileType = 'jpg', $imageQuality = '100')
2517
        # Author:     Jarrod Oberto
2518
        # Date:       18-11-09
2519
        # Purpose:    Display images directly to the browser
2520
        # Param in:   The image type you want to display
2521
        # Param out:
2522
        # Reference:
2523
        # Notes:
2524
        #
2525
    {
2526
        if (!is_resource($this->imageResized)) {
2527
            if ($this->debug) {
2528
                die('saveImage: This is not a resource.');
2529
            } else {
2530
                die();
2531
            }
2532
        }
2533
2534
        switch ($fileType) {
2535
            case 'jpg':
2536
            case 'jpeg':
2537
                header('Content-type: image/jpeg');
2538
                imagejpeg($this->imageResized, '', $imageQuality);
2539
                break;
2540
            case 'gif':
2541
                header('Content-type: image/gif');
2542
                imagegif($this->imageResized);
2543
                break;
2544
            case 'png':
2545
                header('Content-type: image/png');
2546
2547
                // *** Scale quality from 0-100 to 0-9
2548
                $scaleQuality = round(($imageQuality / 100) * 9);
2549
2550
                // *** Invert qualit setting as 0 is best, not 9
2551
                $invertScaleQuality = 9 - $scaleQuality;
2552
2553
                imagepng($this->imageResized, '', $invertScaleQuality);
2554
                break;
2555
            case 'bmp':
2556
                echo 'bmp file format is not supported.';
2557
                break;
2558
2559
            // ... etc
2560
2561
            default:
2562
                // *** No extension - No save.
2563
                break;
2564
        }
2565
        //imagedestroy($this->imageResized);
2566
    }
2567
2568
    ## --------------------------------------------------------
2569
2570
    public function setTransparency($bool)
2571
        # Sep 2011
2572
    {
2573
        $this->keepTransparency = $bool;
2574
    }
2575
2576
    ## --------------------------------------------------------
2577
2578
    public function setFillColor($value)
2579
        # Sep 2011
2580
        # Param in:   (mixed) $value: (array) Could be an array of RGB
2581
        #             (str) Could be hex #ffffff or #fff, fff, ffffff
2582
        #
2583
        # If the keepTransparency is set to false, then no transparency is to be used.
2584
        # This is ideal when you want to save as jpg.
2585
        #
2586
        # this method allows you to set the background color to use instead of
2587
        # transparency.
2588
        #
2589
    {
2590
        $colorArray           = $this->formatColor($value);
2591
        $this->fillColorArray = $colorArray;
2592
    }
2593
2594
    ## --------------------------------------------------------
2595
2596
    public function setCropFromTop($value)
2597
        # Sep 2011
2598
    {
2599
        $this->cropFromTopPercent = $value;
2600
    }
2601
2602
    ## --------------------------------------------------------
2603
2604
    public function testGDInstalled()
2605
        # Author:     Jarrod Oberto
2606
        # Date:       27-02-08
2607
        # Purpose:    Test to see if GD is installed
2608
        # Param in:   n/a
2609
        # Param out:  (bool) True is gd extension loaded otherwise false
2610
        # Reference:
2611
        # Notes:
2612
        #
2613
    {
2614
        if (extension_loaded('gd') && function_exists('gd_info')) {
2615
            $gdInstalled = true;
2616
        } else {
2617
            $gdInstalled = false;
2618
        }
2619
2620
        return $gdInstalled;
2621
    }
2622
2623
    ## --------------------------------------------------------
2624
2625
    public function testEXIFInstalled()
2626
        # Author:     Jarrod Oberto
2627
        # Date:       08-05-11
2628
        # Purpose:    Test to see if EXIF is installed
2629
        # Param in:   n/a
2630
        # Param out:  (bool) True is exif extension loaded otherwise false
2631
        # Reference:
2632
        # Notes:
2633
        #
2634
    {
2635
        if (extension_loaded('exif')) {
2636
            $exifInstalled = true;
2637
        } else {
2638
            $exifInstalled = false;
2639
        }
2640
2641
        return $exifInstalled;
2642
    }
2643
2644
    ## --------------------------------------------------------
2645
2646
    public function testIsImage()
2647
        # Author:     Jarrod Oberto
2648
        # Date:       28 Nov 16
2649
        # Purpose:    Test if file is an image
2650
        # Param in:
2651
        # Param out:  n/a
2652
        # Reference:
2653
        # Notes: A simpler, less restrictive method would be to just check for
2654
        #           the 'image' part of 'image/gif', 'image/jpg', etc.
2655
        #
2656
    {
2657
        $file    = $this->fileName;
2658
        $isImage = false;
0 ignored issues
show
Unused Code introduced by
$isImage is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2659
2660
        $finfo    = finfo_open(FILEINFO_MIME_TYPE);
2661
        $mimeType = finfo_file($finfo, $file);
2662
        finfo_close($finfo);
2663
2664
        switch ($mimeType) {
2665
            case 'image/jpeg':
2666
            case 'image/gif':
2667
            case 'image/png':
2668
            case 'image/bmp':
2669
            case 'image/x-windows-bmp':
2670
                $isImage = true;
2671
                break;
2672
            default:
2673
                $isImage = false;
2674
        }
2675
2676
        return $isImage;
2677
    }
2678
2679
    ## --------------------------------------------------------
2680
2681
    public function getIsImage()
2682
        # Author:     Jarrod Oberto
2683
        # Date:       28 Nov 16
2684
        # Purpose:    Get testIsImage result
2685
        # Param in:
2686
        # Param out:  n/a
2687
        # Reference:
2688
        # Notes:
2689
        #
2690
    {
2691
        return $this->isImage;
2692
    }
2693
2694
    ## --------------------------------------------------------
2695
2696
    public function testFunct()
2697
        # Author:     Jarrod Oberto
2698
        # Date:       27-02-08
2699
        # Purpose:    Test Function
2700
        # Param in:   n/a
2701
        # Param out:  n/a
2702
        # Reference:
2703
        # Notes:
2704
        #
2705
    {
2706
        echo $this->height;
2707
    }
2708
2709
    ## --------------------------------------------------------
2710
2711
    public function setForceStretch($value)
2712
        # Author:     Jarrod Oberto
2713
        # Date:       23-12-10
2714
        # Purpose:
2715
        # Param in:   (bool) $value
2716
        # Param out:  n/a
2717
        # Reference:
2718
        # Notes:
2719
        #
2720
    {
2721
        $this->forceStretch = $value;
2722
    }
2723
2724
    ## --------------------------------------------------------
2725
2726
    public function setFile($fileName)
2727
        # Author:     Jarrod Oberto
2728
        # Date:       28-02-08
2729
        # Purpose:
2730
        # Param in:   n/a
2731
        # Param out:  n/a
2732
        # Reference:
2733
        # Notes:
2734
        #
2735
    {
2736
        try {
2737
            self::__construct($fileName);
2738
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
2739
        }
2740
    }
2741
2742
    ## --------------------------------------------------------
2743
2744
    public function getFileName()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
2745
        # Author:     Jarrod Oberto
2746
        # Date:       10-09-08
2747
        # Purpose:
2748
        # Param in:   n/a
2749
        # Param out:  n/a
2750
        # Reference:
2751
        # Notes:
2752
        #
2753
    {
2754
        return $this->fileName;
2755
    }
2756
2757
    ## --------------------------------------------------------
2758
2759
    public function getHeight()
2760
    {
2761
        return $this->height;
2762
    }
2763
2764
    ## --------------------------------------------------------
2765
2766
    public function getWidth()
2767
    {
2768
        return $this->width;
2769
    }
2770
2771
    ## --------------------------------------------------------
2772
2773
    public function getOriginalHeight()
2774
    {
2775
        return $this->heightOriginal;
2776
    }
2777
2778
    ## --------------------------------------------------------
2779
2780
    public function getOriginalWidth()
2781
    {
2782
        return $this->widthOriginal;
2783
    }
2784
2785
    ## --------------------------------------------------------
2786
2787
    public function getErrors()
2788
        # Author:     Jarrod Oberto
2789
        # Date:       19-11-09
2790
        # Purpose:    Returns the error array
2791
        # Param in:   n/a
2792
        # Param out:  Array of errors
2793
        # Reference:
2794
        # Notes:
2795
        #
2796
    {
2797
        return $this->errorArray;
2798
    }
2799
2800
    ## --------------------------------------------------------
2801
2802
    private function checkInterlaceImage($isEnabled)
2803
        # jpg will use progressive (they don't use interace)
2804
    {
2805
        if ($isEnabled) {
2806
            imageinterlace($this->imageResized, $isEnabled);
2807
        }
2808
    }
2809
2810
    ## --------------------------------------------------------
2811
2812
    protected function formatColor($value)
2813
        # Author:     Jarrod Oberto
2814
        # Date:       09-05-11
2815
        # Purpose:    Determine color method passed in and return color as RGB
2816
        # Param in:   (mixed) $value: (array) Could be an array of RGB
2817
        #             (str) Could be hex #ffffff or #fff, fff, ffffff
2818
        # Param out:
2819
        # Reference:
2820
        # Notes:
2821
        #
2822
    {
2823
        $rgbArray = [];
2824
2825
        // *** If it's an array it should be R, G, B
2826
        if (is_array($value)) {
2827
            if (0 == key($value) && 3 == count($value)) {
2828
                $rgbArray['r'] = $value[0];
2829
                $rgbArray['g'] = $value[1];
2830
                $rgbArray['b'] = $value[2];
2831
            } else {
2832
                $rgbArray = $value;
2833
            }
2834
        } elseif ('transparent' === strtolower($value)) {
2835
            $rgbArray = [
2836
                'r' => 255,
2837
                'g' => 255,
2838
                'b' => 255,
2839
                'a' => 127
2840
            ];
2841
        } else {
2842
            // *** ...Else it should be hex. Let's make it RGB
2843
            $rgbArray = $this->hex2dec($value);
2844
        }
2845
2846
        return $rgbArray;
2847
    }
2848
2849
    ## --------------------------------------------------------
2850
2851
    public function hex2dec($hex)
2852
        # Purpose:  Convert #hex color to RGB
2853
    {
2854
        $color = str_replace('#', '', $hex);
2855
2856
        if (3 == strlen($color)) {
2857
            $color = $color . $color;
2858
        }
2859
2860
        $rgb = [
2861
            'r' => hexdec(substr($color, 0, 2)),
2862
            'g' => hexdec(substr($color, 2, 2)),
2863
            'b' => hexdec(substr($color, 4, 2)),
2864
            'a' => 0
2865
        ];
2866
        return $rgb;
2867
    }
2868
2869
    ## --------------------------------------------------------
2870
2871
    private function createImageColor($colorArray)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
2872
    {
2873
        $r = $colorArray['r'];
2874
        $g = $colorArray['g'];
2875
        $b = $colorArray['b'];
2876
2877
        return imagecolorallocate($this->imageResized, $r, $g, $b);
2878
    }
2879
2880
    ## --------------------------------------------------------
2881
2882
    private function testColorExists($colorArray)
2883
    {
2884
        $r = $colorArray['r'];
2885
        $g = $colorArray['g'];
2886
        $b = $colorArray['b'];
2887
2888
        if (-1 == imagecolorexact($this->imageResized, $r, $g, $b)) {
2889
            return false;
2890
        } else {
2891
            return true;
2892
        }
2893
    }
2894
2895
    ## --------------------------------------------------------
2896
2897
    private function findUnusedGreen()
2898
        # Purpose:  We find a green color suitable to use like green-screen effect.
2899
        #     Therefore, the color must not exist in the image.
2900
    {
2901
        $green = 255;
2902
2903
        do {
2904
            $greenChroma = [0, $green, 0];
2905
            $colorArray  = $this->formatColor($greenChroma);
2906
            $match       = $this->testColorExists($colorArray);
2907
            $green--;
2908
        } while (false == $match && $green > 0);
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
2909
2910
        // *** If no match, just bite the bullet and use green value of 255
2911
        if (!$match) {
2912
            $greenChroma = [0, $green, 0];
2913
        }
2914
2915
        return $greenChroma;
2916
    }
2917
2918
    ## --------------------------------------------------------
2919
2920
    private function findUnusedBlue()
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
2921
        # Purpose:  We find a green color suitable to use like green-screen effect.
2922
        #     Therefore, the color must not exist in the image.
2923
    {
2924
        $blue = 255;
2925
2926
        do {
2927
            $blueChroma = [0, 0, $blue];
2928
            $colorArray = $this->formatColor($blueChroma);
2929
            $match      = $this->testColorExists($colorArray);
2930
            $blue--;
2931
        } while (false == $match && $blue > 0);
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
2932
2933
        // *** If no match, just bite the bullet and use blue value of 255
2934
        if (!$match) {
2935
            $blueChroma = [0, 0, $blue];
2936
        }
2937
2938
        return $blueChroma;
2939
    }
2940
2941
    ## --------------------------------------------------------
2942
2943
    private function invertTransparency($value, $originalMax, $invert = true)
2944
        # Purpose:  This does two things:
2945
        #       1) Convert the range from 0-127 to 0-100
2946
        #       2) Inverts value to 100 is not transparent while 0 is fully
2947
        #          transparent (like Photoshop)
2948
    {
2949
        // *** Test max range
2950
        if ($value > $originalMax) {
2951
            $value = $originalMax;
2952
        }
2953
2954
        // *** Test min range
2955
        if ($value < 0) {
2956
            $value = 0;
2957
        }
2958
2959
        if ($invert) {
2960
            return $originalMax - (($value / 100) * $originalMax);
2961
        } else {
2962
            return ($value / 100) * $originalMax;
2963
        }
2964
    }
2965
2966
    ## --------------------------------------------------------
2967
2968
    private function transparentImage($src)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
2969
    {
2970
        // *** making images with white bg transparent
2971
        $r1 = 0;
0 ignored issues
show
Unused Code introduced by
$r1 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2972
        $g1 = 255;
0 ignored issues
show
Unused Code introduced by
$g1 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2973
        $b1 = 0;
0 ignored issues
show
Unused Code introduced by
$b1 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2974
        for ($x = 0; $x < imagesx($src); ++$x) {
2975
            for ($y = 0; $y < imagesy($src); ++$y) {
2976
                $color = imagecolorat($src, $x, $y);
2977
                $r     = ($color >> 16) & 0xFF;
2978
                $g     = ($color >> 8) & 0xFF;
2979
                $b     = $color & 0xFF;
2980
                for ($i = 0; $i < 270; ++$i) {
2981
                    //if ($r . $g . $b == ($r1 + $i) . ($g1 + $i) . ($b1 + $i)) {
2982
                    if (0 == $r && 255 == $g && 0 == $b) {
2983
                        //if ($g == 255) {
2984
                        $trans_colour = imagecolorallocatealpha($src, 0, 0, 0, 127);
2985
                        imagefill($src, $x, $y, $trans_colour);
2986
                    }
2987
                }
2988
            }
2989
        }
2990
2991
        return $src;
2992
    }
2993
2994
    ## --------------------------------------------------------
2995
2996
    public function checkStringStartsWith($needle, $haystack)
2997
        # Check if a string starts with a specific pattern
2998
    {
2999
        return (substr($haystack, 0, strlen($needle)) == $needle);
3000
    }
3001
3002
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
3003
        BMP SUPPORT (SAVING) - James Heinrich
3004
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
3005
3006
    private function GD2BMPstring(&$gd_image)
3007
        # Author:     James Heinrich
3008
        # Purpose:    Save file as type bmp
3009
        # Param in:   The image canvas (passed as ref)
3010
        # Param out:
3011
        # Reference:
3012
        # Notes:      This code was stripped out of two external files
3013
        #             (phpthumb.bmp.php,phpthumb.functions.php) and added below to
3014
        #             avoid dependancies.
3015
        #
3016
    {
3017
        $imageX = imagesx($gd_image);
3018
        $imageY = imagesy($gd_image);
3019
3020
        $BMP = '';
3021
        for ($y = ($imageY - 1); $y >= 0; $y--) {
3022
            $thisline = '';
3023
            for ($x = 0; $x < $imageX; ++$x) {
3024
                $argb     = $this->GetPixelColor($gd_image, $x, $y);
3025
                $thisline .= chr($argb['blue']) . chr($argb['green']) . chr($argb['red']);
3026
            }
3027
            while (strlen($thisline) % 4) {
3028
                $thisline .= "\x00";
3029
            }
3030
            $BMP .= $thisline;
3031
        }
3032
3033
        $bmpSize = strlen($BMP) + 14 + 40;
3034
        // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp
3035
        $BITMAPFILEHEADER = 'BM';                                    // WORD    bfType;
3036
        $BITMAPFILEHEADER .= $this->LittleEndian2String($bmpSize, 4); // DWORD   bfSize;
3037
        $BITMAPFILEHEADER .= $this->LittleEndian2String(0, 2); // WORD    bfReserved1;
3038
        $BITMAPFILEHEADER .= $this->LittleEndian2String(0, 2); // WORD    bfReserved2;
3039
        $BITMAPFILEHEADER .= $this->LittleEndian2String(54, 4); // DWORD   bfOffBits;
3040
3041
        // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp
3042
        $BITMAPINFOHEADER = $this->LittleEndian2String(40, 4); // DWORD  biSize;
3043
        $BITMAPINFOHEADER .= $this->LittleEndian2String($imageX, 4); // LONG   biWidth;
3044
        $BITMAPINFOHEADER .= $this->LittleEndian2String($imageY, 4); // LONG   biHeight;
3045
        $BITMAPINFOHEADER .= $this->LittleEndian2String(1, 2); // WORD   biPlanes;
3046
        $BITMAPINFOHEADER .= $this->LittleEndian2String(24, 2); // WORD   biBitCount;
3047
        $BITMAPINFOHEADER .= $this->LittleEndian2String(0, 4); // DWORD  biCompression;
3048
        $BITMAPINFOHEADER .= $this->LittleEndian2String(0, 4); // DWORD  biSizeImage;
3049
        $BITMAPINFOHEADER .= $this->LittleEndian2String(2835, 4); // LONG   biXPelsPerMeter;
3050
        $BITMAPINFOHEADER .= $this->LittleEndian2String(2835, 4); // LONG   biYPelsPerMeter;
3051
        $BITMAPINFOHEADER .= $this->LittleEndian2String(0, 4); // DWORD  biClrUsed;
3052
        $BITMAPINFOHEADER .= $this->LittleEndian2String(0, 4); // DWORD  biClrImportant;
3053
3054
        return $BITMAPFILEHEADER . $BITMAPINFOHEADER . $BMP;
3055
    }
3056
3057
    ## --------------------------------------------------------
3058
3059
    private function GetPixelColor(&$img, $x, $y)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
3060
        # Author:     James Heinrich
3061
        # Purpose:
3062
        # Param in:
3063
        # Param out:
3064
        # Reference:
3065
        # Notes:
3066
        #
3067
    {
3068
        if (!is_resource($img)) {
3069
            return false;
3070
        }
3071
        return @imagecolorsforindex($img, @imagecolorat($img, $x, $y));
3072
    }
3073
3074
    ## --------------------------------------------------------
3075
3076
    private function LittleEndian2String($number, $minbytes = 1)
3077
        # Author:     James Heinrich
3078
        # Purpose:    BMP SUPPORT (SAVING)
3079
        # Param in:
3080
        # Param out:
3081
        # Reference:
3082
        # Notes:
3083
        #
3084
    {
3085
        $intstring = '';
3086
        while ($number > 0) {
3087
            $intstring = $intstring . chr($number & 255);
3088
            $number    >>= 8;
3089
        }
3090
        return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
3091
    }
3092
3093
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
3094
        BMP SUPPORT (READING)
3095
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
3096
3097
    private function ImageCreateFromBMP($filename)
3098
        # Author:     DHKold
3099
        # Date:     The 15th of June 2005
3100
        # Version:    2.0B
3101
        # Purpose:    To create an image from a BMP file.
3102
        # Param in:   BMP file to open.
3103
        # Param out:  Return a resource like the other ImageCreateFrom functions
3104
        # Reference:  http://us3.php.net/manual/en/function.imagecreate.php#53879
3105
        # Bug fix:    Author:   domelca at terra dot es
3106
        #             Date:   06 March 2008
3107
        #             Fix:    Correct 16bit BMP support
3108
        # Notes:
3109
        #
3110
    {
3111
        //Ouverture du fichier en mode binaire
3112
        if (!$f1 = fopen($filename, 'rb')) {
3113
            return false;
3114
        }
3115
3116
        //1 : Chargement des ent�tes FICHIER
3117
        $FILE = unpack('vfile_type/Vfile_size/Vreserved/Vbitmap_offset', fread($f1, 14));
3118
        if (19778 != $FILE['file_type']) {
3119
            return false;
3120
        }
3121
3122
        //2 : Chargement des ent�tes BMP
3123
        $BMP           = unpack(
3124
            'Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel' . '/Vcompression/Vsize_bitmap/Vhoriz_resolution' . '/Vvert_resolution/Vcolors_used/Vcolors_important',
3125
            fread($f1, 40)
3126
        );
3127
        $BMP['colors'] = pow(2, $BMP['bits_per_pixel']);
3128
3129
        if (0 == $BMP['size_bitmap']) {
3130
            $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
3131
        }
3132
3133
        $BMP['bytes_per_pixel']  = $BMP['bits_per_pixel'] / 8;
3134
        $BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']);
3135
        $BMP['decal']            = ($BMP['width'] * $BMP['bytes_per_pixel'] / 4);
3136
        $BMP['decal']            -= floor($BMP['width'] * $BMP['bytes_per_pixel'] / 4);
3137
        $BMP['decal']            = 4 - (4 * $BMP['decal']);
3138
3139
        if (4 == $BMP['decal']) {
3140
            $BMP['decal'] = 0;
3141
        }
3142
3143
        //3 : Chargement des couleurs de la palette
3144
        $PALETTE = [];
3145
        if ($BMP['colors'] < 16777216) {
3146
            $PALETTE = unpack('V' . $BMP['colors'], fread($f1, $BMP['colors'] * 4));
3147
        }
3148
3149
        //4 : Cr�ation de l'image
3150
        $IMG  = fread($f1, $BMP['size_bitmap']);
3151
        $VIDE = chr(0);
3152
3153
        $res = imagecreatetruecolor($BMP['width'], $BMP['height']);
3154
        $P   = 0;
3155
        $Y   = $BMP['height'] - 1;
3156
        while ($Y >= 0) {
3157
            $X = 0;
3158
            while ($X < $BMP['width']) {
3159
                if (24 == $BMP['bits_per_pixel']) {
3160
                    $COLOR = unpack('V', substr($IMG, $P, 3) . $VIDE);
3161
                } elseif (16 == $BMP['bits_per_pixel']) {
3162
                    /*
3163
                     * BMP 16bit fix
3164
                     * =================
3165
                     *
3166
                     * Ref: http://us3.php.net/manual/en/function.imagecreate.php#81604
3167
                     *
3168
                     * Notes:
3169
                     * "don't work with bmp 16 bits_per_pixel. change pixel
3170
                     * generator for this."
3171
                     *
3172
                     */
3173
3174
                    // *** Original code (don't work)
3175
                    //$COLOR = unpack("n",substr($IMG,$P,2));
3176
                    //$COLOR[1] = $PALETTE[$COLOR[1]+1];
3177
3178
                    $COLOR    = unpack('v', substr($IMG, $P, 2));
3179
                    $blue     = ($COLOR[1] & 0x001f) << 3;
3180
                    $green    = ($COLOR[1] & 0x07e0) >> 3;
3181
                    $red      = ($COLOR[1] & 0xf800) >> 8;
3182
                    $COLOR[1] = $red * 65536 + $green * 256 + $blue;
3183
                } elseif (8 == $BMP['bits_per_pixel']) {
3184
                    $COLOR    = unpack('n', $VIDE . substr($IMG, $P, 1));
3185
                    $COLOR[1] = $PALETTE[$COLOR[1] + 1];
3186
                } elseif (4 == $BMP['bits_per_pixel']) {
3187
                    $COLOR = unpack('n', $VIDE . substr($IMG, floor($P), 1));
3188
                    if (0 == ($P * 2) % 2) {
3189
                        $COLOR[1] = ($COLOR[1] >> 4);
3190
                    } else {
3191
                        $COLOR[1] = ($COLOR[1] & 0x0F);
3192
                    }
3193
                    $COLOR[1] = $PALETTE[$COLOR[1] + 1];
3194
                } elseif (1 == $BMP['bits_per_pixel']) {
3195
                    $COLOR = unpack('n', $VIDE . substr($IMG, floor($P), 1));
3196
                    if (0 == ($P * 8) % 8) {
3197
                        $COLOR[1] = $COLOR[1] >> 7;
3198
                    } elseif (1 == ($P * 8) % 8) {
3199
                        $COLOR[1] = ($COLOR[1] & 0x40) >> 6;
3200
                    } elseif (2 == ($P * 8) % 8) {
3201
                        $COLOR[1] = ($COLOR[1] & 0x20) >> 5;
3202
                    } elseif (3 == ($P * 8) % 8) {
3203
                        $COLOR[1] = ($COLOR[1] & 0x10) >> 4;
3204
                    } elseif (4 == ($P * 8) % 8) {
3205
                        $COLOR[1] = ($COLOR[1] & 0x8) >> 3;
3206
                    } elseif (5 == ($P * 8) % 8) {
3207
                        $COLOR[1] = ($COLOR[1] & 0x4) >> 2;
3208
                    } elseif (6 == ($P * 8) % 8) {
3209
                        $COLOR[1] = ($COLOR[1] & 0x2) >> 1;
3210
                    } elseif (7 == ($P * 8) % 8) {
3211
                        $COLOR[1] = ($COLOR[1] & 0x1);
3212
                    }
3213
                    $COLOR[1] = $PALETTE[$COLOR[1] + 1];
3214
                } else {
3215
                    return false;
3216
                }
3217
3218
                imagesetpixel($res, $X, $Y, $COLOR[1]);
3219
                ++$X;
3220
                $P += $BMP['bytes_per_pixel'];
3221
            }
3222
3223
            $Y--;
3224
            $P += $BMP['decal'];
3225
        }
3226
3227
        //Fermeture du fichier
3228
        fclose($f1);
3229
3230
        return $res;
3231
    }
3232
3233
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
3234
        PSD SUPPORT (READING)
3235
    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
3236
3237
    private function imagecreatefrompsd($fileName)
3238
        # Author:     Tim de Koning
3239
        # Version:    1.3
3240
        # Purpose:    To create an image from a PSD file.
3241
        # Param in:   PSD file to open.
3242
        # Param out:  Return a resource like the other ImageCreateFrom functions
3243
        # Reference:  http://www.kingsquare.nl/phppsdreader
3244
        # Notes:
3245
        #
3246
    {
3247
        if (file_exists($this->psdReaderPath)) {
3248
            include_once($this->psdReaderPath);
3249
3250
            $psdReader = new PhpPsdReader($fileName);
3251
3252
            if (isset($psdReader->infoArray['error'])) {
3253
                return '';
3254
            } else {
3255
                return $psdReader->getImage();
3256
            }
3257
        } else {
3258
            return false;
3259
        }
3260
    }
3261
3262
    ## --------------------------------------------------------
3263
3264
    public function __destruct()
3265
    {
3266
        if (is_resource($this->imageResized)) {
3267
            imagedestroy($this->imageResized);
3268
        }
3269
    }
3270
3271
    ## --------------------------------------------------------
3272
3273
}
3274
3275
3276
3277
3278
/*
3279
 *    Example with some API calls (outdated):
3280
 *
3281
 *
3282
 *      ===============================
3283
 *      Compulsary
3284
 *      ===============================
3285
 *
3286
 *      include("classes/resize_class.php");
3287
 *
3288
 *      // *** Initialise object
3289
 *      $magicianObj = new resize('images/cars/large/a.jpg');
3290
 *
3291
 *      // *** Turn off stretching (optional)
3292
 *      $magicianObj -> setForceStretch(false);
3293
 *
3294
 *      // *** Resize object
3295
 *      $magicianObj -> resizeImage(150, 100, 0);
3296
 *
3297
 *      ===============================
3298
 *      Image options - can run none, one, or all.
3299
 *      ===============================
3300
 *
3301
 *      //  *** Add watermark
3302
 *        $magicianObj -> addWatermark('stamp.png');
3303
 *
3304
 *          // *** Add text
3305
 *      $magicianObj -> addText('testing...');
3306
 *
3307
 *      ===============================
3308
 *      Output options - can run one, or the other, or both.
3309
 *      ===============================
3310
 *
3311
 *      // *** Save image to disk
3312
 *      $magicianObj -> saveImage('images/cars/large/b.jpg', 100);
3313
 *
3314
 *          // *** Or output to screen (params in can be jpg, gif, png)
3315
 *      $magicianObj -> displayImage('png');
3316
 *
3317
 *      ===============================
3318
 *      Return options - return errors. nice for debuggin.
3319
 *      ===============================
3320
 *
3321
 *      // *** Return error array
3322
 *      $errorArray = $magicianObj -> getErrors();
3323
 *
3324
 *
3325
 *      ===============================
3326
 *      Cleanup options - not really neccessary, but good practice
3327
 *      ===============================
3328
 *
3329
 *      // *** Free used memory
3330
 *      $magicianObj -> __destruct();
3331
 */
3332