Просмотр файла delta_framework-main/core/lib/Core/Helpers/Thumbs.class.php

Размер файла: 36.19Kb
<?php
    /**
     * Copyright (c) 2022 Roman Grinko <[email protected]>
     * Permission is hereby granted, free of charge, to any person obtaining
     * a copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     */

    namespace Core\Helpers;

    use \Core\CoreException;

    class Thumbs
    {
        /** @var string $filename */
        private string $filename;

        /** @var int $width */
        private $width;

        /** @var int $height */
        private $height;

        /** @var int $type */
        private $type;

        /**
         * @var false|\GdImage|resource
         */
        private $img;

        public function __construct(string $filename)
        {
            $this->filename = $filename;
            if (empty($this->filename)) {
                throw new CoreException('Файл не найден');
            }

            $info = getimagesize($this->filename);
            if (empty($info)) {
                throw new CoreException('Файл не найден');
            }

            $this->width  = $info[0];
            $this->height = $info[1];
            $this->type   = $info[2];
            switch ($this->type) {
                case IMAGETYPE_GIF:
                    $this->img = imagecreatefromgif($this->filename);
                    break;
                case IMAGETYPE_JPEG:
                    $this->img = imagecreatefromjpeg($this->filename);
                    break;
                case IMAGETYPE_PNG:
                    $this->img = imagecreatefrompng($this->filename);
                    imagealphablending($this->img, true);
                    imagesavealpha($this->img, true);
                    break;
                case IMAGETYPE_WEBP:
                    $this->img = imagecreatefromwebp($this->filename);
                    break;
                default:
                    throw new CoreException('Формат файла не поддерживается');
                    break;
            }
        }

        public function fixWebpBlue()
        {
            $f_im = imagecreatetruecolor(imagesx($this->img), imagesy($this->img));
            $c    = imagecolorallocate($f_im, 255, 255, 255);
            imagefill($f_im, 0, 0, $c);

            for ($y = 0; $y < imagesy($this->img); $y++) {
                for ($x = 0; $x < imagesx($this->img); $x++) {
                    $rgb_old    = imagecolorat($this->img, $x, $y);
                    $r          = ($rgb_old >> 24) & 0xFF;
                    $g          = ($rgb_old >> 16) & 0xFF;
                    $b          = ($rgb_old >> 8) & 0xFF;
                    $pixelcolor = imagecolorallocate($f_im, $r, $g, $b);
                    imagesetpixel($f_im, $x, $y, $pixelcolor);
                }
            }
            $this->img = $f_im;
        }

        /**
         * Изминение размера изображения.
         */
        public function resize($width, $height)
        {
            if (empty($width)) {
                $width = ceil($height / ($this->height / $this->width));
            }
            if (empty($height)) {
                $height = ceil($width / ($this->width / $this->height));
            }

            $tmp = imageCreateTrueColor($width, $height);
            if ($this->type === IMAGETYPE_GIF || $this->type === IMAGETYPE_PNG) {
                imagealphablending($tmp, true);
                imageSaveAlpha($tmp, true);
                $transparent = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
                imagefill($tmp, 0, 0, $transparent);
                imagecolortransparent($tmp, $transparent);
            }

            if ($width < $this->width || $height < $this->height) {
                $tw = ceil($height / ($this->height / $this->width));
                if ($tw < $width) {
                    imageCopyResampled(
                        $tmp,
                        $this->img,
                        ceil(($width - $tw) / 2),
                        ceil(($height - $height) / 2),
                        0,
                        0,
                        $tw,
                        $height,
                        $this->width,
                        $this->height
                    );
                } else {
                    $th = ceil($width / ($this->width / $this->height));
                    imageCopyResampled(
                        $tmp,
                        $this->img,
                        ceil(($width - $width) / 2),
                        ceil(($height - $th) / 2),
                        0,
                        0,
                        $width,
                        $th,
                        $this->width,
                        $this->height
                    );
                }
            } else {
                imageCopyResampled($tmp, $this->img, 0, 0, 0, 0, $width, $height, $this->width, $this->height);
            }

            $this->img = $tmp;
            unset($tmp);

            $this->width  = $width;
            $this->height = $height;
        }

        /**
         * Уменьшить изображение, ели оно больше указанных размеров.
         */
        public function reduce($max_width, $max_height)
        {
            if (empty($max_width) && empty($max_height)) {
                throw new CoreException('Не указан размер изображения');
            } elseif (empty($max_width)) {
                $max_width = ceil($max_height / ($this->height / $this->width));
            } elseif (empty($max_height)) {
                $max_height = ceil($max_width / ($this->width / $this->height));
            }

            if ($this->width > $max_width || $this->height > $max_height) {
                $width  = ceil($max_height / ($this->height / $this->width));
                $height = ceil($max_width / ($this->width / $this->height));

                if ($width > $max_width) {
                    $width = $max_width;
                } else {
                    $height = $max_height;
                }

                return $this->resize($width, $height);
            }
        }

        /**
         * Изменение размера холста
         */
        public function resizeCanvas($width, $height, $bg = [])
        {
            if (empty($width)) {
                $width = ceil($height / ($this->height / $this->width));
            }
            if (empty($height)) {
                $height = ceil($width / ($this->width / $this->height));
            }

            $tw = ceil($height / ($this->height / $this->width));
            $th = ceil($width / ($this->width / $this->height));

            $tmp = imageCreateTrueColor($width, $height);

            if (!empty($bg)) {
                $bgc = imagecolorallocate($tmp, $bg[0], $bg[1], $bg[2]);
                imagefilledrectangle($tmp, 0, 0, $width, $height, $bgc);
            } else {
                imagealphablending($tmp, true);
                imageSaveAlpha($tmp, true);
                $transparent = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
                imagefill($tmp, 0, 0, $transparent);
                imagecolortransparent($tmp, $transparent);
            }

            if ($width >= $this->width && $height >= $this->height) {
                $seze = [ceil(($width - $this->width) / 2), ceil(($height - $this->height) / 2), $this->width, $this->height];
            } elseif ($width >= $this->width) {
                $seze = [ceil(($width - $tw) / 2), 0, ceil($height / ($this->height / $this->width)), $height];
            } elseif ($height >= $this->height) {
                $seze = [0, ceil(($height - $th) / 2), $width, ceil($width / ($this->width / $this->height))];
            } elseif ($tw < $width) {
                $seze = [ceil(($width - $tw) / 2), ceil(($height - $height) / 2), $tw, $height];
            } else {
                $seze = [0, ceil(($height - $th) / 2), $width, $th];
            }

            imageCopyResampled($tmp, $this->img, $seze[0], $seze[1], 0, 0, $seze[2], $seze[3], $this->width, $this->height);
            $this->img = $tmp;
            unset($tmp);

            $this->width  = $width;
            $this->height = $height;
        }

        /**
         * Вырезать часть изображения
         */
        public function crop($x, $y, $width, $height)
        {
            if (empty($height)) {
                $height = $width;
            }
            if (empty($width)) {
                $width = $height;
            }

            $tmp = imageCreateTrueColor($width, $height);
            if ($this->type === IMAGETYPE_GIF || $this->type === IMAGETYPE_PNG) {
                imagealphablending($tmp, true);
                imageSaveAlpha($tmp, true);
                $transparent = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
                imagefill($tmp, 0, 0, $transparent);
                imagecolortransparent($tmp, $transparent);
            }

            imageCopyResampled($tmp, $this->img, 0, 0, $x, $y, $this->width, $this->height, $this->width, $this->height);

            $this->img = $tmp;
            unset($tmp);

            $this->width  = $width;
            $this->height = $height;
        }

        /**
         * Получение основной части изображения.
         */
        public function cut($width, $height)
        {
            if (empty($width)) {
                $width = ceil($height / ($this->height / $this->width));
            }
            if (empty($height)) {
                $height = ceil($width / ($this->width / $this->height));
            }

            if ($this->width != $width && $this->height != $height) {
                $tw = ceil($height / ($this->height / $this->width));
                $th = ceil($width / ($this->width / $this->height));

                if ($this->width === $this->height) {
                    // Источник - квадратная фотка
                    if ($width === $height) {
                        // Превью - квадратная.
                        $this->resize($width, $height);
                    } elseif ($width > $height) {
                        // Превью - горизонтальная.
                        $this->resize($width, $width);
                        $this->crop(0, ceil(($this->height - $height) / 2), $width, $height);
                    } else {
                        // Превью - вертикальная.
                        $this->resize($height, $height);
                        $this->crop(ceil(($this->width - $width) / 2), 0, $width, $height);
                    }
                } elseif ($this->width > $this->height) {
                    // Источник - горизонтальная фотка
                    if ($width == $height) {
                        // Превью - квадратная.
                        $this->resize(0, $height);
                        $this->crop(ceil(($this->width - $width) / 2), 0, $width, $height);
                    } elseif ($width > $height) {
                        // Превью - горизонтальная.
                        if ($width <= $tw) {
                            $this->resize(0, $height);
                            $this->crop(ceil(($this->width - $width) / 2), 0, $width, $height);
                        } else {
                            $this->resize($width + 1, 0);
                            $this->crop(0, ceil(($this->height - $height) / 2), $width, $height);
                        }
                    } else {
                        // Превью - вертикальная.
                        $this->resize(0, $height);
                        $this->crop(ceil(($this->width - $width) / 2), 0, $width, $height);
                    }
                } else {
                    // Источник - вертикальная фотка
                    if ($width == $height) {
                        // Превью - квадратная.
                        $this->resize($width, 0);
                        $this->crop((ceil($this->width - $width) / 2), ceil((($this->height - $height) / 2) / 2), $width, $height);
                    } elseif ($width > $height) {
                        // Превью - горизонтальная.
                        $this->resize($width, 0);
                        $this->crop(0, ceil((($this->height - $height) / 2) / 3), $width, $height);
                    } else {
                        // Превью - вертикальная.
                        if ($tw > $width) {
                            $this->resize(0, $height);
                            $this->crop(ceil(($this->width - $width) / 2), 0, $width, $height);
                        } else {
                            $this->resize(0, $th);
                            $this->crop(ceil(($this->width - $width) / 2), 0, $width, $height);
                        }
                    }
                }

                $this->width  = $width;
                $this->height = $height;
            }

            return true;
        }

        /**
         * Превью.
         */
        public function thumb($width, $height)
        {
            if (empty($width)) {
                $width = ceil($height / ($this->height / $this->width));
            }
            if (empty($height)) {
                $height = ceil($width / ($this->width / $this->height));
            }

            $tw = ceil($height / ($this->height / $this->width));
            $th = ceil($width / ($this->width / $this->height));

            if ($this->width !== $width && $this->height !== $height) {
                $tmp = imageCreateTrueColor($width, $height);
                if ($this->type === IMAGETYPE_GIF || $this->type === IMAGETYPE_PNG) {
                    imagealphablending($tmp, true);
                    imageSaveAlpha($tmp, true);
                    $transparent = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
                    imagefill($tmp, 0, 0, $transparent);
                    imagecolortransparent($tmp, $transparent);
                }

                // Определение цвета фона...
                $entry_1 = $entry_2 = [];
                for ($n = 0; $n < $this->width; $n++) {
                    $color           = imagecolorat($this->img, $n, 0);
                    $entry_1[$color] = (isset($entry_1[$color])) ? $entry_1[$color] + 1 : 1;

                    $color           = imagecolorat($this->img, $n, $this->height - 1);
                    $entry_2[$color] = (isset($entry_2[$color])) ? $entry_2[$color] + 1 : 1;
                }

                arsort($entry_1);
                $top_color   = key($entry_1);
                $top_defined = (100 * $entry_1[$top_color] / $this->width) > 45;

                arsort($entry_2);
                $bottom_color   = key($entry_2);
                $bottom_defined = (100 * $entry_2[$bottom_color] / $this->width) > 45;
                unset($entry_1, $entry_2);

                for ($n = 0; $n < $this->height; $n++) {
                    $color           = imagecolorat($this->img, 0, $n);
                    $entry_1[$color] = (isset($entry_1[$color])) ? $entry_1[$color] + 1 : 1;

                    $color           = imagecolorat($this->img, $this->width - 1, $n);
                    $entry_2[$color] = (isset($entry_2[$color])) ? $entry_2[$color] + 1 : 1;
                }

                arsort($entry_1);
                $left_color   = key($entry_1);
                $left_defined = (100 * $entry_1[$left_color] / $this->height) > 45;

                arsort($entry_2);
                $right_color   = key($entry_2);
                $right_defined = (100 * $entry_2[$right_color] / $this->height) > 45;
                unset($entry_1, $entry_2);

                if ($top_defined || $bottom_defined || $right_defined || $left_defined) {
                    if (imageistruecolor($this->img)) {
                        $top_rgb    = imagecolorsforindex($tmp, $top_color);
                        $right_rgb  = imagecolorsforindex($tmp, $right_color);
                        $bottom_rgb = imagecolorsforindex($tmp, $bottom_color);
                        $left_rgb   = imagecolorsforindex($tmp, $left_color);

                        if (!empty($top_rgb['alpha']) && !empty($top_rgb['alpha']) && !empty($top_rgb['alpha']) && !empty($top_rgb['alpha'])) {
                            $top_defined = $right_defined = $bottom_defined = $left_defined = true;
                        } elseif (empty($top_rgb['alpha']) || empty($top_rgb['alpha']) || empty($top_rgb['alpha']) || empty($top_rgb['alpha'])) {
                            if ($top_defined && $bottom_defined && $left_defined == false && $right_defined == false) {
                                if ($th < $height) {
                                    imagefilledrectangle($tmp, 0, 0, $width - 1, $height / 2, $top_color);
                                    imagefilledrectangle($tmp, 0, $height / 2, $width - 1, $height - 1, $bottom_color);
                                } else {
                                    return $this->cut($width, $height);
                                }
                            } elseif ($left_defined && $right_defined && $top_defined == false && $bottom_defined == false) {
                                if ($tw < $width) {
                                    imagefilledrectangle($tmp, 0, 0, $width / 2, $height - 1, $left_color);
                                    imagefilledrectangle($tmp, $width / 2, 0, $width - 1, $height - 1, $right_color);
                                } else {
                                    return $this->cut($width, $height);
                                }
                            } else {
                                if ($top_defined) {
                                    imagefill($tmp, 0, 0, $top_color);
                                } elseif ($right_defined) {
                                    imagefill($tmp, 0, 0, $right_color);
                                } elseif ($bottom_defined) {
                                    imagefill($tmp, 0, 0, $bottom_color);
                                } else {
                                    imagefill($tmp, 0, 0, $left_color);
                                }
                            }
                        }
                    }

                    if ($top_defined == false && $right_defined && $bottom_defined && $left_defined) {
                        // top
                        if ($width >= $this->width && $height >= $this->height) {
                            $seze = [ceil(($width - $this->width) / 2), 0, $this->width, $this->height];
                        } elseif ($width >= $this->width) {
                            $seze = [
                                ceil(($width - ($height / ($this->height / $this->width))) / 2),
                                0,
                                ceil($height / ($this->height / $this->width)),
                                $height,
                            ];
                        } elseif ($height >= $this->height) {
                            $seze = [0, 0, $width, ceil($width / ($this->width / $this->height))];
                        } elseif ($tw < $width) {
                            $seze = [ceil(($width - $tw) / 2), 0, $tw, $height];
                        } else {
                            $seze = [ceil(($width - $width) / 2), 0, $width, $th];
                        }
                    } elseif ($top_defined == false && $right_defined && $bottom_defined && $left_defined == false) {
                        // top-left
                        if ($width >= $this->width && $height >= $this->height) {
                            $seze = [0, 0, $this->width, $this->height];
                        } elseif ($width >= $this->width) {
                            $seze = [0, 0, ceil($height / ($this->height / $this->width)), $height];
                        } elseif ($height >= $this->height) {
                            $seze = [0, 0, $width, ceil($width / ($this->width / $this->height))];
                        } elseif ($tw < $width) {
                            $seze = [0, 0, $tw, $height];
                        } else {
                            $seze = [0, 0, $width, $th];
                        }
                    } elseif ($top_defined == false && $right_defined == false && $bottom_defined && $left_defined) {
                        // top-right
                        if ($width >= $this->width && $height >= $this->height) {
                            $seze = [$width - $this->width, 0, $this->width, $this->height];
                        } elseif ($width >= $this->width) {
                            $seze = [$width - $tw, 0, ceil($height / ($this->height / $this->width)), $height];
                        } elseif ($height >= $this->height) {
                            $seze = [0, 0, $width, ceil($width / ($this->width / $this->height))];
                        } elseif ($tw < $width) {
                            $seze = [$width - $tw, 0, $tw, $height];
                        } else {
                            $seze = [0, 0, $width, $th];
                        }
                    } elseif ($top_defined && $right_defined && $bottom_defined == false && $left_defined == false) {
                        // bottom-left
                        if ($width >= $this->width && $height >= $this->height) {
                            $seze = [0, $height - $this->height, $this->width, $this->height];
                        } elseif ($width >= $this->width) {
                            $seze = [0, 0, ceil($height / ($this->height / $this->width)), $height];
                        } elseif ($height >= $this->height) {
                            $seze = [0, $height - $th, $width, ceil($width / ($this->width / $this->height))];
                        } elseif ($tw < $width) {
                            $seze = [0, 0, $tw, $height];
                        } else {
                            $seze = [0, $height - $th, $width, $th];
                        }
                    } elseif ($top_defined && $right_defined == false && $bottom_defined == false && $left_defined) {
                        // bottom-right
                        if ($width >= $this->width && $height >= $this->height) {
                            $seze = [$width - $this->width, $height - $this->height, $this->width, $this->height];
                        } elseif ($width >= $this->width) {
                            $seze = [$width - $tw, 0, ceil($height / ($this->height / $this->width)), $height];
                        } elseif ($height >= $this->height) {
                            $seze = [0, $height - $th, $width, ceil($width / ($this->width / $this->height))];
                        } elseif ($tw < $width) {
                            $seze = [$width - $tw, 0, $tw, $height];
                        } else {
                            $seze = [$width - $tw, $height - $th, $width, $th];
                        }
                    } elseif ($top_defined && $right_defined == false && $bottom_defined && $left_defined
                              && ($top_color == $bottom_color
                                  && $bottom_color == $left_color)) {
                        // right
                        if ($width >= $this->width && $height >= $this->height) {
                            $seze = [$width - $this->width, ceil(($height - $this->height) / 2), $this->width, $this->height];
                        } elseif ($width >= $this->width) {
                            $seze = [$width - $tw, 0, ceil($height / ($this->height / $this->width)), $height];
                        } elseif ($height >= $this->height) {
                            $seze = [0, $height - $th, $width, ceil($width / ($this->width / $this->height))];
                        } elseif ($tw < $width) {
                            $seze = [$width - $tw, ceil(($height - $height) / 2), $tw, $height];
                        } else {
                            $seze = [0, ceil(($height - $th) / 2), $width, $th];
                        }
                    } elseif ($top_defined && $right_defined && $bottom_defined == false && $left_defined) {
                        // bottom
                        if ($width >= $this->width && $height >= $this->height) {
                            $seze = [ceil(($width - $this->width) / 2), $height - $this->height, $this->width, $this->height];
                        } elseif ($width >= $this->width) {
                            $seze = [
                                ceil(($width - ($height / ($this->height / $this->width))) / 2),
                                0,
                                ceil($height / ($this->height / $this->width)),
                                $height,
                            ];
                        } elseif ($height >= $this->height) {
                            $seze = [0, $height - $th, $width, ceil($width / ($this->width / $this->height))];
                        } elseif ($tw < $width) {
                            $seze = [ceil(($width - $tw) / 2), 0, $tw, $height];
                        } else {
                            $seze = [ceil(($width - $width) / 2), $height - $th, $width, $th];
                        }
                    } elseif ($top_defined && $right_defined && $bottom_defined && $left_defined == false) {
                        // left
                        if ($width >= $this->width && $height >= $this->height) {
                            $seze = [0, ceil(($height - $this->height) / 2), $this->width, $this->height];
                        } elseif ($width >= $this->width) {
                            $seze = [0, 0, ceil($height / ($this->height / $this->width)), $height];
                        } elseif ($height >= $this->height) {
                            $seze = [0, ceil(($height - $th) / 2), $width, ceil($width / ($this->width / $this->height))];
                        } elseif ($tw < $width) {
                            $seze = [0, ceil(($height - $height) / 2), $tw, $height];
                        } else {
                            $seze = [0, ceil(($height - $th) / 2), $width, $th];
                        }
                    } elseif (($top_defined && $bottom_defined) || ($right_defined && $left_defined)) {
                        // more
                        if ($width >= $this->width && $height >= $this->height) {
                            $seze = [ceil(($width - $this->width) / 2), ceil(($height - $this->height) / 2), $this->width, $this->height];
                        } elseif ($width >= $this->width) {
                            $seze = [ceil(($width - $tw) / 2), 0, ceil($height / ($this->height / $this->width)), $height];
                        } elseif ($height >= $this->height) {
                            $seze = [0, ceil(($height - $th) / 2), $width, ceil($width / ($this->width / $this->height))];
                        } elseif ($tw < $width) {
                            $seze = [ceil(($width - $tw) / 2), ceil(($height - $height) / 2), $tw, $height];
                        } else {
                            $seze = [0, ceil(($height - $th) / 2), $width, $th];
                        }
                    } else {
                        return $this->cut($width, $height);
                    }

                    imageCopyResampled($tmp, $this->img, $seze[0], $seze[1], 0, 0, $seze[2], $seze[3], $this->width, $this->height);
                    $this->img = $tmp;
                    unset($tmp);

                    return true;
                }

                return $this->cut($width, $height);
            }
        }

        /**
         * Поворот изображения
         */
        public function rotate($deg)
        {
            $this->img = imagerotate($this->img, $deg, 0);

            $width        = $this->width;
            $this->width  = $this->height;
            $this->height = $width;
        }

        /**
         * Поворот изображения по часовой стрелки.
         */
        public function rotateRight()
        {
            $this->rotate(-90);
        }

        /**
         * Поворот изображения против часовой стрелки.
         */
        public function rotateLeft()
        {
            $this->rotate(90);
        }

        public function opacity($image, $opacity)
        {
            $width  = imagesx($image);
            $height = imagesy($image);

            $tmp = imagecreatetruecolor($width, $height);
            imagealphablending($tmp, false);
            imagefill($tmp, 0, 0, imagecolortransparent($tmp));
            imagecopy($tmp, $image, 0, 0, 0, 0, $width, $height);

            for ($x = 0; $x < $width; ++$x) {
                for ($y = 0; $y < $height; ++$y) {
                    $pixelColor   = imagecolorat($tmp, $x, $y);
                    $pixelOpacity = 127 - (($pixelColor >> 24) & 0xFF);
                    if ($pixelOpacity > 0) {
                        $pixelOpacity = $pixelOpacity * $opacity;
                        $pixelColor   = ($pixelColor & 0xFFFFFF) | ((int)round(127 - $pixelOpacity) << 24);
                        imagesetpixel($tmp, $x, $y, $pixelColor);
                    }
                }
            }

            return $tmp;
        }

        public function watermark($file, $position = 'center', $transparency = 1)
        {
            if (empty($file)) {
                throw new CoreException('Файл маски не найден');
            }

            $info = getimagesize($file);
            if (empty($info)) {
                throw new CoreException('Файл маски не найден');
            }

            switch ($info[2]) {
                case IMAGETYPE_GIF:
                    $dest = imageCreateFromGif($file);
                    break;
                case IMAGETYPE_JPEG:
                    $dest = imageCreateFromJpeg($file);
                    break;
                case IMAGETYPE_PNG:
                    $dest        = imageCreateFromPng($file);
                    $transparent = imagecolorallocatealpha($dest, 0, 0, 0, 127);
                    imagefill($dest, 0, 0, $transparent);
                    imagecolortransparent($dest, $transparent);

                    imageAlphaBlending($dest, true);
                    imageSaveAlpha($dest, true);


                    break;
                case IMAGETYPE_WEBP:
                    $dest = imageCreatefromWebp($file);
                    break;
                default:
                    throw new CoreException('Формат файла маски не подерживается');
                    break;
            }

            switch ($position) {
                case 'top':
                    $x = ceil(($this->width - $info[0]) / 2);
                    $y = 0;
                    break;
                case 'top-left':
                    $x = 0;
                    $y = 0;
                    break;
                case 'top-right':
                    $x = ceil($this->width - $info[0]);
                    $y = 0;
                    break;
                case 'left':
                    $x = 0;
                    $y = ceil(($this->height - $info[1]) / 2);
                    break;
                case 'right':
                    $x = ceil($this->width - $info[0]);
                    $y = ceil(($this->height - $info[1]) / 2);
                    break;
                case 'bottom':
                    $x = ceil(($this->width - $info[0]) / 2);
                    $y = ceil($this->height - $info[1]);
                    break;
                case 'bottom-left':
                    $x = 0;
                    $y = ceil($this->height - $info[1]);
                    break;
                case 'bottom-right':
                    $x = ceil($this->width - $info[0]);
                    $y = ceil($this->height - $info[1]);
                    break;
                default:
                    $x = ceil(($this->width - $info[0]) / 2);
                    $y = ceil(($this->height - $info[1]) / 2);
                    break;
            }

            $dest = $this->opacity($dest, $transparency);
            imagecopy($this->img, $dest, $x, $y, 0, 0, $info[0], $info[1]);
        }

        /**
         * Сохраняет изображение в файл.
         */
        public function saveJPG($filename, $quality = 100)
        {
            return imageJpeg($this->img, $filename, $quality);
        }

        public function savePNG($filename)
        {
            if (empty($filename)) {
                $filename = $this->filename;
            }

            return imagePng($this->img, $filename);
        }

        public function saveGIF($filename)
        {
            return imageGif($this->img, $filename);
        }

        public function saveWEBP($filename, $quality = 100)
        {
            return imageWebp($this->img, $filename, $quality);
        }

        public function save($filename = '', $quality = 100)
        {
            if (empty($filename)) {
                $filename = $this->filename;
            }

            switch ($this->type) {
                case IMAGETYPE_GIF:
                    return $this->saveGif($filename);
                case IMAGETYPE_JPEG:
                    return $this->saveJpg($filename, $quality);
                case IMAGETYPE_PNG:
                    return $this->savePng($filename);
                case IMAGETYPE_WEBP:
                    return $this->saveWebp($filename);
            }
        }

        /**
         * Выводит изображение в браузер.
         */
        public function output($quality = 100): void
        {
            switch ($this->type) {
                case IMAGETYPE_GIF:
                    header('Content-Type: image/gif');
                    imageGif($this->img);
                    break;
                case IMAGETYPE_JPEG:
                    header('Content-Type: image/jpeg');
                    imageJpeg($this->img, null, $quality);
                    break;
                case IMAGETYPE_PNG:
                    header('Content-Type: image/x-png');
                    imagePng($this->img);
                    break;
                case IMAGETYPE_WEBP:
                    header('Content-Type: image/webp');
                    imageWebp($this->img, $quality);
                    break;
            }
        }

        /**
         * Выводит изображение в браузер и Сохраняет его.
         */
        public function saveOut($filename, $quality = 100): void
        {
            if (empty($filename)) {
                $filename = $this->filename;
            }

            switch ($this->type) {
                case IMAGETYPE_GIF:
                    header('Content-Type: image/gif');
                    imageGif($this->img, $filename);
                    break;
                case IMAGETYPE_JPEG:
                    header('Content-Type: image/jpeg');
                    imageJpeg($this->img, $filename, $quality);
                    break;
                case IMAGETYPE_PNG:
                    header('Content-Type: image/x-png');
                    imagePng($this->img, $filename);
                    break;
            }

            header('Content-Length: ' . filesize($filename));
            readfile($filename);
        }

        public function destroy(): void
        {
            imagedestroy($this->img);
        }
    }