I was hoping to get in touch with someone on a situation that I cannot find the solution to anywhere.
I am trying to create a captcha on my website using php and although I was able to create an image and create the random captcha text.
I am unable to over lay the two. Here is my code:
<?PHP
session_start();
function generateRandomString($length = 10) {
$letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$len = strlen($letters);
$letter = $letters[rand(0, $len - 1)];
$text_color = imagecolorallocate($image, 0, 0, 0);
$word = "";
for ($i = 0; $i < 6; $i++) {
$letter = $letters[rand(0, $len - 1)];
imagestring($image, 7, 5 + ($i * 30), 20, $letter, $text_color);
$word .= $letter;
}
$_SESSION['captcha_string'] = $word;
}
function security_image(){
// $code = isset($_SESSION['captcha']) ? $_SESSION['captcha'] : generate_code();
//$font = 'content/fonts/comic.ttf';
$width = '110';
$height = '20';
$font_size = $height * 0.75;
// $image = #imagecreate($width, $height) or die('GD not installed');
global $image;
$image = imagecreatetruecolor($width, $height) or die("Cannot Initialize new GD image stream");
$background_color = imagecolorallocate($image, 255, 255, 255);
imagefilledrectangle($image,0,0,200,50,$background_color);
$line_color = imagecolorallocate($image, 64,64,64);
for($i=0;$i<10;$i++) {
imageline($image,0,rand()%50,200,rand()%50,$line_color);
}
$pixel_color = imagecolorallocate($image, 0,0,255);
for($i=0;$i<1000;$i++) {
imagesetpixel($image,rand()%200,rand()%50,$pixel_color);
}
//$textbox = imagettfbbox($font_size, 0, $font, $code);
//$textbox = imagettfbbox($font_size, 0, $randomString);
$x = ($width - $textbox[4]) / 2;
$y = ($height - $textbox[5]) / 2;
// imagettftext($image, $font_size, 0, $x, $y, $text_color, $font , $code);
imagettftext($image, $font_size, 0, $x, $y, $text_color , $word);
$images = glob("*.png");
foreach ($images as $image_to_delete) {
#unlink($image_to_delete);
}
imagepng($image, "image" . $_SESSION['count'] . ".png");
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
}
security_image();
?>
I have no idea what I’m doing wrong. I’ve spent over 10 hours on this “display text” issue. I don’t understand and I am desperate for help. I even downloaded working captcha version from other resources that break once I upload it to my server. I have no idea whats going on. At first I thought there was something wrong with my server but the fact that I can even create the pixels, lines image means that it is at least working.
Please help!!!!
UPDATE---------------------------------------------
Thank you for your suggestions. Here is the edited code. I'm still getting the same issue.
<?PHP
session_start();
function security_image(){
global $image;
// $code = isset($_SESSION['captcha']) ? $_SESSION['captcha'] : generate_code();
$font = 'content/fonts/comic.ttf';
$width = '110';
$height = '20';
$font_size = $height * 0.75;
$image = imagecreatetruecolor($width, $height) or die("Cannot Initialize new GD image stream");
$background_color = imagecolorallocate($image, 255, 255, 255);
imagefilledrectangle($image,0,0,200,50,$background_color);
$line_color = imagecolorallocate($image, 64,64,64);
for($i=0;$i<10;$i++) {
imageline($image,0,rand()%50,200,rand()%50,$line_color);
}
$pixel_color = imagecolorallocate($image, 0,0,255);
for($i=0;$i<1000;$i++) {
imagesetpixel($image,rand()%200,rand()%50,$pixel_color);
}
$letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$len = strlen($letters);
$letter = $letters[rand(0, $len - 1)];
$text_color = imagecolorallocate($image, 0, 0, 0);
$word = "";
for ($i = 0; $i < 6; $i++) {
$letter = $letters[rand(0, $len - 1)];
imagestring($image, 7, 5 + ($i * 30), 20, $letter, $text_color);
$word .= $letter;
}
$_SESSION['captcha_string'] = $word;
/*texbox unitinitialized (removed for the sake of just showing the word size doesnt matter)
$x = ($width - $textbox[4]) / 2;
$y = ($height - $textbox[5]) / 2;
*/
$x = ($width) / 2;
$y = ($height) / 2;
imagettftext($image,$font, 4, $x, $y, $word);
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
}
security_image();?>
i made some suggested changes but the code seems to still do the same thing. Just display the lines and pixels as expected but the text still is missing... ?
There are some several "errors" in your functions, let's fix them:
In generateRandomString()
generateRandomString($length = 10)
$lenght is not used its scope.
$text_color = imagecolorallocate($image, 0, 0, 0);
$image is uninitialized
In security_image() function:
$textbox is uninitialized
$text_color and $word is uninitialized.
And Wrong parameter count for imagettftext() You add 7 parameters, and forget the font file parameter.
found the problem. using this:
http://php.net/manual/en/function.imagettftext.php
i was able to see that the font location was incorrect. using the example on that page and editing it to my needs worked.
Related
I have a function which adds text under a existing qr-code image.
In some cases the return is faster than the server has written the image on the filesystem, so that other function got issues.
How can I make sure that everything is done before I return the path to the image?
At the moment I am trying to use a while-loop, but I am also really unhappy with it. That causes also timeouts and crashes on my server (no idea why).
function addTextToQrCode($oldImage, $text)
{
$newImage = $oldImage;
$newImage = str_replace(".png", "_original.png", $newImage);
copy($oldImage, $newImage);
$image = imagecreatefrompng($oldImage);
$black = imagecolorallocate($image, 0, 0, 0);
$fontSize = 20;
$textWidth = imagefontwidth($fontSize) * strlen($text);
$textHeight = imagefontheight($fontSize);
$x = imagesx($image) / 2 - $textWidth / 2;
$y = imagesy($image) - $textHeight - 3;
imagestring($image, 5, $x, $y, $text, $black);
$filePath = "/qrCodes/qrcode".$text.'.png';
imagepng($image, $filePath);
while(!$this->checkIfNewQrCodeIsOnFileSystem($filePath)){
$this->checkIfNewQrCodeIsOnFileSystem($filePath);
}
return $filePath;
}
function checkIfNewQrCodeIsOnFileSystem($filePath) {
if (file_exists($filePath)) {
return true;
} else {
return false;
}
}
Check only imagepng(). The solution i would prefer.
function addTextToQrCode($oldImage, $text)
{
$newImage = $oldImage;
$newImage = str_replace(".png", "_original.png", $newImage);
copy($oldImage, $newImage);
$image = imagecreatefrompng($oldImage);
$black = imagecolorallocate($image, 0, 0, 0);
$fontSize = 20;
$textWidth = imagefontwidth($fontSize) * strlen($text);
$textHeight = imagefontheight($fontSize);
$x = imagesx($image) / 2 - $textWidth / 2;
$y = imagesy($image) - $textHeight - 3;
imagestring($image, 5, $x, $y, $text, $black);
$filePath = "/qrCodes/qrcode".$text.'.png';
if (imagepng($image, $filePath) === true) {
return $filePath;
}
}
I want to implement a simple captcha in ci4, I try to search a sample code in google and then copas it. But when run the code get result like this. Please help what wrong in my code ?
My controller is :
private function captcha()
{
$i = 0;
$imgHeight = 80;
$imgWidth = 250;
$randTotal = 7;
$randomDots = 50;
$randomLines = 25;
$font = realpath('./fonts/monofont.ttf');
$random = '';
$captTextColor = "0x142864";
$noiseColor = "0x142864";
$fontSize = $imgHeight * 0.65;
$random = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz0123456789'), 0,
$randTotal);
$image = #imagecreate($imgWidth, $imgHeight);
$arrTextColor = $this->hexToRGB($captTextColor);
$arrNoiseColor = $this->hexToRGB($noiseColor);
$bgColor = imagecolorallocate($image, 255, 255, 255);
$captTextColor = imagecolorallocate($image, $arrTextColor['red'], $arrTextColor['green'], $arrTextColor['blue']);
$imgNoiseColor = imagecolorallocate($image, $arrNoiseColor['red'], $arrNoiseColor['green'], $arrNoiseColor['blue']);
// Cetak titik acak di latar belakang gambar
for ($i = 0; $i < $randomDots; $i++) {
imagefilledellipse($image, mt_rand(0, $imgWidth), mt_rand(0, $imgHeight), 2, 3, $imgNoiseColor);
}
// Cetak garis acak di latar belakang gambar
for ($i = 0; $i < $randomLines; $i++) {
imageline(
$image,
mt_rand(0, $imgWidth),
mt_rand(0, $imgHeight),
mt_rand(0, $imgWidth),
mt_rand(0, $imgHeight),
$imgNoiseColor
);
}
// Cetak kotak teks dan tambahkan 6 kode huruf captcha
$textBox = imagettfbbox($fontSize, 0, $font, $random);
$x = ($imgWidth - $textBox[4]) / 2;
$y = ($imgHeight - $textBox[5]) / 2;
$_SESSION['captcha'] = $random;
// imagettftext($image, $fontSize, 0, $x, $y, $captTextColor, $font, $random);
imagettftext($image, $fontSize, 0, $x, $y, $captTextColor, $font, $random);
header('Content-Type: image/jpeg');
imagejpeg($image, null, null);
imagedestroy($image);
}
Thank you
Thank you.
Try adding the exit; command after the imagedestroy($image); line
I would like to put on a picture in vertical text in PHP:
function scrivi($scrivi, $p) {
$imgResource = imagecreatefromjpeg($p);
$textcolor = imagecolorallocate($imgResource, 255, 255, 255);
$fontPath = "st.ttf";
$fontSize = "18";
$rotation = "270"; // counter-clockwise rotation
$text = "this is a text";
$textCoords = imagettfbbox($fontSize, $rotation, $fontPath, $text);
$x = 36;
$y = 36;
imagettftext($imgResource, $fontSize, $rotation, $x, $y, $textcolor, $fontPath, $text);
unlink($p);
imagejpeg($imgResource, $p, 100);
imagedestroy($imgResource);
}
It works well only that I would like that the letters are turned this is an example using the function
Instead I would like to
an idea could be to wrap each letter
All you really need to do is split the text into an array, loop it, then offset the y by the height + leading of the font character:
function scrivi($p,$text)
{
$imgResource = imagecreatefromjpeg($p);
$textcolor = imagecolorallocate($imgResource, 255,255, 255);
$fontPath = __DIR__."/st.ttf";
$fontSize = "18";
$x = 36 ;
$y = 36;
foreach(str_split($text) as $char) {
$textCoords = imagettfbbox($fontSize, 0, $fontPath, $char);
imagettftext($imgResource, $fontSize, 0, $x, $y, $textcolor,$fontPath,$char);
$y += 24;
}
unlink($p);
imagejpeg($imgResource,$p,100);
imagedestroy($imgResource);
}
scrivi('http://imgtops.sourceforge.net/bakeoff/bw.jpg',"Cats are great");
Gives you:
(Image credit: http://imgtops.sourceforge.net/bakeoff/)
The PHP code below generates text as a dynamically created image, how would I be able to get the image to only be as large as the text? Thanks.
<?php
header('Content-Type: image/jpeg');
$text='Test';
$img = imageCreate(200,200);
imagecolorallocate($img, 255, 255, 255);
$textColor = imagecolorallocate($img, 0, 0, 0);
imagefttext($img, 15, 0, 0, 55, $textColor, 'bgtbt.ttf', $text);
imagejpeg($img);
imagedestroy($img);
?>
UPDATE 1: I found the answer here with the example of the original poster - Creating IMage from Text in PHP - how can I make multiline?
UPDATE 2: Martin Geisler's version also works well
When using a TrueType font, you use the imageftbbox function to obtain the bounding box for a string typeset with your font. The bounding box gives the offsets from the base-point to the four corners in the rectangle occupied by the text. So if you store the bounding box in $bb and use imagefttext to put text at ($x, $y), then the corners will have these coordinates:
($x + $bb[6], $y + $bb[7]) ($x + $bb[4], $y + $bb[5])
+-------+
| Hello |
+-------+
($x + $bb[0], $y + $bb[1]) ($x + $bb[2], $y + $bb[3])
That tells us that we want an image width of ($x + $bb[2]) - ($x + $bb[6]) = $bb[2] - $bb[6] and similarly an image height of $bb[3] - $bb[7]. The text should then be rendered at coordinates (-$bb[6], -$bb[7]) inside that picture since we want to have
(0, 0) = ($x + $bb[6], $y + $bb[7]) ==> $x = -$bb[6] and $y = -$bb[7]
You can try it out with this code. Put it into a file called img.php and browse to img.php?q=Hello to test:
<?php
header("Content-type: image/png");
$q = $_REQUEST['q'];
$font = "Impact.ttf";
$size = 30;
$bbox = imageftbbox($size, 0, $font, $q);
$width = $bbox[2] - $bbox[6];
$height = $bbox[3] - $bbox[7];
$im = imagecreatetruecolor($width, $height);
$green = imagecolorallocate($im, 60, 240, 60);
imagefttext($im, $size, 0, -$bbox[6], -$bbox[7], $green, $font, $q);
imagepng($im);
imagedestroy($im);
?>
If you use the bitmap fonts instead, then look at the imagefontwidth and imagefontheight functions.
#Martin Geisler's answer is almost correct, but I couldn't get my text to fit completely inside the image. I tried this instead, which works perfectly!
From the PHP Manual's User Contributed Notes:
$text = "<?php echo \"hello, world\"; ?>";
$font = "./arial.ttf";
$size = "60";
$bbox = imagettfbbox($size, 0, $font, $text);
$width = abs($bbox[2] - $bbox[0]);
$height = abs($bbox[7] - $bbox[1]);
$image = imagecreatetruecolor($width, $height);
$bgcolor = imagecolorallocate($image, 255, 255, 255);
$color = imagecolorallocate($image, 0, 0, 0);
$x = $bbox[0] + ($width / 2) - ($bbox[4] / 2);
$y = $bbox[1] + ($height / 2) - ($bbox[5] / 2);
imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);
$last_pixel= imagecolorat($image, 0, 0);
for ($j = 0; $j < $height; $j++)
{
for ($i = 0; $i < $width; $i++)
{
if (isset($blank_left) && $i >= $blank_left)
{
break;
}
if (imagecolorat($image, $i, $j) !== $last_pixel)
{
if (!isset($blank_top))
{
$blank_top = $j;
}
$blank_left = $i;
break;
}
$last_pixel = imagecolorat($image, $i, $j);
}
}
$x -= $blank_left;
$y -= $blank_top;
imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);
I have a script that generates images from text using PHP. It's working fine except that I would like it to generate multiline text as well with differing colors. How can it be done using PHP, GD and Freetype? Below is the code I use to generate single line text images.
$textval = 'This is some text to be an image';
$textcolor = '666666';
$font="arial.ttf";
$size = 9;
$padding= 1;
$bgcolor= "ffffff";
$transparent = 0;
$antialias = 0;
$fontfile = $fontpath.$font;
$box= imageftbbox( $size, 0, $fontfile, $textval, array());
$boxwidth= $box[4];
$boxheight= abs($box[3]) + abs($box[5]);
$width= $boxwidth + ($padding*2) + 1;
$height= $boxheight + ($padding) + 0;
$textx= $padding;
$texty= ($boxheight - abs($box[3])) + $padding;
// create the image
$png= imagecreate($width, $height);
$color = str_replace("#","",$bgcolor);
$red = hexdec(substr($bgcolor,0,2));
$green = hexdec(substr($bgcolor,2,2));
$blue = hexdec(substr($bgcolor,4,2));
$bg = imagecolorallocate($png, $red, $green, $blue);
$color = str_replace("#","",$textcolor);
$red = hexdec(substr($textcolor,0,2));
$green = hexdec(substr($textcolor,2,2));
$blue = hexdec(substr($textcolor,4,2));
$tx = imagecolorallocate($png, $red, $green, $blue);
imagettftext( $png, $size, 0, $textx, $texty, $tx, $fontfile, $textval );
header("content-type: image/jpeg");
imagejpeg($png);
imagedestroy($png);
exit;
Add this function to wrap the text before it goes into your function.
function wrap($fontSize, $angle, $fontFace, $string, $width){
$ret = "";
$arr = explode(' ', $string);
foreach ( $arr as $word ){
$teststring = $ret.' '.$word;
$testbox = imagettfbbox($fontSize, $angle, $fontFace, $teststring);
if ( $testbox[2] > $width ){
$ret.=($ret==""?"":"\n").$word;
} else {
$ret.=($ret==""?"":' ').$word;
}
}
return $ret;
}
Source: http://www.php.net/imagettftext