Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
65 / 65
100.00% covered (success)
100.00%
18 / 18
CRAP
100.00% covered (success)
100.00%
1 / 1
Image
100.00% covered (success)
100.00%
65 / 65
100.00% covered (success)
100.00%
18 / 18
34
100.00% covered (success)
100.00%
1 / 1
 createImageFromFile
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 createImageFromStream
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 loadImageFromFile
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
6
 loadImageFromStream
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
5
 resizeToWidth
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 resizeToHeight
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 resize
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 scale
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 isFile
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 isStream
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 getImage
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStream
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWidth
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHeight
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getResizedWidth
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
 getResizedHeight
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
 getResizeDimensions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isPreserveResolution
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Pdf\Document\Page;
16
17/**
18 * Pdf page image class
19 *
20 * @category   Pop
21 * @package    Pop\Pdf
22 * @author     Nick Sagona, III <nick@popphp.org>
23 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
24 * @license    https://www.popphp.org/license     New BSD License
25 * @version    6.0.0
26 */
27class Image
28{
29
30    /**
31     * Image file name
32     * @var ?string
33     */
34    protected ?string $image = null;
35
36    /**
37     * Image stream
38     * @var string
39     */
40    protected ?string $stream = null;
41
42    /**
43     * Image width
44     * @var int|float|null
45     */
46    protected int|float|null $width = null;
47
48    /**
49     * Image height
50     * @var int|float|null
51     */
52    protected int|float|null $height = null;
53
54    /**
55     * Image resize value
56     * @var ?array
57     */
58    protected ?array $resize = null;
59
60    /**
61     * Flag to preserve image resolution
62     * @var bool
63     */
64    protected bool $preserveResolution = false;
65
66    /**
67     * Create PDF image object from file
68     *
69     * @param  string $file
70     * @throws Exception
71     * @return Image
72     */
73    public static function createImageFromFile(string $file): Image
74    {
75        $image = new self();
76        $image->loadImageFromFile($file);
77        return $image;
78    }
79
80    /**
81     * Create PDF image object from data stream
82     *
83     * @param  string $stream
84     * @throws Exception
85     * @return Image
86     */
87    public static function createImageFromStream(string $stream): Image
88    {
89        $image = new self();
90        $image->loadImageFromStream($stream);
91        return $image;
92    }
93
94    /**
95     * Load image from file
96     *
97     * @param  string $file
98     * @throws Exception
99     * @return Image
100     */
101    public function loadImageFromFile(string $file): Image
102    {
103        if (!file_exists($file)) {
104            throw new Exception('Error: That image file does not exist.');
105        }
106
107        $imgSize = getimagesize($file);
108
109        if (!isset($imgSize['mime']) ||
110            (($imgSize['mime'] != 'image/jpeg') &&
111                ($imgSize['mime'] != 'image/gif') && ($imgSize['mime'] != 'image/png'))) {
112            throw new Exception(
113                'Error: That image type is not supported. Only GIF, JPG and PNG image types are supported.'
114            );
115        }
116
117        // Set image properties.
118        $this->image  = $file;
119        $this->width  = $imgSize[0];
120        $this->height = $imgSize[1];
121
122        return $this;
123    }
124
125    /**
126     * Load image from stream
127     *
128     * @param  string $stream
129     * @throws Exception
130     * @return Image
131     */
132    public function loadImageFromStream(string $stream): Image
133    {
134        $imgSize = getimagesizefromstring($stream);
135
136        if (!isset($imgSize['mime']) ||
137            (($imgSize['mime'] != 'image/jpeg') &&
138                ($imgSize['mime'] != 'image/gif') && ($imgSize['mime'] != 'image/png'))) {
139            throw new Exception(
140                'Error: That image type is not supported. Only GIF, JPG and PNG image types are supported.'
141            );
142        }
143
144        $this->stream = $stream;
145        $this->width  = $imgSize[0];
146        $this->height = $imgSize[1];
147
148        return $this;
149    }
150
151    /**
152     * Resize image to width
153     *
154     * @param  int|float $width
155     * @param  bool      $preserveResolution
156     * @return Image
157     */
158    public function resizeToWidth(int|float $width, bool $preserveResolution = false): Image
159    {
160        $this->resize = [
161            'width'  => (int)round($width),
162            'height' => (int)round($this->height * ($width / $this->width))
163        ];
164
165        $this->preserveResolution = $preserveResolution;
166        return $this;
167    }
168
169    /**
170     * Resize image to height
171     *
172     * @param  int|float $height
173     * @param  bool      $preserveResolution
174     * @return Image
175     */
176    public function resizeToHeight(int|float $height, bool $preserveResolution = false): Image
177    {
178        $this->resize = [
179            'width'  => (int)round($this->width * ($height / $this->height)),
180            'height' => (int)round($height)
181        ];
182
183        $this->preserveResolution = $preserveResolution;
184        return $this;
185    }
186
187    /**
188     * Resize image on whichever dimension is the greatest
189     *
190     * @param  int|float $pixel
191     * @param  bool      $preserveResolution
192     * @return Image
193     */
194    public function resize(int|float $pixel, bool $preserveResolution = false): Image
195    {
196        $scale        = ($this->width > $this->height) ? ($pixel / $this->width) : ($pixel / $this->height);
197        $this->resize = [
198            'width'  => (int)round($this->width * $scale),
199            'height' => (int)round($this->height * $scale)
200        ];
201
202        $this->preserveResolution = $preserveResolution;
203        return $this;
204    }
205
206    /**
207     * Scale image
208     *
209     * @param  float $scale
210     * @param  bool  $preserveResolution
211     * @return Image
212     */
213    public function scale(float $scale, bool $preserveResolution = false): Image
214    {
215        $this->resize = [
216            'width'  => (int)round($this->width * $scale),
217            'height' => (int)round($this->height * $scale)
218        ];
219        $this->preserveResolution = $preserveResolution;
220        return $this;
221    }
222
223    /**
224     * Is image file
225     *
226     * @return bool
227     */
228    public function isFile(): bool
229    {
230        return (($this->image !== null) && ($this->stream === null));
231    }
232
233    /**
234     * Is image stream
235     *
236     * @return bool
237     */
238    public function isStream(): bool
239    {
240        return (($this->stream !== null) && ($this->image === null));
241    }
242
243    /**
244     * Get the image file
245     *
246     * @return ?string
247     */
248    public function getImage(): ?string
249    {
250        return $this->image;
251    }
252
253    /**
254     * Get the image stream
255     *
256     * @return ?string
257     */
258    public function getStream(): ?string
259    {
260        return $this->stream;
261    }
262
263    /**
264     * Get the image width
265     *
266     * @return int|float|null
267     */
268    public function getWidth(): int|float|null
269    {
270        return $this->width;
271    }
272
273    /**
274     * Get the image height
275     *
276     * @return int|float|null
277     */
278    public function getHeight(): int|float|null
279    {
280        return $this->height;
281    }
282
283    /**
284     * Get the image resized width
285     *
286     * @return int|float|null
287     */
288    public function getResizedWidth(): int|float|null
289    {
290        return (($this->resize !== null) && isset($this->resize['width'])) ? $this->resize['width'] : null;
291    }
292
293    /**
294     * Get the image resized height
295     *
296     * @return int|float|null
297     */
298    public function getResizedHeight(): int|float|null
299    {
300        return (($this->resize !== null) && isset($this->resize['height'])) ? $this->resize['height'] : null;
301    }
302
303    /**
304     * Get the image resize dimensions
305     *
306     * @return ?array
307     */
308    public function getResizeDimensions(): ?array
309    {
310        return $this->resize;
311    }
312
313    /**
314     * Get the image preserve resolution flag
315     *
316     * @return bool
317     */
318    public function isPreserveResolution(): bool
319    {
320        return $this->preserveResolution;
321    }
322
323}