Processor::resize()   A
last analyzed

Complexity

Conditions 6
Paths 64

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 13
nc 64
nop 2
dl 0
loc 20
ccs 9
cts 9
cp 1
crap 6
rs 9.2222
c 1
b 0
f 0
1
<?php
2
3
namespace kalanis\kw_images\Graphics;
4
5
6
use kalanis\kw_images\ImagesException;
7
use kalanis\kw_images\Interfaces\IIMTranslations;
8
use kalanis\kw_images\Traits\TLang;
9
10
11
/**
12
 * Class Processor
13
 * @package kalanis\kw_images
14
 * Pass images in temporary local storage  - cannot work with images directly in main storage
15
 */
16
class Processor
17
{
18
    use TLang;
19
20
    protected Format\Factory $factory;
21
    /** @var resource|\GdImage|null */
22
    protected $resource = null;
23
24
    /**
25
     * @param Format\Factory $factory
26
     * @param IIMTranslations|null $lang
27
     * @throws ImagesException
28
     */
29 48
    public function __construct(Format\Factory $factory, ?IIMTranslations $lang = null)
30
    {
31 48
        $this->setImLang($lang);
32
33 48
        if (!(function_exists('imagecreatetruecolor')
34 48
            && function_exists('imagecolorallocate')
35 48
            && function_exists('imagesetpixel')
36 48
            && function_exists('imagecopyresized')
37 48
            && function_exists('imagecopyresampled')
38 48
            && function_exists('imagesx')
39 48
            && function_exists('imagesy')
40 48
            && function_exists('imagerotate')
41 48
            && function_exists('imageflip')
42
        )) {
43
            // @codeCoverageIgnoreStart
44
            throw new ImagesException($this->getImLang()->imGdLibNotPresent(), ImagesException::PROCESSOR_NO_LIBRARY);
45
        }
46
        // @codeCoverageIgnoreEnd
47
48 48
        $this->factory = $factory;
49
    }
50
51
    /**
52
     * @param string $type
53
     * @param string $tempPath
54
     * @throws ImagesException
55
     * @return $this
56
     */
57 27
    public function load(string $type, string $tempPath): self
58
    {
59 27
        $processor = $this->factory->getByType($type, $this->getImLang());
60 26
        $this->resource = $processor->load($tempPath);
61 23
        return $this;
62
    }
63
64
    /**
65
     * @param string $type
66
     * @param string $tempPath
67
     * @throws ImagesException
68
     * @return $this
69
     */
70 20
    public function save(string $type, string $tempPath): self
71
    {
72 20
        $processor = $this->factory->getByType($type, $this->getImLang());
73 20
        $processor->save($tempPath, $this->getResource());
74 20
        return $this;
75
    }
76
77
    /**
78
     * Change image size - cut it to desired size
79
     * @param int|null $width
80
     * @param int|null $height
81
     * @throws ImagesException
82
     * @return $this
83
     */
84 1
    public function resize(?int $width = null, ?int $height = null): self
85
    {
86 1
        $fromWidth = $this->width();
87 1
        $fromHeight = $this->height();
88 1
        $width = (!is_null($width) && (0 < $width)) ? intval($width) : $fromWidth;
89 1
        $height = (!is_null($height) && (0 < $height)) ? intval($height) : $fromHeight;
90 1
        $resource = $this->create($width, $height);
91
        try {
92 1
            if (false === imagecopyresized($resource, $this->getResource(), 0, 0, 0, 0, $width, $height, $fromWidth, $fromHeight)) {
93
                // @codeCoverageIgnoreStart
94
                @imagedestroy($resource);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagedestroy(). 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

94
                /** @scrutinizer ignore-unhandled */ @imagedestroy($resource);

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...
95
                throw new ImagesException($this->getImLang()->imImageCannotResize(), ImagesException::PROCESSOR_CANNOT_RESIZE);
96
            }
97
            // @codeCoverageIgnoreEnd
98
        } finally {
99
            @imagedestroy($this->getResource());
100
        }
101
        // @codeCoverageIgnoreEnd
102 1
        $this->resource = $resource;
103 1
        return $this;
104
    }
105
106
    /**
107
     * Change image size - content will change its proportions according the passed sizes
108
     * @param int|null $width
109
     * @param int|null $height
110
     * @throws ImagesException
111
     * @return $this
112
     */
113 9
    public function resample(?int $width = null, ?int $height = null): self
114
    {
115 9
        $fromWidth = $this->width();
116 9
        $fromHeight = $this->height();
117 9
        $width = (!is_null($width) && (0 < $width)) ? intval($width) : $fromWidth;
118 9
        $height = (!is_null($height) && (0 < $height)) ? intval($height) : $fromHeight;
119 9
        $resource = $this->create($width, $height);
120
        try {
121 9
            if (false === @imagecopyresampled($resource, $this->getResource(), 0, 0, 0, 0, $width, $height, $fromWidth, $fromHeight)) {
122
                // @codeCoverageIgnoreStart
123
                @imagedestroy($resource);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagedestroy(). 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

123
                /** @scrutinizer ignore-unhandled */ @imagedestroy($resource);

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...
124
                throw new ImagesException($this->getImLang()->imImageCannotResample(), ImagesException::PROCESSOR_CANNOT_RESAMPLE);
125
            }
126
            // @codeCoverageIgnoreEnd
127
        } finally {
128
            @imagedestroy($this->getResource());
129
        }
130
        // @codeCoverageIgnoreEnd
131 9
        $this->resource = $resource;
132 9
        return $this;
133
    }
134
135
    /**
136
     * Rotate image by passed angle
137
     * @param float $angle
138
     * @throws ImagesException
139
     * @return $this
140
     */
141 8
    public function rotate(float $angle): self
142
    {
143 8
        $image = @imagerotate($this->resource, $angle, 0);
144 8
        if (empty($image)) {
145
            // @codeCoverageIgnoreStart
146
            throw new ImagesException($this->getImLang()->imImageCannotOrientate(), ImagesException::PROCESSOR_CANNOT_ROTATE);
147
        }
148
        // @codeCoverageIgnoreEnd
149 8
        $this->resource = $image;
150 8
        return $this;
151
    }
152
153
    /**
154
     * Flip image
155
     * @return $this
156
     */
157 3
    public function flip(int $mode): self
158
    {
159 3
        if (in_array($mode, [IMG_FLIP_HORIZONTAL, IMG_FLIP_VERTICAL, IMG_FLIP_BOTH])) {
160 3
            if (empty(@imageflip($this->resource, $mode))) {
161
                // @codeCoverageIgnoreStart
162
                throw new ImagesException($this->getImLang()->imImageCannotFlip(), ImagesException::PROCESSOR_CANNOT_FLIP);
163
            }
164
            // @codeCoverageIgnoreEnd
165
        }
166 3
        return $this;
167
    }
168
169
    /**
170
     * Create empty image resource
171
     * @param int $width
172
     * @param int $height
173
     * @throws ImagesException
174
     * @return \GdImage|resource
175
     */
176 10
    protected function create(int $width, int $height)
177
    {
178 10
        $resource = @imagecreatetruecolor($width, $height);
179 10
        if (false === $resource) {
180
            // @codeCoverageIgnoreStart
181
            throw new ImagesException($this->getImLang()->imImageCannotCreateEmpty(), ImagesException::PROCESSOR_CANNOT_CREATE);
182
        }
183
        // @codeCoverageIgnoreEnd
184 10
        return $resource;
185
    }
186
187
    /**
188
     * @throws ImagesException
189
     * @return int
190
     */
191 17
    public function width(): int
192
    {
193 17
        $size = @imagesx($this->getResource());
194 17
        if (false === $size) {
195
            // @codeCoverageIgnoreStart
196
            throw new ImagesException($this->getImLang()->imImageCannotGetSize(), ImagesException::PROCESSOR_CANNOT_GET_SIZE);
197
        }
198
        // @codeCoverageIgnoreEnd
199 17
        return intval($size);
200
    }
201
202
    /**
203
     * @throws ImagesException
204
     * @return int
205
     */
206 19
    public function height(): int
207
    {
208 19
        $size = @imagesy($this->getResource());
209 18
        if (false === $size) {
210
            // @codeCoverageIgnoreStart
211
            throw new ImagesException($this->getImLang()->imImageCannotGetSize(), ImagesException::PROCESSOR_CANNOT_GET_SIZE);
212
        }
213
        // @codeCoverageIgnoreEnd
214 18
        return intval($size);
215
    }
216
217
    /**
218
     * @throws ImagesException
219
     * @return \GdImage|resource
220
     */
221 24
    public function getResource()
222
    {
223 24
        if (empty($this->resource)) {
224 1
            throw new ImagesException($this->getImLang()->imImageLoadFirst(), ImagesException::PROCESSOR_CANNOT_GET_RESOURCE);
225
        }
226 23
        return $this->resource;
227
    }
228
}
229