From f2ecdfcf97773f8016049abd7daa88a4fa174491 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Wed, 28 Jun 2023 17:22:19 +0600 Subject: [PATCH] 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. --- app/Captcha/Contracts/Image.php | 17 ++++ app/Captcha/Images/Image.php | 138 ++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 app/Captcha/Contracts/Image.php create mode 100644 app/Captcha/Images/Image.php diff --git a/app/Captcha/Contracts/Image.php b/app/Captcha/Contracts/Image.php new file mode 100644 index 0000000..15cb650 --- /dev/null +++ b/app/Captcha/Contracts/Image.php @@ -0,0 +1,17 @@ +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 + ); + } +}