phpUnsharpMask::applyUnsharpMask()   C
last analyzed

Complexity

Conditions 15
Paths 43

Size

Total Lines 100
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 15
eloc 57
nc 43
nop 4
dl 0
loc 100
rs 5.9166
c 4
b 0
f 0

How to fix   Long Method    Complexity   

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
////            Unsharp Mask for PHP - version 2.1.1
5
////
6
////    Unsharp mask algorithm by Torstein Hønsi 2003-07.
7
////             thoensi_at_netcom_dot_no.
8
////               Please leave this notice.
9
////
10
//////////////////////////////////////////////////////////////
11
//  From: http://vikjavev.no/computing/ump.php              //
12
//                                                          //
13
//  Reformatted by James Heinrich <[email protected]>   //
14
//    for use in phpThumb() on 3 February 2003.             //
15
//    updated to v2.1.1 on 24 April 2011                    //
16
//                                                          //
17
//  phpThumb() is found at http://phpthumb.sourceforge.net  //
18
//         and/or https://github.com/JamesHeinrich/phpThumb //
19
//////////////////////////////////////////////////////////////
20
21
/*
22
New:
23
- In version 2.1 (February 26 2007) Tom Bishop has done some important speed enhancements.
24
- From version 2 (July 17 2006) the script uses the imageconvolution function in PHP
25
  version >= 5.1, which improves the performance considerably.
26
27
Unsharp masking is a traditional darkroom technique that has proven very suitable for
28
digital imaging. The principle of unsharp masking is to create a blurred copy of the image
29
and compare it to the underlying original. The difference in colour values
30
between the two images is greatest for the pixels near sharp edges. When this
31
difference is subtracted from the original image, the edges will be
32
accentuated.
33
34
The Amount parameter simply says how much of the effect you want. 100 is 'normal'.
35
Radius is the radius of the blurring circle of the mask. 'Threshold' is the least
36
difference in colour values that is allowed between the original and the mask. In practice
37
this means that low-contrast areas of the picture are left unrendered whereas edges
38
are treated normally. This is good for pictures of e.g. skin or blue skies.
39
40
Any suggenstions for improvement of the algorithm, especially regarding the speed
41
and the roundoff errors in the Gaussian blur process, are welcome.
42
*/
43
44
class phpUnsharpMask
45
{
46
    public static function applyUnsharpMask(&$img, $amount, $radius, $threshold)
47
    {
48
        // $img is an image that is already created within php using
49
        // imgcreatetruecolor. No url! $img must be a truecolor image.
50
51
        // Attempt to calibrate the parameters to Photoshop:
52
        $amount    = min($amount, 500) * 0.016;
53
        $radius    = abs(round(min(50, $radius) * 2)); // Only integers make sense.
54
        $threshold = min(255, $threshold);
55
        if ($radius == 0) {
56
            return true;
57
        }
58
        $w         = imagesx($img);
59
        $h         = imagesy($img);
60
        $imgCanvas = imagecreatetruecolor($w, $h);
61
        $imgBlur   = imagecreatetruecolor($w, $h);
62
63
        // Gaussian blur matrix:
64
        //
65
        //    1    2    1
66
        //    2    4    2
67
        //    1    2    1
68
        //
69
        //////////////////////////////////////////////////
70
71
        if (function_exists('imageconvolution')) { // PHP >= 5.1
72
            $matrix = [
73
                [1, 2, 1],
74
                [2, 4, 2],
75
                [1, 2, 1],
76
            ];
77
            imagecopy($imgBlur, $img, 0, 0, 0, 0, $w, $h);
78
            imageconvolution($imgBlur, $matrix, 16, 0);
79
        } else {
80
            // Move copies of the image around one pixel at the time and merge them with weight
81
            // according to the matrix. The same matrix is simply repeated for higher radii.
82
            for ($i = 0; $i < $radius; $i++) {
83
                imagecopy($imgBlur, $img, 0, 0, 1, 0, $w - 1, $h);               // left
84
                imagecopymerge($imgBlur, $img, 1, 0, 0, 0, $w, $h, 50);       // right
85
                imagecopymerge($imgBlur, $img, 0, 0, 0, 0, $w, $h, 50);       // center
86
                imagecopy($imgCanvas, $imgBlur, 0, 0, 0, 0, $w, $h);
87
                imagecopymerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 33.33333); // up
0 ignored issues
show
Bug introduced by
33.33333 of type double is incompatible with the type integer expected by parameter $pct of imagecopymerge(). ( Ignorable by Annotation )

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

87
                imagecopymerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, /** @scrutinizer ignore-type */ 33.33333); // up
Loading history...
88
                imagecopymerge($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 25);       // down
89
            }
90
        }
91
92
        if ($threshold > 0) {
93
            // Calculate the difference between the blurred pixels and the original
94
            // and set the pixels
95
            for ($x = 0; $x < $w - 1; $x++) { // each row
96
                for ($y = 0; $y < $h; $y++) { // each pixel
97
98
                    $rgbOrig = imagecolorat($img, $x, $y);
99
                    $rOrig   = (($rgbOrig >> 16) & 0xFF);
100
                    $gOrig   = (($rgbOrig >> 8) & 0xFF);
101
                    $bOrig   = ($rgbOrig & 0xFF);
102
103
                    $rgbBlur = imagecolorat($imgBlur, $x, $y);
104
105
                    $rBlur = (($rgbBlur >> 16) & 0xFF);
106
                    $gBlur = (($rgbBlur >> 8) & 0xFF);
107
                    $bBlur = ($rgbBlur & 0xFF);
108
109
                    // When the masked pixels differ less from the original
110
                    // than the threshold specifies, they are set to their original value.
111
                    $rNew = ((abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig);
112
                    $gNew = ((abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig);
113
                    $bNew = ((abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig);
114
115
                    if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) {
116
                        $pixCol = imagecolorallocate($img, $rNew, $gNew, $bNew);
117
                        imagesetpixel($img, $x, $y, $pixCol);
118
                    }
119
                }
120
            }
121
        } else {
122
            for ($x = 0; $x < $w; $x++) { // each row
123
                for ($y = 0; $y < $h; $y++) { // each pixel
124
                    $rgbOrig = imagecolorat($img, $x, $y);
125
                    $rOrig   = (($rgbOrig >> 16) & 0xFF);
126
                    $gOrig   = (($rgbOrig >> 8) & 0xFF);
127
                    $bOrig   = ($rgbOrig & 0xFF);
128
129
                    $rgbBlur = imagecolorat($imgBlur, $x, $y);
130
131
                    $rBlur = (($rgbBlur >> 16) & 0xFF);
132
                    $gBlur = (($rgbBlur >> 8) & 0xFF);
133
                    $bBlur = ($rgbBlur & 0xFF);
134
135
                    $rNew   = min(255, max(0, ($amount * ($rOrig - $rBlur)) + $rOrig));
136
                    $gNew   = min(255, max(0, ($amount * ($gOrig - $gBlur)) + $gOrig));
137
                    $bNew   = min(255, max(0, ($amount * ($bOrig - $bBlur)) + $bOrig));
138
                    $rgbNew = ($rNew << 16) + ($gNew << 8) + $bNew;
139
                    imagesetpixel($img, $x, $y, $rgbNew);
140
                }
141
            }
142
        }
143
        imagedestroy($imgCanvas);
144
        imagedestroy($imgBlur);
145
        return true;
146
    }
147
}
148