= $aWidth || $aY < 0 || $aY >= $aHeight) { return $defaultColor; } else { $pos = imagecolorat($aIm,$aX,$aY); $color = imagecolorsforindex($aIm, $pos); return $color; } } /** * Applies a (gaussian) matrix at a given point in the image. * @param resource The image. * @param int x-location of the point. * @param int y-location of the point. * @param array The (gaussian) matrix. * @param int The sum of all weights in the matrix. * @param array The default (background) color of the image. * @return array Rgb value of point after gaussian filter application. */ function getGaussianAt($aIm,$aX,$aY,$aMatrix,$aSum,$defaultColor) { $aRed = 0; $aGreen = 0; $aBlue = 0; $aCount = (count($aMatrix)-1)/2; for ($i=-$aCount;$i<=$aCount;$i++) { for ($j=-$aCount;$j<=$aCount;$j++) { $aRGB = getColorAt($aIm,$aX+$i,$aY+$j,$defaultColor); $aRed += $aRGB["red"]*$aMatrix[$i+$aCount][$j+$aCount]; $aGreen += $aRGB["green"]*$aMatrix[$i+$aCount][$j+$aCount]; $aBlue += $aRGB["blue"]*$aMatrix[$i+$aCount][$j+$aCount]; } } $aRed = round($aRed/$aSum); $aGreen = round($aGreen/$aSum); $aBlue = round($aBlue/$aSum); $bRGB = array("red"=>$aRed,"green"=>$aGreen,"blue"=>$aBlue); return $bRGB; } /** * Makes the basic image, putting the letters on the background. * @param resource The image. * @param int The left and right border. * @param int The top and bottom border. * @param int The distance between two letters. * @param int The string to write. * @param int The directory containing the letter pictures. */ function composeBasicImage($aIm,$aBorder,$bBorder,$lSpacing,$aString,$picDir) { $aLeft = $aBorder; for ($i=0;$i $aHeight) { $aHeight = $aSize[1]; } } $bWidth = $aWidth+$xBorder*2; $bHeight = $aHeight+$yBorder*2; return array($bWidth,$bHeight,$aWidth,$aHeight,$cHeight/strlen($aString)); } /** * Applies a distortion to the vertical axes. * @param resource The original image. * @param resource The resulting image. * @param int Width of the text. * @param int Height of the text. * @param int Left position of the text. * @param int Top position of the text. * @param float Minimal vertical distortion. * @param float Random part of the vertical distortion. */ function applyVerticalRoundness($aIm,$bIm,$xText,$yText,$xBorder,$yBorder,$verticalMinimum,$verticalVariance) { $aStretch = $yText*($verticalMinimum+(rand(0,100)/100)*$verticalVariance); if (rand(1,100) > 50) { $aStretch *= -1; } $aDelta = 0; for ($i=0;$i<$yText;$i=$i+1) { $aX = $xBorder; $aY = $yBorder+$i; $aDelta = (2*$i-($yText))/($yText); $aDelta = sin(acos($aDelta)); $aDelta = $aDelta*$aStretch; $bX = $aX-$aDelta; ImageCopy($bIm,$aIm,$bX,$aY,$aX,$aY,$xText,1); } } /** * Stretches the text using a cubic function with randomized parameters. * @param resource The original image. * @param resource The resulting image. * @param int Width of the image. * @param int Height of the image. */ function applyHorizontalWaveLine($aIm,$bIm,$xSize,$ySize,$yBorder) { $xInterval = 20; $xHalfInterval = $xInterval/2; $xWindow = 14; $aLeftMax = -($xHalfInterval-($xInterval-$xWindow)); $aLeft = rand(-$xHalfInterval,$aLeftMax); $aParam = 0.01 + rand(0,100)/100*.005; $bParam = rand(0,100)/100*1.5; for ($x=0;$x<$xSize;$x++) { $xP = $x/$xSize*$xWindow+$aLeft; $aDelta = $aParam*pow($xP,3)+$bParam*$xP; if ($aDelta > $yBorder) { $aDelta = $yBorder; } ImageCopy($bIm,$aIm,$x,$aDelta,$x,0,1,$ySize); } } /** * Applies a given matrix on the picture. * @param resource The original image. * @param resource The resulting image. * @param array The matrix to apply. * @param int The sum of the matrix coefficients. * @param int Width of the picture. * @param int Height of the picture. * @param array Backgroundcolor of the picture. */ function applyMatrix($aIm,$bIm,$aMatrix,$aSum,$xSize,$ySize,$bgColor) { $defaultRGB = array("red"=>$bgColor["red"],"green"=>$bgColor["green"],"blue"=>$bgColor["blue"]); for ($i=0;$i<$xSize;$i++) { for ($j=0;$j<$ySize;$j++) { $aRGB = getGaussianAt($aIm,$i,$j,$aMatrix,$aSum,$defaultRGB); $aColor = ImageColorAllocate($aIm,$aRGB["red"],$aRGB["green"],$aRGB["blue"]); imagesetpixel($bIm,$i,$j,$aColor); } } } /** * Calculates the coefficient sum of a given matrix. * @param array A two dimensional matrix. * @return int The coefficient sum. */ function getMatrixTotal($aMatrix) { $aSum = 0; for ($i=0;$i170,"green"=>170,"blue"=>170); // The color of the guide lines (should be the same as the letters). $lineColor = array("red"=>255,"green"=>0,"blue"=>0); // A 3x3 gaussian blur filter. $aMatrix = array(array(10,22,10), array(22,75,22), array(10,22,10)); // The coefficient sum. $aSum = getMatrixTotal($aMatrix); // Only generate the captcha if empty. if (strlen($_SESSION["captcha"]) == 0) { $_SESSION["captcha"] = getRandomCode($aLength); } $aString = $_SESSION["captcha"]; // Predict image dimensions. list($xSize,$ySize,$xText,$yText,$avgHeight) = predictImageSize($aString,$xBorder,$yBorder,$lSpacing,$picDir); // Create and inizialize image and auxiliary image. $aIm = @ImageCreateTrueColor($xSize,$ySize); $bIm = @ImageCreateTrueColor($xSize,$ySize); $aColor = ImageColorAllocate($aIm,$bgColor["red"],$bgColor["green"],$bgColor["blue"]); $bColor = ImageColorAllocate($bIm,$bgColor["red"],$bgColor["green"],$bgColor["blue"]); $cColor = ImageColorAllocate($aIm,$lineColor["red"],$lineColor["green"],$lineColor["blue"]); ImageFillToBorder($aIm, 0, 0, $aColor, $aColor); ImageFillToBorder($bIm, 0, 0, $bColor, $bColor); // Draw 'guidelines' to make segmentation harder. $aY = $yBorder; $bY = $yBorder+$avgHeight-1; imageline($aIm,$xBorder,$aY,$xBorder+$xSize,$aY,$cColor); imageline($aIm,$xBorder,$bY,$xBorder+$xSize,$bY,$cColor); // Draw the image, apply distortions and gaussian blur. composeBasicImage(&$aIm,$xBorder,$yBorder,$lSpacing,$aString,$picDir); applyVerticalRoundness(&$aIm,&$bIm,$xText,$yText,$xBorder,$yBorder,$verticalMinimum,$verticalVariance); applyHorizontalWaveLine(&$bIm,&$aIm,$xSize,$ySize,$yBorder); applyMatrix(&$aIm,&$bIm,$aMatrix,$aSum,$xSize,$ySize,$bgColor); // Output the image. header ("Content-type: image/png"); ImagePNG ($bIm); ?>