Image::isDark()   B
last analyzed

Complexity

Conditions 7
Paths 6

Size

Total Lines 30
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 7
eloc 19
c 1
b 1
f 0
nc 6
nop 4
dl 0
loc 30
rs 8.8333
1
<?php
2
3
namespace Jackal\ImageMerge\Model;
4
5
use Exception;
6
use Jackal\ImageMerge\Builder\ImageBuilder;
7
8
use Jackal\ImageMerge\Command\Options\SingleCoordinateFileObjectCommandOption;
9
use Jackal\ImageMerge\Command\Asset\ImageAssetCommand;
10
use Jackal\ImageMerge\Exception\InvalidColorException;
11
use Jackal\ImageMerge\Http\Response\ImageResponse;
12
use Jackal\ImageMerge\Metadata\Metadata;
13
use Jackal\ImageMerge\Model\File\FileObjectInterface;
14
use Jackal\ImageMerge\Model\File\FileTempObject;
15
use Jackal\ImageMerge\Model\Format\ImageReader;
16
use Jackal\ImageMerge\Model\Format\ImageWriter;
17
use Jackal\ImageMerge\Utils\ColorUtils;
18
use Jackal\ImageMerge\ValueObject\Coordinate;
19
20
/**
21
 * Class Image
22
 * @package Jackal\ImageMerge\Model
23
 */
