用PHP从文本、字体和另一个图像中创建一个图像的例子

62 阅读1分钟

如果你想从文本、字体和另一个图像中创建一个图像,你可以按照下面的例子。

结构

image$ tree
.
├── background.jpg
├── background.png
├── create.php
├── Montserrat-Bold.ttf
├── Montserrat-Regular.ttf
└── Montserrat-SemiBold.ttf
class Image
{
    private const FONT_BOLD = '/srv/www/image/Montserrat-Bold.ttf';
    private const FONT_SEMI_BOLD = '/srv/www/image/Montserrat-SemiBold.ttf';
    private const FONT_REGULAR = '/srv/www/image/Montserrat-Regular.ttf';
    private const IMAGE_WIDTH = 854;
    private const IMAGE_HEIGHT = 480;
    private const CLIENT_NAME_LIMIT = 34;
    private const SERVICE_PROPERTIES_LIMIT = 4;

    private $validImageTypes = ['jpg', 'png'];
    private $imageType;
    private $clientName;
    private $clientPhone;
    private $serviceType;
    private $servicePrice;
    private $serviceAddress;
    private $serviceDate;
    private $serviceReference;
    private $serviceProperties;

    public function setImageType(string $imageType): self
    {
        if (!in_array($imageType, $this->validImageTypes)) {
            throw new Exception(sprintf('Invalid image type "%s".', $imageType));
        }

        $this->imageType = $imageType;

        return $this;
    }

    public function setClientName(string $clientName): self
    {
        $clientName = mb_strtoupper($clientName);
        if (strlen($clientName) > self::CLIENT_NAME_LIMIT) {
            $clientName = substr($clientName, 0, self::CLIENT_NAME_LIMIT).' ...';
        }

        $this->clientName = $clientName;

        return $this;
    }

    public function setClientPhone(string $clientPhone): self
    {
        $this->clientPhone = $clientPhone;

        return $this;
    }

    public function setClientType(string $serviceType): self
    {
        $this->serviceType = mb_strtoupper($serviceType);

        return $this;
    }

    public function setServicePrice(string $servicePrice): self
    {
        $this->servicePrice = $servicePrice;

        return $this;
    }

    public function setServiceAddress(string $serviceAddress): self
    {
        $this->serviceAddress = $serviceAddress;

        return $this;
    }

    public function setServiceDate(string $serviceDate): self
    {
        $this->serviceDate = $serviceDate;

        return $this;
    }

    public function setServiceReference(string $serviceReference): self
    {
        $this->serviceReference = $serviceReference;

        return $this;
    }

    public function setServiceProperties(iterable $serviceProperties): self
    {
        $this->serviceProperties = array_slice(array_filter($serviceProperties), 0, self::SERVICE_PROPERTIES_LIMIT);

        return $this;
    }

    public function create(): void
    {
        // Create image from existing file
        $image = ($this->imageType === 'jpg')
            ? imagecreatefromjpeg('/srv/www/image/background.jpg')
            : imagecreatefrompng('/srv/www/image/background.png');

        // Create text colours
        $white = imagecolorallocate($image, 255, 255, 255);
        $blue = imagecolorallocate($image, 51, 204, 255);

        // Draw top and bottom line
        imageline($image, 30, 74, 824, 74, $white);
        imageline($image, 30, 385, 824, 385, $white);

        // Write client name
        $this->writeText($image, 50, 24, $blue, self::FONT_BOLD, $this->clientName);

        // Write service type and price
        $text = sprintf('%s - %s', $this->serviceType, $this->servicePrice);
        $this->writeText($image, 124, 24, $white, self::FONT_SEMI_BOLD, $text);

        // Write service address and date
        $text = sprintf('%s - Written on %s', $this->serviceAddress, $this->serviceDate);
        $this->writeText($image, 165, 14, $white, self::FONT_SEMI_BOLD, $text);

        // Write service properties
        $y = 214;
        foreach ($this->serviceProperties as $text) {
            $this->writeText($image, $y, 14, $blue, self::FONT_SEMI_BOLD, $text);

            $y = $y + 30;
        }

        // Write client phone and service reference
        $text = sprintf('Phone: %s - Reference: %s', $this->clientPhone, $this->serviceReference);
        $this->writeText($image, 358, 14, $white, self::FONT_SEMI_BOLD, $text);

        // Save image
        ($this->imageType === 'jpg')
            ? imagejpeg($image, '/srv/www/image/image.jpg')
            : imagepng($image, '/srv/www/image/image.png');
    }

    private function writeText($image, int $y, int $fontSize, int $fontColour, string $fontPath, string $text): void
    {
        $x = $this->getXcoordinate($image, $fontSize, $fontPath, $text);

        imagettftext($image, $fontSize, 0, $x, $y, $fontColour, $fontPath, $text);
    }

    private function getXcoordinate($image, int $fontSize, string $fontPath, string $text): int
    {
        $dimensions = imagettfbbox($fontSize, 0, $fontPath, $text);
        $width = abs($dimensions[4] - $dimensions[0]);

        return round((imagesx($image) - $width) / 2);
    }
}

测试

$image = new Image();
$image
    ->setImageType('jpg')
    ->setClientName('Inanzzz')
    ->setClientPhone('012 3456 7890')
    ->setClientType('Blogger')
    ->setServicePrice('£1,000,000')
    ->setServiceAddress('Nice Street / London / England')
    ->setServiceDate('18/04/2018')
    ->setServiceReference('123ABC')
    ->setServiceProperties([
        'Keep It Simple, Stupid',
        'Open Source',
        'Multiple Languages',
        '',
        'R&D',
        'Will be ignored',
        '  '
    ])
    ->create();

如果你想把一个图像添加到另一个图像上,你可以使用下面的代码示例。

// Create image instances
$dest = imagecreatefromjpeg('/srv/www/image/main_image.jpg');
$src = imagecreatefromjpeg('/srv/www/image/logo.jpg');

// Copy and merge
imagecopymerge($dest, $src, 10, 10, 0, 0, 378, 144, 75);

imagejpeg($dest, '/srv/www/image/result.jpg');