There is an excellent code in this question which produces images similar to the following example, using PHP GD library. The image is basically a repeated square pattern.
I need to create similar images BUT with circles pattern but am unable to do so as I am still learning. I tried to modify the code using imagefilledellipse.
$width = 1000;
$height = 600;
$image_p = imagecreatetruecolor($width, $height);
$baseR = 255 - rand(0, 100);
$baseG = 255 - rand(0, 100);
$baseB = 255 - rand(0, 100);
for ($i = 0; $i <= floor($width / 40); $i++){
for ($j = 0; $j <= floor($height / 40); $j++){
$val = floor(100 * (rand(0, 100) / 100)); //value will always be within the range of 1-100
$r = $baseR - $val;
$g = $baseG - $val;
$b = $baseB - $val;
$color = imagecolorallocate($image_p, $r, $g, $b);
imagefilledellipse($image_p, $i * 40, $j * 40, ($i * 40), ($j * 40), $color);
}
}
imagejpeg($image_p, uniqid() .'.jpg');
The result is horrible. Although I understand rest of the code, this line imagefilledellipse($image_p, $i * 40, $j * 40, ($i * 40), ($j * 40), $color); is beyond me. Please help.
just change
imagefilledellipse($image_p, $i * 40, $j * 40, ($i * 40), ($j * 40), $color);
by
imagefilledellipse($image_p, $i * 40, $j * 40, 40, 40, $color);
Related
So, my problem is that i'm using FPDF to create a pdf file from php. Just one problem. Once text is too large for a cell it doesn't wrap. So i came to the point to try to use multicells, but there is another problem. Once a cell is wrapped in a table i got no way to get the other multicells to the same height.
Here is the code i tested.
<?php
require('../fpdf181/fpdf.php');
$pdf = new FPDF('P', 'mm', 'A4');
$pdf->AliasNbPages();
$pdf->AddPage();
$pdf->SetFont('Arial', '', 14);
$x = $pdf->GetX();
$y = $pdf->GetY();
$push_right = 0;
$pdf->MultiCell(50,10,"TEST shdfkjhdsafhahsjdkfkhjshakjfhdsdsfhkjdkjhsafhkjdakjhsfhkjdskjhaf", "TBRL");
$pdf->SetXY($x+50, $y);
$pdf->MultiCell(50,10,"TEST shdfkjhdsafhahsjdkfkhjshakjfhdsdsfhkjdsafsdafdsafsdafsdafddkjhsafhkjdakjhsfhkjdskjhaf", "TBRL");
$pdf->Output();
From that code i got this:
But it should look like this:
This is how it works, for those who have the same problem:
function MultiCellRow($cells, $width, $height, $data, $pdf)
{
$x = $pdf->GetX();
$y = $pdf->GetY();
$maxheight = 0;
for ($i = 0; $i < $cells; $i++) {
$pdf->MultiCell($width, $height, $data[$i]);
if ($pdf->GetY() - $y > $maxheight) $maxheight = $pdf->GetY() - $y;
$pdf->SetXY($x + ($width * ($i + 1)), $y);
}
for ($i = 0; $i < $cells + 1; $i++) {
$pdf->Line($x + $width * $i, $y, $x + $width * $i, $y + $maxheight);
}
$pdf->Line($x, $y, $x + $width * $cells, $y);
$pdf->Line($x, $y + $maxheight, $x + $width * $cells, $y + $maxheight);
}
To execute the function I used: MultiCellRow(3, 50, 10, ["Cell1","Cell2", "Cell3"], $pdf);
The accepted answer works for non-colored backgrounds. If, you wanted to have colored backgrounds, then the accepted answer wouldn't shade the smaller height columns properly.
The below code provides the same functionality as the approved answer, but also supports colored backgrounds. It may not be the cleanest solution (because it has to render the MultiCell components twice), but is the only solution I could create that actually works:
function MultiCellRow($pdf, $data, $width, $height,$darkenBackground){
$x = $pdf->GetX();
$y = $pdf->GetY();
$maxheight = 0;
for ($i = 0; $i < count($data); $i++) {
$pdf->MultiCell($width, $height, $data[$i],0,'C');
if ($pdf->GetY() - $y > $maxheight) $maxheight = $pdf->GetY() - $y;
$pdf->SetXY($x + ($width * ($i + 1)), $y);
}
for ($i = 0; $i < count($data); $i++) {
if($darkenBackground) $pdf->Rect($x+$width*$i,$y,$width,$maxheight,"F");
$pdf->Line($x + $width * $i, $y, $x + $width * $i, $y + $maxheight);
$pdf->SetXY($x+$i*$width,$y);
$pdf->MultiCell($width, $height, $data[$i],0,'C');
}
$pdf->Line($x + $width * count($data), $y, $x + $width * count($data), $y + $maxheight);
$pdf->Line($x, $y, $x + $width * count($data), $y);
$pdf->Line($x, $y + $maxheight, $x + $width * count($data), $y + $maxheight);
$pdf->SetY($y+$maxheight);}
Where the inputs are:
$pdf is the pdf object (new FPDF();)
$data is the array of strings to be rendered in the row
$width is the cell width (integer)
$height is determines the padding/line-spacing of the cell
$darkenBackground is a Boolean.
I give partial credit to "Florian7843" for the first half of the code. I would have edited their existing post, but I made significant changes and thought it would be better to contribute a separate answer.
If somebody wants to dedicate a cleaner/efficient solution, please propose an edit.
Cheers!
I am trying to create an image with a pattern of a repeated circle. I am doing this in PHP with GD. So far I have been able to tile the circle in horizontal manner (x-axis) but am unable to tile it in the vertical(y-axis). Here is an example image.
Below is the code that created the above image :
$width = 1000;
$height = 500;
$image_p = imagecreatetruecolor($width, $height);
$color = imagecolorallocate($image_p, 0, 255, 0);
for ($i = 0; $i <= 10; $i++){
if ($i % 2 !== 0){ //only if odd numbers
imagefilledellipse ($image_p, 50 * $i, 50, 100, 100, $color);
}
}
imagejpeg($image_p, uniqid() .'.jpg');
My guess is that in order to tile each circle in a vertical manner it just needs another nested for loop and it would be similar to one already there except the change in y-axis like so :
imagefilledellipse ($image_p, 50, 50 * $i, 100, 100, $color);
I have tried a lot of nesting variation but could not get it to work. Please help.
The function imagefilledellipse has the following signature (I suppose):
imagefilledellipse(image, x, y, width, height, color)
Which means that you are drawing for every i in 0 < i < 10 a circle with a different x position.
Swap it with the y parameter to draw vertical circles:
$width = 1000;
$height = 500;
$image_p = imagecreatetruecolor($width, $height);
$color = imagecolorallocate($image_p, 0, 255, 0);
for ($i = 0; $i <= 10; $i++){
if ($i % 2 !== 0){ //only if odd numbers
imagefilledellipse ($image_p, 50, 50 * $i, 100, 100, $color);
}
}
imagejpeg($image_p, uniqid() .'.jpg');
In order to draw both horizontal and vertical circles you will need indeed, as you said, a nested for-loop:
$width = 1000;
$height = 500;
$image_p = imagecreatetruecolor($width, $height);
$color = imagecolorallocate($image_p, 0, 255, 0);
for ($i = 0; $i <= 10; $i++){
for ($j = 0; $j <= 10; $j++) {
if ($i % 2 !== 0 && $j % 2 !== 0) { //only if odd numbers
imagefilledellipse ($image_p, 50 * $i, 50 * $j, 100, 100, $color);
}
}
}
imagejpeg($image_p, uniqid() .'.jpg');
Also, you do not need to check for odd numbers if you would change the scale from i * 50 to 50 + i * 100, like this:
imagefilledellipse ($image_p, 50 + 100 * $i, 50 + 100 * $j, 100, 100, $color);
If you know how many columns you want it should be quite easy.
$colCounter=0;
$yAxis = 50;
for ($i = 0; $i <= 10; $i++){
if ($i % 2 !== 0){ //only if odd numbers
if ($colCounter % 5 === 0){ // Do something every 5 cols
$yAxis = $yAxis + 50 // add 50 onto each row
}
$colCounter++;//increment counter
imagefilledellipse ($image_p, 50 * $i, $yAxis, 100, 100, $color);
}
}
Note this is un-tested code
I have created a code to generate a random pattern image. it creates an image with given width and height and fills it with small 40x40 pixel rectangles.
this is my code:
<?php
$width = 1000;
$height = 600;
$image_p = imagecreate($width, $height);
$baseR = 255 - rand(0, 100);
$baseG = 255 - rand(0, 100);
$baseB = 255 - rand(0, 100);
for ($i = 0; $i <= floor($width / 40); $i++){
for ($j = 0; $j <= floor($height / 40); $j++){
$val = floor(100 * (rand(0, 100) / 100));
$r = $baseR - $val;
$g = $baseG - $val;
$b = $baseB - $val;
$color = imagecolorallocate($image_p, $r, $g, $b);
imagefilledrectangle($image_p, $i * 40, $j * 40, (($i + 1) * 40), (($j + 1) * 40), $color);
}
}
imagejpeg($image_p, 'my_dir/test.jpg');
?>
there's no problem when i set the width to a value like 640 and the height to 400. but if i set the width to 1000 and the height to 800, there will be a blank area on the right side of the image which is not covered by rectangles.
I implemented the same code in delphi and it worked perfectly, but in PHP...!
Change imagecreate to imagecreatetruecolor
You're creating a palette based image with 255 colors max. You're running out of colors to allocate at the end and it's recycling the last color on the palette for the remainder of the blocks.
I have set imagealphablending on every image I create, still there is a black background. What could be the problem?
$systemSettings = array(
'captcha' => array(
'colors' => array(array(30, 80, 180), array(20, 160, 40), array(220, 40, 10)),
'fonts' => array('AntykwaBold.ttf', 'Candice.ttf', 'Carbon.ttf', 'Duality.ttf', 'Heineken.ttf', 'Jura.ttf', 'StayPuft.ttf', 'TimesNewRomanBold.ttf', 'VeraSansBold.ttf'),
'size' => array('width' => '200', 'height' => '50')
)
);
function generateCaptcha() {
global $systemSettings;
$randomLetters = "abcdef";
$scale = 3;
$width = $systemSettings['captcha']['size']['width'];
$height = $systemSettings['captcha']['size']['height'];
$im = imagecreatetruecolor($width * $scale, $height * $scale);
imagealphablending($im, true);
//$GdBgColor = imagecolorallocate($im, 250, 250, 250);
//imagefilledrectangle($im, 0, 0, $width * $scale, $height * $scale, $GdBgColor);
$color = $systemSettings['captcha']['colors'][mt_rand(0, sizeof($systemSettings['captcha']['colors']) - 1)];
$GdFgColor = imagecolorallocate($im, $color[0], $color[1], $color[2]);
$fontfile = 'visual/fonts/' . $systemSettings['captcha']['fonts'][array_rand($systemSettings['captcha']['fonts'])];
$x = 20 * $scale;
$y = round(($height * 0.75) * $scale);
$length = strlen($randomLetters);
for ($i = 0; $i < $length; $i++) {
$degree = rand(-10, 10);
$fontsize = rand(20, 25) * $scale;
$letter = substr($randomLetters, $i, 1);
$coords = imagettftext($im, $fontsize, $degree, $x, $y, $GdFgColor, $fontfile, $letter);
$x += ($coords[2] - $x);
}
$k = rand(0, 100);
$xp = $scale * 12 * rand(1, 3);
for ($i = 0; $i < ($width * $scale); $i++)
imagecopy($im, $im, $i - 1, sin($k + $i / $xp) * ($scale * 5), $i, 0, 1, $height * $scale);
$k = rand(0, 100);
$yp = $scale * 12 * rand(1, 3);
for ($i = 0; $i < ($height * $scale); $i++)
imagecopy($im, $im, sin($k + $i / $yp) * ($scale * 14), $i - 1, 0, $i, $width * $scale, 1);
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
$imResampled = imagecreatetruecolor($width, $height);
imagecopyresampled($imResampled, $im, 0, 0, 0, 0, $width, $height, $width * $scale, $height * $scale);
imagealphablending($imResampled, true);
header("Content-type: image/png");
imagepng($imResampled);
imagedestroy($im);
imagedestroy($imResampled);
}
try this
$systemSettings = array(
'captcha' => array(
'colors' => array(array(30, 80, 180), array(20, 160, 40), array(220, 40, 10)),
'fonts' => array('AntykwaBold.ttf', 'Candice.ttf', 'Carbon.ttf', 'Duality.ttf', 'Heineken.ttf', 'Jura.ttf', 'StayPuft.ttf', 'TimesNewRomanBold.ttf', 'VeraSansBold.ttf'),
'size' => array('width' => '200', 'height' => '50')
)
);
function generateCaptcha() {
global $systemSettings;
$randomLetters = "abcdef";
$scale = 3;
$width = $systemSettings['captcha']['size']['width'];
$height = $systemSettings['captcha']['size']['height'];
$im = imagecreatetruecolor($width * $scale, $height * $scale);
// enable alpha blending on the destination image.
imagealphablending($im, true);
// Allocate a transparent color and fill the new image with it.
// Without this the image will have a black background instead of being transparent.
$transparent = imagecolorallocatealpha( $im, 0, 0, 0, 127 );
imagefill( $im, 0, 0, $transparent );
// disable alpha blending on the destination image.
imagealphablending($im, false);
// save the alpha
imagesavealpha($im,true);
//$GdBgColor = imagecolorallocate($im, 250, 250, 250);
//imagefilledrectangle($im, 0, 0, $width * $scale, $height * $scale, $GdBgColor);
$color = $systemSettings['captcha']['colors'][mt_rand(0, sizeof($systemSettings['captcha']['colors']) - 1)];
$GdFgColor = imagecolorallocate($im, $color[0], $color[1], $color[2]);
$fontfile = 'visual/fonts/' . $systemSettings['captcha']['fonts'][array_rand($systemSettings['captcha']['fonts'])];
$x = 20 * $scale;
$y = round(($height * 0.75) * $scale);
$length = strlen($randomLetters);
for ($i = 0; $i < $length; $i++) {
$degree = rand(-10, 10);
$fontsize = rand(20, 25) * $scale;
$letter = substr($randomLetters, $i, 1);
$coords = imagettftext($im, $fontsize, $degree, $x, $y, $GdFgColor, $fontfile, $letter);
$x += ($coords[2] - $x);
}
$k = rand(0, 100);
$xp = $scale * 12 * rand(1, 3);
for ($i = 0; $i < ($width * $scale); $i++)
imagecopy($im, $im, $i - 1, sin($k + $i / $xp) * ($scale * 5), $i, 0, 1, $height * $scale);
$k = rand(0, 100);
$yp = $scale * 12 * rand(1, 3);
for ($i = 0; $i < ($height * $scale); $i++)
imagecopy($im, $im, sin($k + $i / $yp) * ($scale * 14), $i - 1, 0, $i, $width * $scale, 1);
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
$imResampled = imagecreatetruecolor($width, $height);
// enable alpha blending on the destination image.
imagealphablending($imResampled, true);
// Allocate a transparent color and fill the new image with it.
// Without this the image will have a black background instead of being transparent.
$transparent = imagecolorallocatealpha( $imResampled, 0, 0, 0, 127 );
imagefill( $imResampled, 0, 0, $transparent );
// disable alpha blending on the destination image.
imagealphablending($imResampled, false);
// save the alpha
imagesavealpha($imResampled,true);
imagecopyresampled($imResampled, $im, 0, 0, 0, 0, $width, $height, $width * $scale, $height * $scale);
header("Content-type: image/png");
imagepng($imResampled);
imagedestroy($im);
imagedestroy($imResampled);
}
Just for the sake of my question, lets say this function:
int imagecolorexact ( resource $image , int $red , int $green , int $blue )
We can call it up pretty easy like this:
$index = imagecolorexact($image, 0, 0, 0);
Obviously because we are talking the example in hand is about RGB colors, therefore the $red, $green and $blue values are between 0 and 255. This function returns an index of the pixel with that rgb compound.
What I need is to get the index of all pixels that their compound is NOT (0, 0, 0), so I'd thought to do it like this:
for($i = 0; $i <= 255; $i++) {
for($j = 0; $i <= 255; $i++) {
for($k = 0; $i <= 255; $i++) {
$index[] = imagecolorexact($image, $i, $j, $k);
}
}
}
But this will run 255*255*255 times which is alot I quess.
My question is:
Is there any way to simplify this?
Why am I asking this?
I am trying to change all the black pixels from an image to yellow, thus that would be:
$image = imagecreatefrompng("./test.png");
imagecolorset($image, imagecolorexact($image, 0, 0, 0), 255, 255, 0);
And I need to change all the NON black pixels from the same image into black, thus that will be (I quess?):
for($i = 1; $i <= 255; $i++) {
for($j = 1; $i <= 255; $i++) {
for($k = 1; $i <= 255; $i++) {
$index = imagecolorexact($image, $i, $j, $k);
imagecolorset($new, $value, 0, 0, 0);
}
}
}
Thus I am asking if there is a better, optimized way?