Generate pixels from image template in php not working :( - php

I tried this code to generate pixels around a black and white template, but it only gives me scrambled machine code.
Can anyone tell my how to fix it, or why exactly this happens?
https://nowat.org/test44.php
<?php
// Load the image of Nelson Mandela
$original = imagecreatefromjpeg('https://www.bigissue.org.za/wp-content/uploads/2016/07/Nelson-Mandela_AFP-Photo-2.jpg');
// Get the dimensions of the original image
$width = imagesx($original);
$height = imagesy($original);
// Create a blank image with the same dimensions
$image = imagecreatetruecolor($width, $height);
// Generate random pixels
for ($x = 0; $x < $width; $x++) {
for ($y = 0; $y < $height; $y++) {
// Get the color of the current pixel from the original image
$rgb = imagecolorat($original, $x, $y);
$colors = imagecolorsforindex($original, $rgb);
// Generate a random color variation
$red = rand($colors['red'] - 50, $colors['red'] + 50);
$green = rand($colors['green'] - 50, $colors['green'] + 50);
$blue = rand($colors['blue'] - 50, $colors['blue'] + 50);
$color = imagecolorallocate($image, $red, $green, $blue);
// Set the pixel color
imagesetpixel($image, $x, $y, $color);
}
}
// Output the image as a PNG
header('Content-Type: image/png');
imagepng($image);
// Clean up
imagedestroy($image);
?>
Any Help appreciated!

Your random color are not correct. Color must be between 0 and 255.
...
var_dump($red, $blue, $green);
...
int(261) <--- HERE
PHP Fatal error: Uncaught ValueError: imagecolorallocate(): Argument #2 ($red) must be between 0 and 255 (inclusive) in test.php:24
Stack trace:
#0 test.php(24): imagecolorallocate()
#1 {main}
thrown in test.php on line 24
Try this:
$red = abs(rand($colors['red'] - 50, $colors['red'] + 50) % 255);
$green = abs(rand($colors['green'] - 50, $colors['green'] + 50) % 255);
$blue = abs(rand($colors['blue'] - 50, $colors['blue'] + 50) % 255);
Result here

Related

PHP error when creating image using imagecreatetruecolor

I got a simple HTML that calls a image generated from a PHP file but the image is not being displayed. The HTML part is:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<img src="imgcaptcha.php"/>
</body>
</html>
imgcaptcha.php is:
<?php
//error_reporting(E_ALL);
//header('Content-Type: image/png');
//Generates rando string
function geraStringAleatoria($length = 10) {
$charSet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$stringAleatoria = '';
for ($i = 0; $i < $length; $i++) {
$stringAleatoria .= $charSet[rand(0, strlen($charSet) - 1)];
}
return $stringAleatoria;
}
//Generate the captcha image
function geraImagemCaptcha($text = 'good'){
// Set the content-type
$width = 200;
$height = 30;
// Create the image
$im = imagecreatetruecolor($width, $height) or die('display nao instalado');;
// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, $width-1, $height-1, $white);
//ADD NOISE - DRAW background squares
$square_count = 6;
for($i = 0; $i < $square_count; $i++){
$cx = rand(0,$width);
$cy = (int)rand(0, $width/2);
$h = $cy + (int)rand(0, $height/5);
$w = $cx + (int)rand($width/3, $width);
imagefilledrectangle($im, $cx, $cy, $w, $h, $white);
}
//ADD NOISE - DRAW ELLIPSES
$ellipse_count = 5;
for ($i = 0; $i < $ellipse_count; $i++) {
$cx = (int)rand(-1*($width/2), $width + ($width/2));
$cy = (int)rand(-1*($height/2), $height + ($height/2));
$h = (int)rand($height/2, 2*$height);
$w = (int)rand($width/2, 2*$width);
imageellipse($im, $cx, $cy, $w, $h, $grey);
}
// Replace path by your own font path
$font = 'flushout.ttf';
// Add some shadow to the text
imagettftext($im, 20, 0, 11, 21, $grey, $font, $text);
// Add the text
imagettftext($im, 20, 0, 10, 20, $black, $font, $text);
// Using imagepng() results in clearer text compared with imagejpeg()
imagepng($im);
imagedestroy($im);
}
geraImagemCaptcha(geraStringAleatoria());
?>
I'm using PHP 7
Tried already commenting out header(); call and add error_reporting(E_ALL); but no error message was displayed. Tried also many other different font.ttf files according to this, also didn't worked, so I guess that the problem is in another part of the code rather than the font because I tried many sites and also some other .ttf files I got from other programs installed. The problem is happening in both all browsers I tested. What could be missing in the code? Btw, I got this generate captcha image from here.

How to account for font swash with PHP and GD

I have the following code to print text on an image. I am also adding a debug box around the text. However, I noticed the text on the left lies outside of the box that PHP gives me with imagettfbbox.
This looks like an issue with the font swash. Is there anyway to account for this? Can I figure out the distance between the start of the swash and the actual position imagettfbbox gives to me?
I don't think this is an issue with the font, as I tried it with a few script style fonts and the results were similar.
<?php
$font = 'scriptin.ttf';
$text = 'Ipsum';
$size = 30;
$image = imagecreatetruecolor(200, 200);
$fontColour = imagecolorallocate($image, hexdec('11'), hexdec('11'), hexdec('11'));
$bgColour = imagecolorallocate($image, hexdec('CC'), hexdec('CC'), hexdec('CC'));
imagefilledrectangle($image, 0, 0, 200, 200, $bgColour);
$dimensions = imagettfbbox($size, 0, $font, $text);
imagefilledrectangle(
$image,
$dimensions[0] + 40,
$dimensions[7] + 50,
$dimensions[2] + 40,
$dimensions[3] + 50,
imagecolorallocate($image, mt_rand(1, 180), mt_rand(1, 180), mt_rand(1, 180))
);
imagettftext(
$image,
$size,
0,
40,
50,
$fontColour,
$font,
$text
);
header('Content-Type: image/png');
imagepng($image);
The code and font is available here: https://github.com/AydinHassan/image-swash-example
If you point a VHOST at the repository, you can just hit swash.php
Edit: This appears to be fixed in PHP 7.0.12 (bug #53504) so the code below shouldn't be required.
Based on a comment in the PHP manual I've written the following function to calculate and return the difference between where GD thinks the left side of the bounding box is and where the leftmost pixel is found:
function xadjust($size, $angle, $fontfile, $text)
{
$bbox = imagettfbbox($size, $angle, $fontfile, $text);
$width = $bbox[4] - $bbox[6]; // upper right x - upper left x;
$height = $bbox[1] - $bbox[7]; // lower left y - upper left y;
// create an image with height and width doubled to fit any 'swash'.
$im = imagecreatetruecolor($width * 2, $height * 2);
// set background color to opaque black.
imagefill($im, 0, 0, 0x00000000);
// draw the text in opaque white.
imagettftext(
$im,
$size,
0,
$width / 2,
$height,
0x00ffffff,
$fontfile,
$text
);
// set the min-width to its possible maximum.
$min_x = $width * 2;
for ($x = 0; $x < $width * 2; $x++) {
// each x-pixel (horizontal)
for ($y = 0; $y < $height * 2; $y++) {
// each y-pixel (vertical)
if (imagecolorat($im, $x, $y) > 0) {
// non-black pixel found!
$min_x = min($x, $min_x);
}
}
}
imagedestroy($im);
// return the difference between where GD thinks the bounding box is and
// where we found the leftmost non-black pixel.
return (($width / 2) - $min_x) - abs($bbox[0]);
}
This can be integrated to your script fairly easily:
$font = 'scriptin.ttf';
$text = 'Ipsum';
$size = 30;
$image = imagecreatetruecolor(200, 200);
$fontColour = imagecolorallocate($image, hexdec('11'), hexdec('11'), hexdec('11'));
$bgColour = imagecolorallocate($image, hexdec('CC'), hexdec('CC'), hexdec('CC'));
imagefilledrectangle($image, 0, 0, 200, 200, $bgColour);
$xadjust = xadjust($size, 0, $font, $text); // 1. get the adjust value.
$dimensions = imagettfbbox($size, 0, $font, $text);
imagefilledrectangle(
$image,
$dimensions[0] + 40 - $xadjust, // 2. move the left-side of the box to the left.
$dimensions[7] + 50,
$dimensions[2] + 40 - $xadjust, // 3. move the right-side of the box to the left.
$dimensions[3] + 50,
imagecolorallocate($image, mt_rand(1, 180), mt_rand(1, 180), mt_rand(1, 180))
);
imagettftext(
$image,
$size,
0,
40,
50,
$fontColour,
$font,
$text
);
header('Content-Type: image/png');
imagepng($image);
This gives me the following output:
I've run it with a few other fonts and sizes and it seems to be accurate to within 1 pixel.

Change color of non-transparent parts of png in PHP

I want to fill the png non transparent part with any color or image using php.
Following is the base image
Following is the target image
I have used following code of php to fill non transparent part of the png.
$im = imagecreatefrompng(dirname(__FILE__) . '/images/cat_1.png');
$red = imagecolorallocate($im, 255, 0, 0);
imagefill($im, 0, 0, $red);
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
But it gives me following output.
please help me to complete my task.
Thanks in advance.
Save this version of the base image:
This image has been saved as an indexed-PNG format, making it perfect for colour substitution. In this case, index 0 is the cat's colour, and index 1 is the background (not ideal, but that's what GIMP gave me)
In this case:
$img = imagecreatefrompng("cat_1.png");
imagecolorset($img,0, 255,0,0);
imagepng($img); // output red cat
Image editing in general is made much easier if you have a base image that lends itself to easy editing in this way ;)
This line imagefill($im, 0, 0, $red); fills the image with the color red, at the coordinate (0,0), which is topleft. So it starts filling at the top left and fills everything like when you use the paintbucket in MSPaint. You could use imagefill($im, 150, 150, $red); for example (if 150,150 is the center).
use this function, it returns a base64 image <img src="output">
public static function colorImage($url, $hex = null, $r = null, $g = null, $b = null)
{
if ($hex != null) {
$hex = str_replace("#", "", $hex);
$r = hexdec(substr($hex, 0, 2));
$g = hexdec(substr($hex, 2, 2));
$b = hexdec(substr($hex, 4, 2));
}
$im = imagecreatefrompng($url);
imageAlphaBlending($im, true);
imageSaveAlpha($im, true);
if (imageistruecolor($im)) {
$sx = imagesx($im);
$sy = imagesy($im);
for ($x = 0; $x < $sx; $x++) {
for ($y = 0; $y < $sy; $y++) {
$c = imagecolorat($im, $x, $y);
$a = $c & 0xFF000000;
$newColor = $a | $r << 16 | $g << 8 | $b;
imagesetpixel($im, $x, $y, $newColor);
}
}
}
ob_start();
imagepng($im);
imagedestroy($im);
$image_data = ob_get_contents();
ob_end_clean();
$image_data_base64 = "data:image/png;base64," . base64_encode($image_data);
return $image_data_base64;
}

