139 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php declare(strict_types=1);
 | 
						|
 | 
						|
namespace App\Captcha\Images;
 | 
						|
 | 
						|
use App\Captcha\Contracts\Image as ImageContract;
 | 
						|
use App\Captcha\Dto\Coordinators;
 | 
						|
use App\Captcha\Exceptions\CaptchaException;
 | 
						|
 | 
						|
final class Image implements ImageContract
 | 
						|
{
 | 
						|
    private readonly \GdImage $image;
 | 
						|
 | 
						|
    public function __construct(int $width, int $height) {
 | 
						|
        $this->image = imagecreatetruecolor($width, $height);
 | 
						|
    }
 | 
						|
 | 
						|
    public function getWidth(): int
 | 
						|
    {
 | 
						|
        return imagesx($this->image);
 | 
						|
    }
 | 
						|
 | 
						|
    public function getHeight(): int
 | 
						|
    {
 | 
						|
        return imagesy($this->image);
 | 
						|
    }
 | 
						|
 | 
						|
    public function insertBackground(string $pathToFile): ImageContract
 | 
						|
    {
 | 
						|
        list($backgroundWidth, $backgroundHeight) = getimagesize($pathToFile);
 | 
						|
        $background = $this->createImageFromPathToFile($pathToFile);
 | 
						|
        imagecopyresampled(
 | 
						|
            dst_image: $this->image,
 | 
						|
            src_image: $background,
 | 
						|
            dst_x: 0,
 | 
						|
            dst_y: 0,
 | 
						|
            src_x: 0,
 | 
						|
            src_y: 0,
 | 
						|
            dst_width: $this->getWidth(),
 | 
						|
            dst_height: $this->getHeight(),
 | 
						|
            src_width: $backgroundWidth,
 | 
						|
            src_height: $backgroundHeight
 | 
						|
        );
 | 
						|
        imagedestroy($background);
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    public function addText(string $text, int $x, int $y, float $size, float $angle, string $hexColor, string $fontName): Coordinators
 | 
						|
    {
 | 
						|
        $y += intval($size);
 | 
						|
        $result = imagefttext(
 | 
						|
            image: $this->image,
 | 
						|
            size: $size,
 | 
						|
            angle: $angle,
 | 
						|
            x: $x,
 | 
						|
            y: $y,
 | 
						|
            color: $this->colorConvertHexToColorIndex($hexColor),
 | 
						|
            font_filename: $fontName,
 | 
						|
            text: $text
 | 
						|
        );
 | 
						|
 | 
						|
        return new Coordinators(
 | 
						|
            x1: $result[0],
 | 
						|
            y1: $result[1],
 | 
						|
            x2: $result[2],
 | 
						|
            y2: $result[3],
 | 
						|
            x3: $result[4],
 | 
						|
            y3: $result[5],
 | 
						|
            x4: $result[6],
 | 
						|
            y4: $result[7]
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    public function addLine(int $x1, int $y1, int $x2, int $y2, string $hexColor): self
 | 
						|
    {
 | 
						|
        imageline(
 | 
						|
            image: $this->image,
 | 
						|
            x1: $x1,
 | 
						|
            y1: $y1,
 | 
						|
            x2: $x2,
 | 
						|
            y2: $y2,
 | 
						|
            color: $this->colorConvertHexToColorIndex($hexColor)
 | 
						|
        );
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    public function encode(): string
 | 
						|
    {
 | 
						|
        ob_start();
 | 
						|
        imagealphablending($this->image, false);
 | 
						|
        imagesavealpha($this->image, true);
 | 
						|
        imagepng($this->image, null, -1);
 | 
						|
        $mime = image_type_to_mime_type(IMAGETYPE_PNG);
 | 
						|
        $buffer = ob_get_contents();
 | 
						|
        ob_end_clean();
 | 
						|
 | 
						|
        return sprintf('data:%s;base64,%s',
 | 
						|
            $mime,
 | 
						|
            base64_encode($buffer)
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    public function __destruct() {
 | 
						|
        imagedestroy($this->image);
 | 
						|
    }
 | 
						|
 | 
						|
    private function createImageFromPathToFile(string $pathToFile): \GdImage
 | 
						|
    {
 | 
						|
        return match (mime_content_type($pathToFile)) {
 | 
						|
            'image/jpeg' => imagecreatefromjpeg($pathToFile),
 | 
						|
            'image/png'  => imagecreatefrompng($pathToFile),
 | 
						|
            default => throw new CaptchaException('Couldn\'t open the file. Not a valid type. File ' . $pathToFile . '.')
 | 
						|
        };
 | 
						|
    }
 | 
						|
 | 
						|
    private function colorConvertHexToColorIndex(string $hexColor): int
 | 
						|
    {
 | 
						|
        $hexColor = str_replace('#', '', $hexColor);
 | 
						|
 | 
						|
        if (strlen($hexColor) === 3) {
 | 
						|
            return imagecolorexact(
 | 
						|
                image: $this->image,
 | 
						|
                red: hexdec(str_repeat(substr($hexColor, 0, 1), 2)),
 | 
						|
                blue: hexdec(str_repeat(substr($hexColor, 1, 1), 2)),
 | 
						|
                green: hexdec(str_repeat(substr($hexColor, 2, 1), 2))
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        $colorVal = hexdec($hexColor);
 | 
						|
        return imagecolorexact(
 | 
						|
            image: $this->image,
 | 
						|
            red: 0xFF & ($colorVal >> 0x10),
 | 
						|
            blue: 0xFF & ($colorVal >> 0x8),
 | 
						|
            green: 0xFF & $colorVal
 | 
						|
        );
 | 
						|
    }
 | 
						|
}
 |