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