Showing graphs with php from Mysql tables

How can I show the statistics of data stored in a MySQL table dynamically with PHP image functions? I am able to show the counts in form of bar charts using count query on static tables but as shown in Image given. I have database that stores the logs of server dynamically.
The image is generated from 3 tables and image & draw functions of php
I dont know how you are trying. But there is a nice Jquery plugin called Highcharts. You can use this to create various types of graphs. Please refer the below link if you are interested
http://www.highcharts.com/
Rgraph is also a very nice HTML5/Javascript Graph library, easy to use and with lots of options.
http://www.rgraph.net/
var data = ['<?php echo implode("','", $average); ?>'];
function drawGraph(){
RGraph.Clear(document.getElementById('myRadar'));
var radar = new RGraph.Radar('myRadar', data);
This is how you can add a PHP array, $average is the array with the numbers, it's a radar chart in this example. The implode function puts a comma between the values of the array.
I have used the following code create a simple bar chart with php.
You have to get the bar value from database and put it in $data array.
Next have to set the $height and $width for image size.
Based on your image size, you have to position the chat.
<?php
$data = array('400', '2570', '245', '473', '1000', '3456', '780', '5000', '30', '420');
$sum = array_sum($data);
$height = 480;
$width = 640;
$im = imagecreate($width, $height);
$background = imagecolorallocate($im, 255, 255, 255);
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);
$red = imagecolorallocate($im, 255, 0, 0);
$green = imagecolorallocate($im, 51, 153, 0);
$yellow = imagecolorallocate($im, 255, 255, 0);
imageline($im, 10, 5, 10, $height - 20, $black);
imageline($im, 10, $height - 20, 620, $height - 20, $black);
header("Content-type: image/png");
$x = 11;
$y = 459;
$x_width = 20;
$y_ht = 0;
$max_i = count($data);
for ($i = 0; $i < $max_i; $i++) {
$y_ht = ($data[$i] / $sum) * $height;
if ($data[$i] > 1000) {
imagefilledrectangle($im, $x, $y, $x + $x_width, ($y - $y_ht), $green);
} else if ($data[$i] > 500) {
imagefilledrectangle($im, $x, $y, $x + $x_width, ($y - $y_ht), $yellow);
} else {
imagefilledrectangle($im, $x, $y, $x + $x_width, ($y - $y_ht), $red);
}
imagestring($im, 2, $x - 1, ($y - $y_ht - 15), $data[$i], $black);
$x += ($x_width + 2);
}
imagepng($im);
imagedestroy($im);
?>
ref: http://www.talkphp.com/advanced-php-programming/1629-bar-chart-php.html

