Добавление водяного знака на изображение в PHP 8
 
			Доброго времени суток! В примере ниже мы рассмотрим с Вами как можно добавить водяной знак на изображение в PHP. В примере будем использовать библиотеку GD, поэтому она должна быть у Вас установлена. Также в примере будем использовать версию PHP 8.1.
Класс Image - обертка над GdImage
<?php
declare(strict_types=1);
class Image
{
    private string $filename;
    private GdImage $image;
    private int $width;
    private int $height;
    private int $bits;
    private string $mimeType;
    /**
     * @throws Exception
     */
    public function __construct(string $filename)
    {
        // если расширение не загружено - бросаем исключение
        if (!extension_loaded('gd')) {
            throw new Exception('GD extension is not loaded');
        }
        if (file_exists($filename)) {
            $this->filename = $filename;
            $fileInfo = getImageSize($filename);
            if(!$fileInfo) {
                throw new Exception("Image file corrupted: $filename"); 
            }
            $this->width  = $fileInfo[0];
            $this->height = $fileInfo[1];
            $this->bits = $fileInfo['bits'] ?? '';
            $this->mimeType = $fileInfo['mime'] ?? '';
            // выражение match, добавленное в PHP 8, выполняет функции switch
            // создаем изображение из файла заданного формата
            $this->image = match ($this->mimeType) {
                'image/gif' => imageCreateFromGif($filename),
                'image/png' => imageCreateFromPng($filename),
                'image/jpeg' => imageCreateFromJpeg($filename),
                default => throw new Exception("Unrecognized image type: $filename"),
            };
        } else {
            throw new Exception("Could not load image $filename");
        }
    }
    public function getFile(): string
    {
        return $this->filename;
    }
    public function getImage(): GdImage
    {
        return $this->image;
    }
    public function getResource(): GdImage
    {
        return $this->image;
    }
    public function cleanResource(): void
    {
        imageDestroy($this->image);
    }
    public function getWidth(): int
    {
        return $this->width;
    }
    public function getHeight(): int
    {
        return $this->height;
    }
    public function getBits(): int
    {
        return $this->bits;
    }
    public function getMime(): string
    {
        return $this->mime;
    }
    public function __toString(): string
    {
        return "[Object Image({$this->getFile()}@{$this->getWidth()}x{$this->getHeight()})]";
    }
}
Класс ImageProcessor - принимает класс Image и ставит на нем водяной знак
<?php
declare(strict_types=1);
class ImageProcessor
{
    private Image $image;
    public function __construct(Image $image)
    {
        $this->image = $image;
    }
    /**
     * Сохраняет изображение в файл 
     * 
     * @throws Exception
     */
    public function save(string $file, int $quality = 90): bool
    {
        $isSaveSuccessfully = false;
        $info = pathinfo($file);
        $extension = strtolower($info['extension']);
        //print($extension);
        $image = $this->image->getResource();
        $is_resource = is_resource($image);
        $isSaveSuccessfully = match ($extension) {
            'jpeg', 'jpg' => imageJpeg($image, $file, $quality),
            'png' => imagePng($image, $file),
            'gif' => imageGif($image, $file),
            default => throw new Exception("Unrecognized output image format: $extension"),
        };
        imageDestroy($image);
        return $isSaveSuccessfully;
    }
    /**
     * Возвращает массив из двух точек - положение водяного знака на исходном изображении 
     * 
     * @param Image $watermark
     * @param WatermarkPosition $position
     * @return array<int, int>
     */
    private function getIntPosition(Image $watermark, WatermarkPosition $position): array
    {
        return match ($position) {
            WatermarkPosition::TopLeft => [0, 0],
            WatermarkPosition::TopCenter => [
                ($this->image->getWidth() - $watermark->getWidth()) / 2,
                0
            ],
            WatermarkPosition::TopRight => [
                $this->image->getWidth() - $watermark->getWidth(),
                0
            ],
            WatermarkPosition::MiddleLeft => [
                0,
                ($this->image->getHeight()->$watermark->getHeight()) / 2
            ],
            WatermarkPosition::MiddleCenter => [
                ($this->image->getWidth() - $watermark->getWidth()) / 2,
                ($this->image->getHeight() - $watermark->getHeight()) / 2
            ],
            WatermarkPosition::MiddleRight => [
                $this->image->getWidth() - $watermark->getWidth(),
                ($this->image->getHeight() - $watermark->getHeight()) / 2
            ],
            WatermarkPosition::BottomLeft => [
                0,
                $this->image->getHeight() - $watermark->getHeight()
            ],
            WatermarkPosition::BottomCenter => [
                ($this->image->getWidth() - $watermark->getWidth()) / 2,
                $this->image->getHeight() - $watermark->getHeight()
            ],
            WatermarkPosition::BottomRight => [
                $this->image->getWidth() - $watermark->getWidth(),
                $this->image->getHeight() - $watermark->getHeight()
            ]
        };
    }
    /**
     * Добавляет водяной знак на изображение с помощью функций библиотеки GD 
     * 
     * @param Image $watermark
     * @param WatermarkPosition $position
     * @return void
     * 
     */
    public function addWatermark(Image $watermark, WatermarkPosition $position = WatermarkPosition::BottomRight): void
    {
        [$watermarkX, $watermarkY] = $this->getIntPosition($watermark, $position);
        $image = $this->image->getResource();
        ImageAlphaBlending($image, true);
        ImageSaveAlpha($image, true);
        ImageCopy($image, $watermark->getImage(), intval($watermarkX), intval($watermarkY), 0, 0, $watermark->getWidth(), $watermark->getHeight());
        ImageDestroy($watermark->getImage());
        $this->image->setGdImage($image);
    }
}
Перечисление WatermarkPosition - описывает положения для водяного знака на исходном изображении
<?php
enum WatermarkPosition
{
    case TopLeft;
    case TopCenter;
    case TopRight;
    case MiddleLeft;
    case MiddleCenter;
    case MiddleRight;
    case BottomLeft;
    case BottomCenter;
    case BottomRight;
}
watermark.php - пример использования
<?php
spl_autoload_register(fn($class) => require_once __DIR__ . "/lib/$class.php");
$image1 = 'images/base_image.png';
$image2 = 'images/watermark.png';
try {
    $baseImage = new Image($image1);
    $watermarkImage = new Image($image2);
    $imageProcessor = new ImageProcessor($baseImage);
    $imageProcessor->addWatermark($watermarkImage, WatermarkPosition::BottomLeft);
    $current_time = time();
    $imageProcessor->save("./image_with_watermark_$current_time.jpg");
} catch (Exception $e) {
    print($e->getMessage());
}
Таким образом, с помощью PHP библиотеки GD можно ставить водяные знаки на изображении и не только!
- 
					Создано 12.05.2022 08:06:13  
- 
					 Михаил Русаков Михаил Русаков
 
			 
			 
		 
				 
			 
				 
				 
				 
				
Комментарии (1):
Отличная статья
Ответить
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.