1: | <?php
|
2: | |
3: | |
4: | |
5: | |
6: | |
7: | |
8: | |
9: | |
10: |
|
11: | namespace Opencart\System\Library;
|
12: | |
13: | |
14: |
|
15: | class Image {
|
16: | |
17: | |
18: |
|
19: | private string $file;
|
20: | |
21: | |
22: |
|
23: | private $image;
|
24: | |
25: | |
26: |
|
27: | private int $width;
|
28: | |
29: | |
30: |
|
31: | private int $height;
|
32: | |
33: | |
34: |
|
35: | private string $bits;
|
36: | |
37: | |
38: |
|
39: | private string $mime;
|
40: |
|
41: | |
42: | |
43: | |
44: | |
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: | |
79: | |
80: | |
81: |
|
82: | public function getFile(): string {
|
83: | return $this->file;
|
84: | }
|
85: |
|
86: | |
87: | |
88: | |
89: | |
90: |
|
91: | public function getImage() {
|
92: | return $this->image ?: null;
|
93: | }
|
94: |
|
95: | |
96: | |
97: | |
98: | |
99: |
|
100: | public function getWidth(): int {
|
101: | return $this->width;
|
102: | }
|
103: |
|
104: | |
105: | |
106: | |
107: | |
108: |
|
109: | public function getHeight(): int {
|
110: | return $this->height;
|
111: | }
|
112: |
|
113: | |
114: | |
115: | |
116: | |
117: |
|
118: | public function getBits(): string {
|
119: | return $this->bits;
|
120: | }
|
121: |
|
122: | |
123: | |
124: | |
125: | |
126: |
|
127: | public function getMime(): string {
|
128: | return $this->mime;
|
129: | }
|
130: |
|
131: | |
132: | |
133: | |
134: | |
135: | |
136: | |
137: | |
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: | |
161: | |
162: | |
163: | |
164: | |
165: | |
166: | |
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: | |
229: | |
230: | |
231: | |
232: | |
233: | |
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: | |
288: | |
289: | |
290: | |
291: | |
292: | |
293: | |
294: | |
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: | |
309: | |
310: | |
311: | |
312: | |
313: | |
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: | |
326: | |
327: | |
328: |
|
329: | private function filter(): void {
|
330: | $args = func_get_args();
|
331: |
|
332: | imagefilter(...$args);
|
333: | }
|
334: |
|
335: | |
336: | |
337: | |
338: | |
339: | |
340: | |
341: | |
342: | |
343: | |
344: | |
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: | |
354: | |
355: | |
356: | |
357: | |
358: | |
359: | |
360: | |
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: | |
368: | |
369: | |
370: | |
371: | |
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: | |