1: | <?php
2: | /**
3: | * @package OpenCart
4: | *
5: | * @author Daniel Kerr
6: | * @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
7: | * @license https://opensource.org/licenses/GPL-3.0
8: | *
9: | * @see https://www.opencart.com
10: | */
11: | namespace Opencart\System\Library;
12: | /**
13: | * Class Image
14: | */
15: | class Image {
16: | /**
17: | * @var string
18: | */
19: | private string $file;
20: | /**
21: | * @var mixed
22: | */
23: | private $image;
24: | /**
25: | * @var int
26: | */
27: | private int $width;
28: | /**
29: | * @var int
30: | */
31: | private int $height;
32: | /**
33: | * @var string
34: | */
35: | private string $bits;
36: | /**
37: | * @var string
38: | */
39: | private string $mime;
40: |
41: | /**
42: | * Constructor
43: | *
44: | * @param string $file
45: | */
46: | public function __construct(string $file) {
47: | if (!extension_loaded('gd')) {
48: | exit('Error: PHP GD is not installed!');
49: | }
50: |
51: | if (is_file($file)) {
52: | $this->file = $file;
53: |
54: | $info = getimagesize($file);
55: |
56: | $this->width = $info[0];
57: | $this->height = $info[1];
58: | $this->bits = $info['bits'] ?? '';
59: | $this->mime = $info['mime'] ?? '';
60: |
61: | if ($this->mime == 'image/gif') {
62: | $this->image = imagecreatefromgif($file);
63: | } elseif ($this->mime == 'image/png') {
64: | $this->image = imagecreatefrompng($file);
65: |
66: | imageinterlace($this->image, false);
67: | } elseif ($this->mime == 'image/jpeg') {
68: | $this->image = imagecreatefromjpeg($file);
69: | } elseif ($this->mime == 'image/webp') {
70: | $this->image = imagecreatefromwebp($file);
71: | }
72: | } else {
73: | throw new \Exception('Error: Could not load image ' . $file . '!');
74: | }
75: | }
76: |
77: | /**
78: | * getFile
79: | *
80: | * @return string
81: | */
82: | public function getFile(): string {
83: | return $this->file;
84: | }
85: |
86: | /**
87: | * getImage
88: | *
89: | * @return mixed
90: | */
91: | public function getImage() {
92: | return $this->image ?: null;
93: | }
94: |
95: | /**
96: | * getWidth
97: | *
98: | * @return int
99: | */
100: | public function getWidth(): int {
101: | return $this->width;
102: | }
103: |
104: | /**
105: | * getHeight
106: | *
107: | * @return int
108: | */
109: | public function getHeight(): int {
110: | return $this->height;
111: | }
112: |
113: | /**
114: | * getBits
115: | *
116: | * @return string
117: | */
118: | public function getBits(): string {
119: | return $this->bits;
120: | }
121: |
122: | /**
123: | * getMime
124: | *
125: | * @return string
126: | */
127: | public function getMime(): string {
128: | return $this->mime;
129: | }
130: |
131: | /**
132: | * Save
133: | *
134: | * @param string $file
135: | * @param int $quality
136: | *
137: | * @return void
138: | */
139: | public function save(string $file, int $quality = 90): void {
140: | $info = pathinfo($file);
141: |
142: | $extension = strtolower($info['extension']);
143: |
144: | if (is_object($this->image) || is_resource($this->image)) {
145: | if ($extension == 'jpeg' || $extension == 'jpg') {
146: | imagejpeg($this->image, $file, $quality);
147: | } elseif ($extension == 'png') {
148: | imagepng($this->image, $file);
149: | } elseif ($extension == 'gif') {
150: | imagegif($this->image, $file);
151: | } elseif ($extension == 'webp') {
152: | imagewebp($this->image, $file);
153: | }
154: |
155: | imagedestroy($this->image);
156: | }
157: | }
158: |
159: | /**
160: | * Resize
161: | *
162: | * @param int $width
163: | * @param int $height
164: | * @param string $default
165: | *
166: | * @return void
167: | */
168: | public function resize(int $width = 0, int $height = 0, string $default = ''): void {
169: | if (!$this->width || !$this->height) {
170: | return;
171: | }
172: |
173: | $xpos = 0;
174: | $ypos = 0;
175: | $scale = 1;
176: |
177: | $scale_w = $width / $this->width;
178: | $scale_h = $height / $this->height;
179: |
180: | if ($default == 'w') {
181: | $scale = $scale_w;
182: | } elseif ($default == 'h') {
183: | $scale = $scale_h;
184: | } else {
185: | $scale = min($scale_w, $scale_h);
186: | }
187: |
188: | if ($scale == 1 && $scale_h == $scale_w && ($this->mime != 'image/png' && $this->mime != 'image/webp')) {
189: | return;
190: | }
191: |
192: | $new_width = (int)($this->width * $scale);
193: | $new_height = (int)($this->height * $scale);
194: | $xpos = (int)(($width - $new_width) / 2);
195: | $ypos = (int)(($height - $new_height) / 2);
196: |
197: | $image_old = $this->image;
198: | $this->image = imagecreatetruecolor($width, $height);
199: |
200: | if ($this->mime == 'image/png') {
201: | imagealphablending($this->image, false);
202: | imagesavealpha($this->image, true);
203: |
204: | $background = imagecolorallocatealpha($this->image, 255, 255, 255, 127);
205: |
206: | imagecolortransparent($this->image, $background);
207: | } elseif ($this->mime == 'image/webp') {
208: | imagealphablending($this->image, false);
209: | imagesavealpha($this->image, true);
210: |
211: | $background = imagecolorallocatealpha($this->image, 255, 255, 255, 127);
212: |
213: | imagecolortransparent($this->image, $background);
214: | } else {
215: | $background = imagecolorallocate($this->image, 255, 255, 255);
216: | }
217: |
218: | imagefilledrectangle($this->image, 0, 0, $width, $height, $background);
219: |
220: | imagecopyresampled($this->image, $image_old, $xpos, $ypos, 0, 0, $new_width, $new_height, $this->width, $this->height);
221: | imagedestroy($image_old);
222: |
223: | $this->width = $width;
224: | $this->height = $height;
225: | }
226: |
227: | /**
228: | * Watermark
229: | *
230: | * @param self $watermark
231: | * @param string $position
232: | *
233: | * @return void
234: | */
235: | public function watermark(self $watermark, string $position = 'bottomright'): void {
236: | switch ($position) {
237: | case 'topleft':
238: | $watermark_pos_x = 0;
239: | $watermark_pos_y = 0;
240: | break;
241: | case 'topcenter':
242: | $watermark_pos_x = (int)(($this->width - $watermark->getWidth()) / 2);
243: | $watermark_pos_y = 0;
244: | break;
245: | case 'topright':
246: | $watermark_pos_x = ($this->width - $watermark->getWidth());
247: | $watermark_pos_y = 0;
248: | break;
249: | case 'middleleft':
250: | $watermark_pos_x = 0;
251: | $watermark_pos_y = (int)(($this->height - $watermark->getHeight()) / 2);
252: | break;
253: | case 'middlecenter':
254: | $watermark_pos_x = (int)(($this->width - $watermark->getWidth()) / 2);
255: | $watermark_pos_y = (int)(($this->height - $watermark->getHeight()) / 2);
256: | break;
257: | case 'middleright':
258: | $watermark_pos_x = ($this->width - $watermark->getWidth());
259: | $watermark_pos_y = (int)(($this->height - $watermark->getHeight()) / 2);
260: | break;
261: | case 'bottomleft':
262: | $watermark_pos_x = 0;
263: | $watermark_pos_y = ($this->height - $watermark->getHeight());
264: | break;
265: | case 'bottomcenter':
266: | $watermark_pos_x = (int)(($this->width - $watermark->getWidth()) / 2);
267: | $watermark_pos_y = ($this->height - $watermark->getHeight());
268: | break;
269: | case 'bottomright':
270: | $watermark_pos_x = ($this->width - $watermark->getWidth());
271: | $watermark_pos_y = ($this->height - $watermark->getHeight());
272: | break;
273: | default:
274: | $watermark_pos_x = 0;
275: | $watermark_pos_y = 0;
276: | break;
277: | }
278: |
279: | imagealphablending($this->image, true);
280: | imagesavealpha($this->image, true);
281: | imagecopy($this->image, $watermark->getImage(), $watermark_pos_x, $watermark_pos_y, 0, 0, $watermark->getWidth(), $watermark->getHeight());
282: |
283: | imagedestroy($watermark->getImage());
284: | }
285: |
286: | /**
287: | * Crop
288: | *
289: | * @param int $top_x
290: | * @param int $top_y
291: | * @param int $bottom_x
292: | * @param int $bottom_y
293: | *
294: | * @return void
295: | */
296: | public function crop(int $top_x, int $top_y, int $bottom_x, int $bottom_y): void {
297: | $image_old = $this->image;
298: | $this->image = imagecreatetruecolor($bottom_x - $top_x, $bottom_y - $top_y);
299: |
300: | imagecopy($this->image, $image_old, 0, 0, $top_x, $top_y, $this->width, $this->height);
301: | imagedestroy($image_old);
302: |
303: | $this->width = $bottom_x - $top_x;
304: | $this->height = $bottom_y - $top_y;
305: | }
306: |
307: | /**
308: | * Rotate
309: | *
310: | * @param int $degree
311: | * @param string $color
312: | *
313: | * @return void
314: | */
315: | public function rotate(int $degree, string $color = 'FFFFFF'): void {
316: | $rgb = $this->html2rgb($color);
317: |
318: | $this->image = imagerotate($this->image, $degree, imagecolorallocate($this->image, $rgb[0], $rgb[1], $rgb[2]));
319: |
320: | $this->width = imagesx($this->image);
321: | $this->height = imagesy($this->image);
322: | }
323: |
324: | /**
325: | * Filter
326: | *
327: | * @return void
328: | */
329: | private function filter(): void {
330: | $args = func_get_args();
331: |
332: | imagefilter(...$args);
333: | }
334: |
335: | /**
336: | * Text
337: | *
338: | * @param string $text
339: | * @param int $x
340: | * @param int $y
341: | * @param int $size
342: | * @param string $color
343: | *
344: | * @return void
345: | */
346: | private function text(string $text, int $x = 0, int $y = 0, int $size = 5, string $color = '000000'): void {
347: | $rgb = $this->html2rgb($color);
348: |
349: | imagestring($this->image, $size, $x, $y, $text, imagecolorallocate($this->image, $rgb[0], $rgb[1], $rgb[2]));
350: | }
351: |
352: | /**
353: | * Merge
354: | *
355: | * @param self $merge
356: | * @param int $x
357: | * @param int $y
358: | * @param int $opacity
359: | *
360: | * @return void
361: | */
362: | private function merge(self $merge, int $x = 0, int $y = 0, int $opacity = 100): void {
363: | imagecopymerge($this->image, $merge->getImage(), $x, $y, 0, 0, $merge->getWidth(), $merge->getHeight(), $opacity);
364: | }
365: |
366: | /**
367: | * HTML2RGB
368: | *
369: | * @param string $color
370: | *
371: | * @return array<int, int>
372: | */
373: | private function html2rgb(string $color): array {
374: | if ($color[0] == '#') {
375: | $color = substr($color, 1);
376: | }
377: |
378: | if (strlen($color) == 6) {
379: | [
380: | $r,
381: | $g,
382: | $b
383: | ] = [
384: | $color[0] . $color[1],
385: | $color[2] . $color[3],
386: | $color[4] . $color[5]
387: | ];
388: | } elseif (strlen($color) == 3) {
389: | [
390: | $r,
391: | $g,
392: | $b
393: | ] = [
394: | $color[0] . $color[0],
395: | $color[1] . $color[1],
396: | $color[2] . $color[2]
397: | ];
398: | } else {
399: | return [];
400: | }
401: |
402: | $r = hexdec($r);
403: | $g = hexdec($g);
404: | $b = hexdec($b);
405: |
406: | return [
407: | $r,
408: | $g,
409: | $b
410: | ];
411: | }
412: | }
413: |

OpenCart API API documentation generated by ApiGen dev-master