This commit adds an Image interface and implementation that will be used in the Captcha generation process. The Image object includes methods for manipulating an image, such as adding text, inserting a background, and adding a line. These methods will provide the necessary functionalities for generating a Captcha.
This commit is contained in:
parent
f6669e93dc
commit
f2ecdfcf97
17
app/Captcha/Contracts/Image.php
Normal file
17
app/Captcha/Contracts/Image.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Captcha\Contracts;
|
||||
|
||||
use App\Captcha\Dto\Coordinators;
|
||||
|
||||
interface Image
|
||||
{
|
||||
public function __construct(int $width, int $height);
|
||||
public function getWidth(): int;
|
||||
public function getHeight(): int;
|
||||
public function insertBackground(string $pathToFile): self;
|
||||
public function addText(string $text, int $x, int $y, float $size, float $angle, string $hexColor, string $fontName): Coordinators;
|
||||
public function addLine(int $x1, int $y1, int $x2, int $y2, string $hexColor): self;
|
||||
public function encode(): string;
|
||||
public function __destruct();
|
||||
}
|
138
app/Captcha/Images/Image.php
Normal file
138
app/Captcha/Images/Image.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?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
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user