?
<?php
namespace App\Livewire;
use Livewire\Component;
use Livewire\Attributes\On;
use Illuminate\Support\Facades\Session;
class CaptchaComponent extends Component
{
public $captcha;
public $captchaImage;
public $mathCaptcha;
public $currentCaptchaType = 'image';
public function mount()
{
$this->toggleCaptchaType();
}
public function toggleCaptchaType()
{
$types = ['image', 'image'];
$this->currentCaptchaType = $types[array_rand($types)];
if ($this->currentCaptchaType === 'math') {
$this->generateMathCaptcha();
} else {
$this->generateImageCaptcha();
}
// $this->generateImageCaptcha();
$this->reset('captcha');
}
public function generateImageCaptcha()
{
$chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
$captchaText = substr(str_shuffle($chars), 0, 6);
session(['captcha_answer' => $captchaText]);
$width = 250;
$height = 80;
$image = imagecreatetruecolor($width, $height);
// Background color
$bgColor = imagecolorallocate($image, 255, 255, 255);
imagefilledrectangle($image, 0, 0, $width, $height, $bgColor);
// Add thick, wavy multi-colored lines
for ($i = 0; $i < 10; $i++) {
$lineColor = imagecolorallocate($image, rand(100, 200), rand(100, 200), rand(100, 200));
imagesetthickness($image, rand(3, 8));
$x1 = 0;
$y1 = rand(0, $height);
$x2 = $width;
$y2 = rand(0, $height);
$steps = 20;
for ($j = 0; $j < $steps; $j++) {
$cx1 = $x1 + ($x2 - $x1) * ($j / $steps);
$cy1 = $y1 + ($y2 - $y1) * ($j / $steps) + sin($j * M_PI / 5) * rand(5, 15);
$cx2 = $x1 + ($x2 - $x1) * (($j + 1) / $steps);
$cy2 = $y1 + ($y2 - $y1) * (($j + 1) / $steps) + sin(($j + 1) * M_PI / 5) * rand(5, 15);
imageline($image, $cx1, $cy1, $cx2, $cy2, $lineColor);
}
}
// Add octopus style semi-transparent clouded pebbles
for ($i = 0; $i < 10; $i++) {
$alpha = rand(60, 100);
$pebbleColor = imagecolorallocatealpha($image, rand(150, 250), rand(150, 250), rand(150, 250), $alpha);
$sizeX = rand(30, 80);
$sizeY = rand(30, 80);
$x = rand(0, $width);
$y = rand(0, $height);
imagefilledellipse($image, $x, $y, $sizeX, $sizeY, $pebbleColor);
imagefilter($image, IMG_FILTER_GAUSSIAN_BLUR);
}
// Add background noise dots with bigger grains
for ($i = 0; $i < 1000; $i++) {
$dotColor = imagecolorallocate($image, rand(150, 200), rand(150, 200), rand(150, 200));
imagesetthickness($image, rand(1, 3));
imagesetpixel($image, rand(0, $width), rand(0, $height), $dotColor);
}
// Place characters with controlled spacing and slight distortion
$font = public_path('fonts/arial.ttf');
$fontSize = 45;
$x = 10;
for ($i = 0; $i < strlen($captchaText); $i++) {
$letter = $captchaText[$i];
$angle = rand(-15, 15);
$y = rand($height / 2 + 5, $height - 15);
// Draw each character multiple times with a slight offset to create a grainy, translucent effect
for ($j = 0; $j < 15; $j++) {
$alpha = rand(40, 90);
$textColor = imagecolorallocatealpha($image, rand(50, 150), rand(50, 150), rand(50, 150), $alpha);
$offsetX = rand(-1, 1);
$offsetY = rand(-1, 1);
imagettftext($image, $fontSize, $angle, $x + $offsetX, $y + $offsetY, $textColor, $font, $letter);
}
// Adjust x for next character with controlled, intentional overlap
$bbox = imagettfbbox($fontSize, 0, $font, $letter);
$charWidth = abs($bbox[2] - $bbox[0]);
$x += $charWidth + rand(-10, -1); // This range creates consistent overlap
}
imagefilter($image, IMG_FILTER_SMOOTH, 5);
imagefilter($image, IMG_FILTER_GAUSSIAN_BLUR, 2);
ob_start();
imagepng($image);
$imageData = ob_get_clean();
imagedestroy($image);
$this->captchaImage = 'data:image/png;base64,' . base64_encode($imageData);
}
public function generateMathCaptcha()
{
$num1 = rand(1, 20);
$num2 = rand(1, 20);
$result = $num1 + $num2;
$this->mathCaptcha = "$num1 + $num2";
session(['captcha_answer' => $result]);
}
public function render()
{
return view('livewire.captcha-component');
}
}