Passed
Pull Request — master (#7)
by Mattia
08:27 queued 03:30
created

LayerValidator::check()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 3
c 1
b 0
f 1
dl 0
loc 6
rs 10
cc 2
nc 2
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Minepic\Image;
6
7
use Minepic\Image\Components\Side;
8
use Minepic\Image\Exceptions\ImageTrueColorCreationFailedException;
9
10
class LayerValidator
11
{
12
    /**
13
     * Max Standard Deviation value for layer check.
14
     */
15
    private const DEFAULT_STANDARD_DEVIATION = 0.2;
16
    private int $meanAlpha;
17
    private float $redStdDev;
18
    private float $greenStdDev;
19
    private float $blueStdDev;
20
21
    /**
22
     * Checks if base image has helm for section.
23
     *
24
     * @param \GdImage $sourceImage
25
     * @param Side     $side
26
     *
27
     *@throws \Minepic\Image\Exceptions\ImageTrueColorCreationFailedException
28
     *@return bool
29
     */
30
    public function check($sourceImage, Side $side): bool
31
    {
32
        $checkImage = $this->createCheckImage($sourceImage, $side);
33
        $this->calculate($checkImage, $side);
0 ignored issues
show
Bug introduced by
$checkImage of type resource is incompatible with the type GdImage expected by parameter $checkImage of Minepic\Image\LayerValidator::calculate(). ( Ignorable by Annotation )

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

33
        $this->calculate(/** @scrutinizer ignore-type */ $checkImage, $side);
Loading history...
34
35
        return $this->validStdDev() || $this->meanAlpha === 127;
36
    }
37
38
    /**
39
     * Calculate sttdev for merging helm.
40
     *
41
     * @param \GdImage $checkImage
42
     * @param Side $side
43
     */
44
    protected function calculate($checkImage, Side $side): void
45
    {
46
        // Check for helm image
47
        $allRed = [];
48
        $allGreen = [];
49
        $allBlue = [];
50
        $allAlpha = [];
51
        $x = 0;
52
        while ($x < $side->getWidth()) {
53
            $y = 0;
54
            while ($y < $side->getHeight()) {
55
                $color = \imagecolorat($checkImage, $x, $y);
56
                $colors = \imagecolorsforindex($checkImage, $color);
57
                $allRed[] = $colors['red'];
58
                $allGreen[] = $colors['green'];
59
                $allBlue[] = $colors['blue'];
60
                $allAlpha[] = $colors['alpha'];
61
                ++$y;
62
            }
63
            ++$x;
64
        }
65
        // mean value for each color
66
        $totalPixels = $side->getWidth() * $side->getHeight();
67
        $meanRed = \array_sum($allRed) / $totalPixels;
68
        $meanGreen = \array_sum($allGreen) / $totalPixels;
69
        $meanBlue = \array_sum($allBlue) / $totalPixels;
70
        $this->meanAlpha = (int) \round(\array_sum($allAlpha) / $totalPixels);
71
        // Arrays deviation
72
        $devsRed = [];
73
        $devsGreen = [];
74
        $devsBlue = [];
75
        $i = 0;
76
        while ($i < $totalPixels) {
77
            $devsRed[] = ($allRed[$i] - $meanRed) ** 2;
78
            $devsGreen[] = ($allGreen[$i] - $meanGreen) ** 2;
79
            $devsBlue[] = ($allBlue[$i] - $meanBlue) ** 2;
80
            ++$i;
81
        }
82
        // stddev for each color
83
        $this->redStdDev = \sqrt(\array_sum($devsRed) / $totalPixels);
84
        $this->greenStdDev = \sqrt(\array_sum($devsGreen) / $totalPixels);
85
        $this->blueStdDev = \sqrt(\array_sum($devsBlue) / $totalPixels);
86
    }
87
88
    /**
89
     * @param \GdImage $sourceImage
90
     * @param Side $side
91
     *
92
     *@throws \Minepic\Image\Exceptions\ImageTrueColorCreationFailedException
93
     * @return resource
94
     */
95
    private function createCheckImage($sourceImage, Side $side)
96
    {
97
        $width = $side->getWidth();
98
        $height = $side->getHeight();
99
        $checkImage = \imagecreatetruecolor($side->getWidth(), $side->getHeight());
100
        if ($checkImage === false) {
101
            throw new ImageTrueColorCreationFailedException('imagecreatetruecolor failed');
102
        }
103
        \imagealphablending($checkImage, false);
104
        \imagesavealpha($checkImage, true);
105
        $colorIdentifier = \imagecolorallocatealpha($checkImage, 255, 255, 255, 127);
106
        \imagefilledrectangle($checkImage, 0, 0, $width, $height, $colorIdentifier);
107
        \imagecopy($checkImage, $sourceImage, 0, 0, $side->getTopLeft()->getX(), $side->getTopLeft()->getY(), $width, $height);
108
109
        return $checkImage;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $checkImage also could return the type GdImage which is incompatible with the documented return type resource.
Loading history...
110
    }
111
112
    /**
113
     * @return bool
114
     */
115
    private function validStdDev(): bool
116
    {
117
        return ($this->redStdDev > self::DEFAULT_STANDARD_DEVIATION && $this->greenStdDev > self::DEFAULT_STANDARD_DEVIATION) ||
118
            ($this->redStdDev > self::DEFAULT_STANDARD_DEVIATION && $this->blueStdDev > self::DEFAULT_STANDARD_DEVIATION) ||
119
            ($this->greenStdDev > self::DEFAULT_STANDARD_DEVIATION && $this->blueStdDev > self::DEFAULT_STANDARD_DEVIATION);
120
    }
121
}
122