24
class Image
25
{
26
    /**
27
     * @var integer
28
     */
29
    private $width;
30
31
    /**
32
     * @var integer
33
     */
34
    private $height;
35
36
    /**
37
     * @var resource
38
     */
39
    private $resource;
40
41
    /**
42
     * @var Metadata
43
     */
44
    private $metadata;
45
46
    /**
47
     * Image constructor.
48
     * @param $width
49
     * @param $height
50
     * @param bool $transparent
51
     * @throws InvalidColorException
52
     */
53
    public function __construct($width, $height, $transparent = true)
54
    {
55
        $this->width = $width;
56
        $this->height = $height;
57
58
        $resource = imagecreatetruecolor($this->width, $this->height);
59
        imagecolortransparent($resource);
0 ignored issues
show
Bug introduced by
It seems like $resource can also be of type false; however, parameter $image of imagecolortransparent() 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

59
        imagecolortransparent(/** @scrutinizer ignore-type */ $resource);
Loading history...
60
61
        if ($transparent) {
62
            imagesavealpha($resource, true);
0 ignored issues
show
Bug introduced by
It seems like $resource 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

62
            imagesavealpha(/** @scrutinizer ignore-type */ $resource, true);
Loading history...
63
            $color = ColorUtils::colorIdentifier($resource, new Color(Color::BLACK), true);
64
            imagefill($resource, 0, 0, $color);
0 ignored issues
show
Bug introduced by
It seems like $resource can also be of type false; however, parameter $image of imagefill() 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

64
            imagefill(/** @scrutinizer ignore-type */ $resource, 0, 0, $color);
Loading history...
65
        }
66
67
        $this->resource = $resource;
0 ignored issues
show
Documentation Bug introduced by
It seems like $resource can also be of type false. However, the property $resource 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...
68
    }
69
70
    /**
71
     * @param FileObjectInterface $filePathName
72
     * @return Image
73
     * @throws Exception
74
     */
75
    public static function fromFile(FileObjectInterface $filePathName)
76
    {
77
        $resource = ImageReader::fromPathname($filePathName);
78
        $imageResource = $resource->getResource();
79
80
        $image = new self(imagesx($imageResource), imagesy($imageResource));
81
        $command = new ImageAssetCommand(new SingleCoordinateFileObjectCommandOption($filePathName, new Coordinate(0, 0)));
82
        $command->execute($image);
83
84
        return $image;
85
    }
86
87
    /**
88
     * @param $contentString
89
     * @return Image
90
     * @throws Exception
91
     */
92
    public static function fromString($contentString)
93
    {
94
        $file = FileTempObject::fromString($contentString);
95
        $resource = ImageReader::fromPathname($file);
96
97
        $image = new self(imagesx($resource->getResource()), imagesy($resource->getResource()));
98
        $command = new ImageAssetCommand(new SingleCoordinateFileObjectCommandOption($file, new Coordinate(0, 0)));
99
        $command->execute($image);
100
101
        return $image;
102
    }
103
104
    /**
105
     * @param $resource
106
     * @return Image
107
     */
108
    public function assignResource($resource)
109
    {
110
        $this->resource = $resource;
111
112
        return $this;
113
    }
114
115
    /**
116
     * @param null $fromX
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $fromX is correct as it would always require null to be passed?
Loading history...
117
     * @param null $fromY
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $fromY is correct as it would always require null to be passed?
Loading history...
118
     * @param null $width
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $width is correct as it would always require null to be passed?
Loading history...
119
     * @param null $height
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $height is correct as it would always require null to be passed?
Loading history...
120
     * @return bool
121
     * @throws Exception
122
     */
123
    public function isDark($fromX = null, $fromY = null, $width = null, $height = null)
124
    {
125
        $samples = 10;
126
        $threshold = 60;
127
128
        if (!is_null($fromY) and !is_null($fromY) and !is_null($width) and !is_null($height)) {
0 ignored issues
show
introduced by
The condition is_null($fromY) is always true.
Loading history...
129
            $builder = new ImageBuilder(clone $this);
130
            $builder->crop($fromX, $fromY, $width, $height);
131
            $portion = $builder->getImage();
132
        } else {
133
            $portion = $this;
134
        }
135
136
        $luminance = 0;
137
        for ($x = 1;$x <= $samples;$x++) {
138
            for ($y = 1;$y <= $samples;$y++) {
139
                $coordX = round($portion->getWidth() / $samples * $x) - ($portion->getWidth() / $samples / 2);
140
                $cooordY = round($portion->getHeight() / $samples * $y) - ($portion->getHeight() / $samples / 2);
141
                $rgb = imagecolorat($portion->getResource(), $coordX, $cooordY);
0 ignored issues
show
Bug introduced by
$cooordY of type double is incompatible with the type integer expected by parameter $y of imagecolorat(). ( Ignorable by Annotation )

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

141
                $rgb = imagecolorat($portion->getResource(), $coordX, /** @scrutinizer ignore-type */ $cooordY);
Loading history...
Bug introduced by
$coordX of type double is incompatible with the type integer expected by parameter $x of imagecolorat(). ( Ignorable by Annotation )

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

141
                $rgb = imagecolorat($portion->getResource(), /** @scrutinizer ignore-type */ $coordX, $cooordY);
Loading history...
142
                $r = ($rgb >> 16) & 0xFF;
143
                $g = ($rgb >> 8) & 0xFF;
144
                $b = $rgb & 0xFF;
145
146
                // choose a simple luminance formula from here
147
                // http://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color
148
                $luminance += ($r + $r + $b + $g + $g + $g) / 6;
149
            }
150
        }
151
152
        return $luminance / ($samples * $samples) <= $threshold;
153
    }
154
155
    /**
156
     * @return resource
157
     */
158
    public function getResource()
159
    {
160
        return $this->resource;
161
    }
162
163
    public function getResourceClone()
164
    {
165
        $original = $this->resource;
166
        $copy = imagecreatetruecolor($this->width, $this->height);
167
168
        imagecopy($copy, $original, 0, 0, 0, 0, $this->width, $this->height);
0 ignored issues
show
Bug introduced by
It seems like $copy 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

168
        imagecopy(/** @scrutinizer ignore-type */ $copy, $original, 0, 0, 0, 0, $this->width, $this->height);
Loading history...
169
170
        return $copy;
171
    }
172
173
    /**
174
     * @param null $filePathName
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $filePathName is correct as it would always require null to be passed?
Loading history...
175
     * @return bool|ImageResponse
176
     * @throws Exception
177
     */
178
    public function toPNG($filePathName = null)
179
    {
180
        return ImageWriter::toPNG($this->getResource(), $filePathName);
181
    }
182
183
    /**
184
     * @param null $filePathName
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $filePathName is correct as it would always require null to be passed?
Loading history...
185
     * @return bool|ImageResponse
186
     * @throws Exception
187
     */
188
    public function toJPG($filePathName = null)
189
    {
190
        return ImageWriter::toJPG($this->getResource(), $filePathName);
191
    }
192
193
    /**
194
     * @param null $filePathName
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $filePathName is correct as it would always require null to be passed?
Loading history...
195
     * @return bool|ImageResponse
196
     * @throws Exception
197
     */
198
    public function toGIF($filePathName = null)
199
    {
200
        return ImageWriter::toGIF($this->getResource(), $filePathName);
201
    }
202
203
    /**
204
     * @param null $filePathName
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $filePathName is correct as it would always require null to be passed?
Loading history...
205
     * @return bool|ImageResponse
206
     * @throws Exception
207
     */
208
    public function toWebP($filePathName = null){
209
        return ImageWriter::toWebP($this->getResource(), $filePathName);
210
    }
211
212
    /**
213
     * @return mixed
214
     */
215
    public function getWidth()
216
    {
217
        return imagesx($this->getResource());
218
    }
219
220
    /**
221
     * @return mixed
222
     */
223
    public function getHeight()
224
    {
225
        return imagesy($this->getResource());
226
    }
227
228
    /**
229
     * @return float
230
     */
231
    public function getAspectRatio()
232
    {
233
        return $this->getWidth() / $this->getHeight();
234
    }
235
236
    /**
237
     * @return bool
238
     */
239
    public function isVertical()
240
    {
241
        return $this->getAspectRatio() < 1;
242
    }
243
244
    /**
245
     * @return bool
246
     */
247
    public function isHorizontal()
248
    {
249
        return $this->getAspectRatio() > 1;
250
    }
251
252
    /**
253
     * @return bool
254
     */
255
    public function isSquare()
256
    {
257
        return $this->getAspectRatio() == 1;
258
    }
259
260
    public function addMetadata(Metadata $metadata)
261
    {
262
        $this->metadata = $metadata;
263
    }
264
265
    /**
266
     * @return Metadata
267
     */
268
    public function getMetadata()
269
    {
270
        return $this->metadata;
271
    }
272
}
273