Check if image is white; if so make transparent

I have an image, and I want to make it transparent if it's completely white. I have the following code already for GD for getting a part of the image:
$srcp = imagecreatefrompng("../images/".$_GET['b'].".png");
$destp = imagecreate(150, 150);
imagecopyresampled($destp, $srcp, 0, 0, 40, 8, 150, 150, 8, 8);
header('Content-type: image/png');
imagepng($destp);
But how can I have it first check if the image is completely white, if so change it to transparent, and apply that to $destp?
EDIT:
Based on re-reading the question, and the discussion below, I believe this is what you're looking for:
$width = 150;
$height = 150;
$srcp = imagecreatefrompng("../images/".$_GET['b'].".png");
$destp = imagecreatetruecolor(150, 150);
$white = 0;
for ($y = 0; $y < $height; $y++)
{
for ($x = 0; $x < $width; $x++)
{
$currentColor = imagecolorat($srcp, $x, $y);
$colorParts = imagecolorsforindex($srcp, $currentColor);
if (($colorParts['red'] == 255 &&
$colorParts['green'] == 255 &&
$colorParts['blue'] == 255))
{
$white++;
}
}
}
if ($white == ($width * $height))
{
imagecopyresampled($destp, $srcp, 0, 0, 40, 8, 150, 150, 8, 8);
}
else
{
imagesavealpha($destp, true);
imagefill($destp, 0, 0, imagecolorallocatealpha($destp, 0, 0, 0, 127));
}
header('Content-type: image/png');
imagepng($destp);
This produces a blank image if the original image's 8x8 slice is all white, otherwise it resamples the 8x8 slice to 150x150.
Original:
I haven't ever done anything with PHP GD before, and thought it would be a fun challenge. Here's how I ended up making this happen:
$filename = 'test.png'; // input image
$image = imagecreatefrompng($filename);
// grab the input image's size
$size = getimagesize($filename);
$width = $size[0];
$height = $size[1];
$newImage = imagecreatetruecolor($width, $height);
// make sure that the image will retain alpha when saved
imagesavealpha($newImage, true);
// fill with transparent pixels first or else you'll
// get black instead of transparent
imagefill($newImage, 0, 0, imagecolorallocatealpha($newImage, 0, 0, 0, 127));
// loop through all the pixels
for ($y = 0; $y < $height; $y++)
{
for ($x = 0; $x < $width; $x++)
{
// get the current pixel's colour
$currentColor = imagecolorat($image, $x, $y);
// then break it into easily parsed bits
$colorParts = imagecolorsforindex($image, $currentColor);
// if it's NOT white
if (!($colorParts['red'] == 255 &&
$colorParts['green'] == 255 &&
$colorParts['blue'] == 255))
{
// then keep the same colour
imagesetpixel($newImage, $x, $y, $currentColor);
}
}
}
// final output, the second arg is the filename
imagepng($newImage, 'newImage.png');
It allowed me to turn this:
Into this (hard to see the alpha here, but you can open it to see):
A simple strightforward solution would be to use imagecolorat and iterate through all the pixels of the png and if all are white change it to transparent.
Hope this helps.
After a quick look through the GD manual pages, I think that the following should work for you (it did on my test server, anyway):
<?php
// Create image instance
$im = imagecreatefromgif('test.gif');
if (imagecolorstotal($im) == 1) {
$rgb = imagecolorat($im, 1, 1); // feel free to test any pixel, but if they're all
// the same colour, then it shouldn't really matter
$colors = imagecolorsforindex($im, $rgb);
if ($colors['red'] == 255 && $colors['green'] == 255 && $colors['blue'] == 255) {
// I'm ignoring $colors['alpha'] but that's optional.
echo "Yup; it's white...";
}
} else {
// if you've got more than one colour then the image has to be at least
// two colours, so not really worth checking if any pixels are white
}
// Free image
imagedestroy($im);
?>
References:
imagecolorat().
imagecolorstotal().

Categories