Passed
Push — master ( 10a915...0d23d6 )
by Mattia
08:28 queued 11s
created

Avatar::calculateHelmStandardDeviation()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 41
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 32
c 1
b 0
f 0
nc 6
nop 1
dl 0
loc 41
rs 9.408
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Image\Sections;
6
7
use App\Image\ImageSection;
8
9
/**
10
 * Class Avatar.
11
 */
12
class Avatar extends ImageSection
13
{
14
    /**
15
     * Max Standard Deviation value for helm check.
16
     */
17
    private const DEFAULT_STANDARD_DEVIATION = 0.2;
18
19
    /**
20
     * Mean Alpha value (Helm).
21
     *
22
     * @var int
23
     */
24
    protected $meanAlpha = 0;
25
26
    /**
27
     * Red Standard Deviation value (Helm).
28
     *
29
     * @var int
30
     */
31
    protected $redStdDev = 0;
32
33
    /**
34
     * Green Standard Deviation value (Helm).
35
     *
36
     * @var int
37
     */
38
    protected $greenStdDev = 0;
39
40
    /**
41
     * Blue Standard Deviation value (Helm).
42
     *
43
     * @var int
44
     */
45
    protected $blueStdDev = 0;
46
47
    /**
48
     * Calculate sttdev for merging helm.
49
     *
50
     * @param $head_part
51
     */
52
    protected function calculateHelmStandardDeviation($head_part): void
53
    {
54
        // Check for helm image
55
        $all_red = [];
56
        $all_green = [];
57
        $all_blue = [];
58
        $all_alpha = [];
59
        $x = 0;
60
        while ($x < 8) {
61
            $y = 0;
62
            while ($y < 8) {
63
                $color = \imagecolorat($head_part, $x, $y);
64
                $colors = \imagecolorsforindex($head_part, $color);
65
                $all_red[] = $colors['red'];
66
                $all_green[] = $colors['green'];
67
                $all_blue[] = $colors['blue'];
68
                $all_alpha[] = $colors['alpha'];
69
                ++$y;
70
            }
71
            ++$x;
72
        }
73
        // mean value for each color
74
        $mean_red = \array_sum($all_red) / 64;
75
        $mean_green = \array_sum($all_green) / 64;
76
        $mean_blue = \array_sum($all_blue) / 64;
77
        $this->meanAlpha = \array_sum($all_alpha) / 64;
78
        // Arrays deviation
79
        $devs_red = [];
80
        $devs_green = [];
81
        $devs_blue = [];
82
        $i = 0;
83
        while ($i < 64) {
84
            $devs_red[] = ($all_red[$i] - $mean_red) ** 2;
85
            $devs_green[] = ($all_green[$i] - $mean_green) ** 2;
86
            $devs_blue[] = ($all_blue[$i] - $mean_blue) ** 2;
87
            ++$i;
88
        }
89
        // stddev for each color
90
        $this->redStdDev = \sqrt(\array_sum($devs_red) / 64);
91
        $this->greenStdDev = \sqrt(\array_sum($devs_green) / 64);
92
        $this->blueStdDev = \sqrt(\array_sum($devs_blue) / 64);
93
    }
94
95
    /**
96
     * Render avatar image.
97
     *
98
     * @throws \Throwable
99
     */
100
    public function renderAvatar(int $size = 0, string $type = 'F'): void
101
    {
102
        if ($size <= 0 || $size > env('MAX_AVATAR_SIZE')) {
103
            $size = (int) env('DEFAULT_AVATAR_SIZE');
104
        }
105
        // generate png from url/path
106
        $image = \imagecreatefrompng($this->skinPath);
107
        \imagealphablending($image, false);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; however, parameter $image of imagealphablending() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

107
        \imagealphablending(/** @scrutinizer ignore-type */ $image, false);
Loading history...
108
        \imagesavealpha($image, true);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; however, parameter $image of imagesavealpha() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

108
        \imagesavealpha(/** @scrutinizer ignore-type */ $image, true);
Loading history...
109
110
        // Head
111
        $this->imgResource = \imagecreatetruecolor($size, $size);
0 ignored issues
show
Documentation Bug introduced by
It seems like imagecreatetruecolor($size, $size) can also be of type false. However, the property $imgResource is declared as type resource. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
112
113
        // Helm
114
        $helm_check = \imagecreatetruecolor($size, $size);
115
        \imagealphablending($helm_check, false);
116
        \imagesavealpha($helm_check, true);
117
        $transparent = \imagecolorallocatealpha($helm_check, 255, 255, 255, 127);
0 ignored issues
show
Bug introduced by
It seems like $helm_check can also be of type false; however, parameter $image of imagecolorallocatealpha() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

117
        $transparent = \imagecolorallocatealpha(/** @scrutinizer ignore-type */ $helm_check, 255, 255, 255, 127);
Loading history...
118
        \imagefilledrectangle($helm_check, 0, 0, 8, 8, $transparent);
0 ignored issues
show
Bug introduced by
It seems like $helm_check can also be of type false; however, parameter $image of imagefilledrectangle() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

118
        \imagefilledrectangle(/** @scrutinizer ignore-type */ $helm_check, 0, 0, 8, 8, $transparent);
Loading history...
119
120
        switch ($type) {
121
            case 'F':
122
                // Avatar front
123
                $sectionSrcX = 8;
124
                $sectionSrcY = 8;
125
126
                // Avatar Helm front
127
                $sectionHelmSrcX = 40;
128
                $sectionHelmSrcY = 8;
129
130
                break;
131
            case 'B':
132
                // Avatar back
133
                $sectionSrcX = 24;
134
                $sectionSrcY = 8;
135
136
                // Avatar Helm back
137
                $sectionHelmSrcX = 56;
138
                $sectionHelmSrcY = 8;
139
140
                break;
141
            case 'R':
142
                // Avatar right
143
                $sectionSrcX = 0;
144
                $sectionSrcY = 8;
145
146
                // Avatar Helm right
147
                $sectionHelmSrcX = 32;
148
                $sectionHelmSrcY = 8;
149
150
                break;
151
            case 'L':
152
                // Avatar left
153
                $sectionSrcX = 16;
154
                $sectionSrcY = 8;
155
156
                // Avatar Helm left
157
                $sectionHelmSrcX = 56;
158
                $sectionHelmSrcY = 8;
159
160
                break;
161
            case 'T':
162
                // Avatar right
163
                $sectionSrcX = 8;
164
                $sectionSrcY = 0;
165
166
                // Avatar Helm right
167
                $sectionHelmSrcX = 40;
168
                $sectionHelmSrcY = 0;
169
                break;
170
            default:
171
                // TODO: Custom exception
172
                throw new \Exception('Invalid avatar section specified');
173
                break;
174
        }
175
176
        @\imagecopyresampled($this->imgResource, $image, 0, 0, $sectionSrcX, $sectionSrcY, $size, $size, 8, 8);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; however, parameter $src_image of imagecopyresampled() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

176
        @\imagecopyresampled($this->imgResource, /** @scrutinizer ignore-type */ $image, 0, 0, $sectionSrcX, $sectionSrcY, $size, $size, 8, 8);
Loading history...
Bug introduced by
It seems like $this->imgResource can also be of type false; however, parameter $dst_image of imagecopyresampled() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

176
        @\imagecopyresampled(/** @scrutinizer ignore-type */ $this->imgResource, $image, 0, 0, $sectionSrcX, $sectionSrcY, $size, $size, 8, 8);
Loading history...
Security Best Practice introduced by
It seems like you do not handle an error condition for imagecopyresampled(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

176
        /** @scrutinizer ignore-unhandled */ @\imagecopyresampled($this->imgResource, $image, 0, 0, $sectionSrcX, $sectionSrcY, $size, $size, 8, 8);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
177
        @\imagecopyresampled($helm_check, $image, 0, 0, $sectionHelmSrcX, $sectionHelmSrcY, 8, 8, 8, 8);
178
179
        $this->calculateHelmStandardDeviation($helm_check);
180
181
        // if all pixel have transparency or the colors aren't the same
182
        if ((
183
            ($this->redStdDev > self::DEFAULT_STANDARD_DEVIATION && $this->greenStdDev > self::DEFAULT_STANDARD_DEVIATION) ||
184
            ($this->redStdDev > self::DEFAULT_STANDARD_DEVIATION && $this->blueStdDev > self::DEFAULT_STANDARD_DEVIATION) ||
185
            ($this->greenStdDev > self::DEFAULT_STANDARD_DEVIATION && $this->blueStdDev > self::DEFAULT_STANDARD_DEVIATION)
186
            ) ||
187
            ($this->meanAlpha === 127)) {
188
            $helm = \imagecreatetruecolor($size, $size);
189
            \imagealphablending($helm, false);
190
            \imagesavealpha($helm, true);
191
            $transparent = \imagecolorallocatealpha($helm, 255, 255, 255, 127);
192
            \imagefilledrectangle($helm, 0, 0, $size, $size, $transparent);
193
            \imagecopyresampled($helm, $image, 0, 0, $sectionHelmSrcX, $sectionHelmSrcY, $size, $size, 8, 8);
194
            $merge = \imagecreatetruecolor($size, $size);
195
            \imagecopy($merge, $this->imgResource, 0, 0, 0, 0, $size, $size);
0 ignored issues
show
Bug introduced by
It seems like $this->imgResource can also be of type false; however, parameter $src_im of imagecopy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

195
            \imagecopy($merge, /** @scrutinizer ignore-type */ $this->imgResource, 0, 0, 0, 0, $size, $size);
Loading history...
Bug introduced by
It seems like $merge can also be of type false; however, parameter $dst_im of imagecopy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

195
            \imagecopy(/** @scrutinizer ignore-type */ $merge, $this->imgResource, 0, 0, 0, 0, $size, $size);
Loading history...
196
            \imagecopy($merge, $helm, 0, 0, 0, 0, $size, $size);
197
            \imagecopymerge($this->imgResource, $merge, 0, 0, 0, 0, $size, $size, 0);
0 ignored issues
show
Bug introduced by
It seems like $this->imgResource can also be of type false; however, parameter $dst_im of imagecopymerge() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

197
            \imagecopymerge(/** @scrutinizer ignore-type */ $this->imgResource, $merge, 0, 0, 0, 0, $size, $size, 0);
Loading history...
Bug introduced by
It seems like $merge can also be of type false; however, parameter $src_im of imagecopymerge() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

197
            \imagecopymerge($this->imgResource, /** @scrutinizer ignore-type */ $merge, 0, 0, 0, 0, $size, $size, 0);
Loading history...
198
            $this->imgResource = $merge;
199
            unset($merge);
200
        }
201
    }
202
}
203