1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
Gd.php
См. документацию.
1<?php
8
9namespace Bitrix\Main\File\Image;
10
11use Bitrix\Main\File;
12
13class Gd extends Engine
14{
15 protected $resource;
16 protected $format;
17
21 public function load()
22 {
23 $this->clear();
24
25 $info = $this->getInfo();
26
27 if ($info && $info->isSupported())
28 {
29 $this->format = $info->getFormat();
30 $resource = null;
31
32 switch ($this->format)
33 {
34 case File\Image::FORMAT_GIF:
35 $resource = imagecreatefromgif($this->file);
36 break;
37 case File\Image::FORMAT_PNG:
38 $resource = imagecreatefrompng($this->file);
39 break;
40 case File\Image::FORMAT_WEBP:
41 $resource = imagecreatefromwebp($this->file);
42 break;
43 case File\Image::FORMAT_BMP:
44 $resource = imagecreatefrombmp($this->file);
45 break;
46 case File\Image::FORMAT_JPEG:
47 ini_set('gd.jpeg_ignore_warning', 1);
48 $resource = imagecreatefromjpeg($this->file);
49 break;
50 }
51
52 if ($resource)
53 {
54 $this->resource = $resource;
55 return true;
56 }
57 }
58 return false;
59 }
60
64 public function rotate($angle, Color $bgColor)
65 {
66 if ($this->resource === null)
67 {
68 return false;
69 }
70
71 $angle = 360 - $angle;
72 $alpha = (1.0 - $bgColor->getAlpha()) * 127;
73 $color = imagecolorallocatealpha($this->resource, $bgColor->getRed(), $bgColor->getGreen(), $bgColor->getBlue(), $alpha);
74
75 $resource = imagerotate($this->resource, $angle, $color);
76
77 if ($resource === false)
78 {
79 return false;
80 }
81
82 $this->clear();
83 $this->resource = $resource;
84
85 return true;
86 }
87
91 public function flipVertical()
92 {
93 if ($this->resource === null)
94 {
95 return false;
96 }
97
98 return imageflip($this->resource, IMG_FLIP_VERTICAL);
99 }
100
104 public function flipHorizontal()
105 {
106 if ($this->resource === null)
107 {
108 return false;
109 }
110
111 return imageflip($this->resource, IMG_FLIP_HORIZONTAL);
112 }
113
117 public function setOrientation($orientation)
118 {
119 // not implemented
120 return true;
121 }
122
126 public function resize(Rectangle $source, Rectangle $destination)
127 {
128 if ($this->resource === null)
129 {
130 return false;
131 }
132
133 $destinationWidth = $destination->getWidth();
134 $destinationHeight = $destination->getHeight();
135
136 if (($picture = imagecreatetruecolor($destinationWidth, $destinationHeight)))
137 {
138 $transparentColor = -1;
139
140 imagealphablending($picture, false);
141
142 if ($this->format == File\Image::FORMAT_PNG || $this->format == File\Image::FORMAT_WEBP)
143 {
144 $color = imagecolorallocatealpha($picture, 0, 0, 0, 127);
145 imagefilledrectangle($picture, 0, 0, $destinationWidth, $destinationHeight, $color);
146 }
147 elseif ($this->format == File\Image::FORMAT_GIF)
148 {
149 // save transparency
150 $transparentColor = $this->getTransparentColor();
151 if ($transparentColor >= 0)
152 {
153 $rgb = imagecolorsforindex($this->resource, $transparentColor);
154 $transparentColor = imagecolorallocatealpha($picture, $rgb['red'], $rgb['green'], $rgb['blue'], 127);
155 imagefilledrectangle($picture, 0, 0, $destinationWidth, $destinationHeight, $transparentColor);
156 }
157 }
158
159 if (imagecopyresampled($picture, $this->resource, 0, 0, $source->getX(), $source->getY(), $destinationWidth, $destinationHeight, $source->getWidth(), $source->getHeight()))
160 {
161 $this->clear();
162 $this->resource = $picture;
163
164 // restore transparency
165 if ($transparentColor >= 0)
166 {
167 $this->restoreTransparency($transparentColor);
168 }
169
170 return true;
171 }
172 }
173 return false;
174 }
175
179 public function blur(int $sigma): bool
180 {
181 if ($this->resource === null)
182 {
183 return false;
184 }
185
186 $sigma = max(1, min(100, round($sigma)));
187
188 $originalWidth = $this->getWidth();
189 $originalHeight = $this->getHeight();
190
191 $minScale = 0.5;
192 $smallestWidth = ceil($originalWidth * (1 - pow($minScale, 1.0 / $sigma)));
193 $smallestHeight = ceil($originalHeight * (1 - pow($minScale, 1.0 / $sigma)));
194
195 $prevImage = $this->resource;
196 $prevWidth = $originalWidth;
197 $prevHeight = $originalHeight;
198 $nextImage = $this->resource;
199 $nextWidth = 0;
200 $nextHeight = 0;
201
202 for ($i = 1; $i <= $sigma; $i += 1)
203 {
204 $denominator = (1 - pow($minScale, 1.0 / $i));
205 $nextWidth = (int)round($smallestWidth / $denominator);
206 $nextHeight = (int)round($smallestHeight / $denominator);
207 $nextImage = imagecreatetruecolor($nextWidth, $nextHeight);
208 if ($this->format == File\Image::FORMAT_PNG || $this->format == File\Image::FORMAT_WEBP)
209 {
210 imagealphablending($nextImage, false);
211 imagesavealpha($nextImage, true);
212 }
213
214 imagecopyresampled($nextImage, $prevImage, 0, 0, 0, 0, $nextWidth, $nextHeight, $prevWidth, $prevHeight);
215 imagefilter($nextImage, IMG_FILTER_GAUSSIAN_BLUR);
216 if ($prevImage !== $this->resource)
217 {
218 imagedestroy($prevImage);
219 }
220
221 $prevImage = $nextImage;
222 $prevWidth = $nextWidth;
223 $prevHeight = $nextHeight;
224 }
225
226 if ($this->format == File\Image::FORMAT_PNG || $this->format == File\Image::FORMAT_WEBP)
227 {
228 imagealphablending($this->resource, false);
229 imagesavealpha($this->resource, true);
230 }
231
232 imagecopyresampled($this->resource, $nextImage, 0, 0, 0, 0, $originalWidth, $originalHeight, $nextWidth, $nextHeight);
233 imagefilter($this->resource, IMG_FILTER_GAUSSIAN_BLUR);
234 if ($nextImage !== $this->resource)
235 {
236 imagedestroy($nextImage);
237 }
238
239 return true;
240 }
241
245 public function filter(Mask $mask)
246 {
247 if ($this->resource === null)
248 {
249 return false;
250 }
251
252 $transparentColor = -1;
253 if ($this->format == File\Image::FORMAT_GIF)
254 {
255 // Process transparency for GIFs
256 $transparentColor = $this->getTransparentColor();
257 }
258
259 // Fix left top corner
260 $newPixel = $this->calculatePixel($mask, 0, 0);
261
262 $result = imageconvolution($this->resource, $mask->getValue(), 1, 0);
263
264 if ($result)
265 {
266 // Fix left top corner
267 imagealphablending($this->resource, false);
268 imagesetpixel($this->resource, 0, 0, $newPixel);
269
270 // restore transparency
271 if ($transparentColor >= 0)
272 {
273 $this->restoreTransparency($transparentColor);
274 }
275 }
276 return $result;
277 }
278
279 protected function getTransparentColor(): int
280 {
281 $transparentColor = imagecolortransparent($this->resource);
282 if ($transparentColor < 0 || $transparentColor >= imagecolorstotal($this->resource))
283 {
284 return -1;
285 }
286 return $transparentColor;
287 }
288
289 protected function restoreTransparency($transparentColor)
290 {
291 imagecolortransparent($this->resource, $transparentColor);
292
293 $width = $this->getWidth();
294 $height = $this->getHeight();
295
296 for ($y = 0; $y < $height; ++$y)
297 {
298 for ($x = 0; $x < $width; ++$x)
299 {
300 if (((imagecolorat($this->resource, $x, $y) >> 24) & 0x7F) >= 100)
301 {
302 imagesetpixel($this->resource, $x, $y, $transparentColor);
303 }
304 }
305 }
306 }
307
314 protected function calculatePixel($mask, $x, $y)
315 {
316 $width = $this->getWidth();
317 $height = $this->getHeight();
318
319 $alpha = (imagecolorat($this->resource, $x, $y) >> 24) & 0xFF;
320 $newR = $newG = $newB = 0;
321
322 for ($j = 0; $j < 3; ++$j)
323 {
324 $yv = $y - 1 + $j;
325 if ($yv < 0)
326 {
327 $yv = 0;
328 }
329 elseif ($yv >= $height)
330 {
331 $yv = $height - 1;
332 }
333
334 for ($i = 0; $i < 3; ++$i)
335 {
336 $xv = $x - 1 + $i;
337 if ($xv < 0)
338 {
339 $xv = 0;
340 }
341 elseif ($xv >= $width)
342 {
343 $xv = $width - 1;
344 }
345
346 $m = $mask[$j][$i];
347 $rgb = imagecolorat($this->resource, $xv, $yv);
348
349 $newR += (($rgb >> 16) & 0xFF) * $m;
350 $newG += (($rgb >> 8) & 0xFF) * $m;
351 $newB += ($rgb & 0xFF) * $m;
352 }
353 }
354
355 $newR = ($newR > 255 ? 255 : ($newR < 0 ? 0 : $newR));
356 $newG = ($newG > 255 ? 255 : ($newG < 0 ? 0 : $newG));
357 $newB = ($newB > 255 ? 255 : ($newB < 0 ? 0 : $newB));
358
359 return imagecolorallocatealpha($this->resource, $newR, $newG, $newB, $alpha);
360 }
361
365 public function drawTextWatermark(TextWatermark $watermark)
366 {
367 if ($this->resource === null)
368 {
369 return false;
370 }
371
372 $font = $watermark->getFont();
373
374 if (!file_exists($font))
375 {
376 return false;
377 }
378
379 $utfText = $watermark->getUtfText();
380
381 $width = $this->getWidth();
382 $height = $this->getHeight();
383
384 if (($textWidth = $watermark->getWidth()) > 0)
385 {
386 $textBox = imagettfbbox(20, 0, $font, $utfText);
387 if (!is_array($textBox))
388 {
389 return false;
390 }
391
392 $scale = $textWidth / ($textBox[2] - $textBox[0]);
393 $fontSize = 20 * $scale;
394
395 $position = new Rectangle($textWidth, ($textBox[0] - $textBox[7]) * $scale);
396 }
397 else
398 {
399 $fontSize = $watermark->getFontSize($width);
400
401 $textBox = imagettfbbox($fontSize, 0, $font, $utfText);
402
403 $position = new Rectangle(($textBox[2] - $textBox[0]), ($textBox[0] - $textBox[7]));
404 }
405
406 $watermark->alignPosition($width, $height, $position);
407
408 $color = $watermark->getColor();
409 $textColor = imagecolorallocate($this->resource, $color->getRed(), $color->getGreen(), $color->getBlue());
410
412 {
413 // Try to take into consideration font's descenders.
414 // Coordinates in imagettftext are for font's *baseline*.
415 // Let the descenders be 20% of the font size.
416 $descender = $fontSize * 0.2;
417 $y = $position->getY() + $position->getHeight() - $descender; // baseline
418 }
419 else
420 {
421 $y = $position->getY() + $fontSize; // baseline
422 }
423
424 $result = imagettftext($this->resource, $fontSize, 0, $position->getX(), $y, $textColor, $font, $utfText);
425
426 return ($result !== false);
427 }
428
432 public function drawImageWatermark(ImageWatermark $watermark)
433 {
434 if ($this->resource === null)
435 {
436 return false;
437 }
438
439 if (($image = $this->loadWatermark($watermark)) === null)
440 {
441 return false;
442 }
443
444 $width = $this->getWidth();
445 $height = $this->getHeight();
446
447 $watermarkWidth = $image->getWidth();
448 $watermarkHeight = $image->getHeight();
449
450 $position = new Rectangle($watermarkWidth, $watermarkHeight);
451
452 $watermark->alignPosition($width, $height, $position);
453
454 $watermarkX = $position->getX();
455 $watermarkY = $position->getY();
456
457 $watermarkAlpha = $watermark->getAlpha();
458 $repeat = ($watermark->getMode() == ImageWatermark::MODE_REPEAT);
459
460 for ($y = 0; $y < $watermarkHeight; $y++)
461 {
462 for ($x = 0; $x < $watermarkWidth; $x++)
463 {
464 $posY = $watermarkY + $y;
465 while (true)
466 {
467 $posX = $watermarkX + $x;
468 while (true)
469 {
470 $alpha = $watermarkAlpha;
471
472 $mainRgb = imagecolorsforindex($this->resource, imagecolorat($this->resource, $posX, $posY));
473 $watermarkRgb = imagecolorsforindex($image->resource, imagecolorat($image->resource, $x, $y));
474
475 if ($watermarkRgb['alpha'] == 127)
476 {
477 $pixel = $mainRgb;
478 }
479 else
480 {
481 if ($watermarkRgb['alpha'])
482 {
483 $alpha = round((( 127 - $watermarkRgb['alpha']) / 127), 2);
484 $alpha = $alpha * $watermarkAlpha;
485 }
486
487 $pixel = [];
488 foreach (['red', 'green', 'blue', 'alpha'] as $k)
489 {
490 $pixel[$k] = round(($mainRgb[$k] * (1 - $alpha)) + ($watermarkRgb[$k] * $alpha));
491 }
492 }
493
494 $color = imagecolorexactalpha($this->resource, $pixel['red'], $pixel['green'], $pixel['blue'], $pixel['alpha']);
495 if ($color == -1)
496 {
497 $color = imagecolorallocatealpha($this->resource, $pixel['red'], $pixel['green'], $pixel['blue'], $pixel['alpha']);
498 if ($color === false)
499 {
500 $color = imagecolorclosestalpha($this->resource, $pixel['red'], $pixel['green'], $pixel['blue'], $pixel['alpha']);
501 }
502 }
503
504 imagesetpixel($this->resource, $posX, $posY, $color);
505
506 $posX += $watermarkWidth;
507
508 if (!$repeat || $posX > $width)
509 {
510 break;
511 }
512 }
513
514 $posY += $watermarkHeight;
515
516 if (!$repeat || $posY > $height)
517 {
518 break;
519 }
520 }
521 }
522 }
523
524 $image->clear();
525
526 return true;
527 }
528
532 public function save($file, $quality = 95, $format = null)
533 {
534 if ($this->resource === null)
535 {
536 return false;
537 }
538
539 if ($format === null)
540 {
542 }
543
544 $result = false;
545
546 switch ($format)
547 {
548 case File\Image::FORMAT_GIF:
549 $result = imagegif($this->resource, $file);
550 break;
551 case File\Image::FORMAT_PNG:
552 imagealphablending($this->resource, true);
553 imagesavealpha($this->resource, true);
554 $result = imagepng($this->resource, $file);
555 break;
556 case File\Image::FORMAT_WEBP:
557 imagealphablending($this->resource, true);
558 imagesavealpha($this->resource, true);
559 $result = imagewebp($this->resource, $file, $quality);
560 break;
561 case File\Image::FORMAT_BMP:
562 $result = imagebmp($this->resource, $file);
563 break;
564 case File\Image::FORMAT_JPEG:
565 $result = imagejpeg($this->resource, $file, $quality);
566 break;
567 }
568
569 return $result;
570 }
571
575 public function getWidth()
576 {
577 return imagesx($this->resource);
578 }
579
583 public function getHeight()
584 {
585 return imagesy($this->resource);
586 }
587
591 public function clear()
592 {
593 if ($this->resource !== null)
594 {
595 imagedestroy($this->resource);
596 $this->resource = null;
597 }
598 }
599
604 public function setResource($resource)
605 {
606 $this->resource = $resource;
607 }
608
612 public function getResource()
613 {
614 return $this->resource;
615 }
616}
getGreen()
Определения Color.php:97
getInfo($flashEnabled=false)
Определения Engine.php:57
loadWatermark(ImageWatermark $watermark)
Определения Engine.php:231
Определения Gd.php:14
blur(int $sigma)
Определения Gd.php:179
$format
Определения Gd.php:16
load()
Определения Gd.php:21
rotate($angle, Color $bgColor)
Определения Gd.php:64
flipVertical()
Определения Gd.php:91
setResource($resource)
Определения Gd.php:604
getTransparentColor()
Определения Gd.php:279
getResource()
Определения Gd.php:612
calculatePixel($mask, $x, $y)
Определения Gd.php:314
getHeight()
Определения Gd.php:583
drawTextWatermark(TextWatermark $watermark)
Определения Gd.php:365
clear()
Определения Gd.php:591
save($file, $quality=95, $format=null)
Определения Gd.php:532
$resource
Определения Gd.php:15
drawImageWatermark(ImageWatermark $watermark)
Определения Gd.php:432
filter(Mask $mask)
Определения Gd.php:245
setOrientation($orientation)
Определения Gd.php:117
getWidth()
Определения Gd.php:575
resize(Rectangle $source, Rectangle $destination)
Определения Gd.php:126
flipHorizontal()
Определения Gd.php:104
restoreTransparency($transparentColor)
Определения Gd.php:289
getValue()
Определения Mask.php:34
const ALIGN_BOTTOM
Определения Watermark.php:18
alignPosition($width, $height, Rectangle $position)
Определения Watermark.php:61
$result
Определения get_property_values.php:14
Определения action.php:3
Определения Image.php:9
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$originalHeight
Определения quickway.php:316
$originalWidth
Определения quickway.php:315
$textWidth
Определения template_pdf.php:80
$i
Определения factura.php:643
$width
Определения html.php:68
$fontSize
Определения pdf.php:30
$k
Определения template_pdf.php:567