service-captcha/app/Captcha/Images/Image.php

139 lines
3.9 KiB
PHP
Raw Normal View History

<?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
);
}
}