PHP Geometry pie chart - php

i have this php program which takes in an angle as a get parameter and prints a segment of a circle with that angle:
<?php
$size = 600;
$img = imagecreatetruecolor($size, $size);
$white = imagecolorallocate($img, 255, 255, 255);
$black = imagecolorallocate($img, 0, 0, 0);
imagefilledrectangle($img,0,0,$size,$size,$white);
function Vector($palette,$startx,$starty,$angle,$length,$colour){
$angle = deg2rad($angle);
$endx = $startx+cos($angle)*$length;
$endy = $starty-sin($angle)*$length;
return(imageline($palette,$startx,$starty,$endx,$endy,$colour));
}
$ang = 0;
while($ang <= $_GET['angle']){
Vector($img,$size/2,$size/2,$ang,200,$black);
$ang += 1;
}
header("Content-type: image/png");
imagepng($img);
?>
The function vector basically draws a line with the given parameters. So i loop through a number of times and then each time i loop through i increase the angle by 1. And then i call the vector function which basically draws a sort of circle segment with the specified angle.
But when i wish to draw another sector of the circle starting at the end point of the previous circle, it overlaps! By the way, here's the code:
<?php
$size = 600;
$img = imagecreatetruecolor($size, $size);
$white = imagecolorallocate($img, 255, 255, 255);
$black = imagecolorallocate($img, 0, 0, 0);
$blue = imagecolorallocate($img, 0, 0, 255);
imagefilledrectangle($img,0,0,$size,$size,$white);
function Vector($palette,$startx,$starty,$angle,$length,$colour){
$angle = deg2rad($angle);
$endx = $startx+cos($angle)*$length;
$endy = $starty-sin($angle)*$length;
return(imageline($palette,$startx,$starty,$endx,$endy,$colour));
}
$int = 0;
while($int <= $_GET['angle']){
Vector($img,$size/2,$size/2,$int,200,$black);
$int += 0.01;
}
$int = 0;
while($int <= $_GET['angle']){
Vector($img,$size/2,$size/2,$int,200,$blue);
$int += 0.01;
}
header("Content-type: image/png");
imagepng($img);
?>
In the above code, i expect to draw a circle sector with an angle and then draw another sector with the same angle but in blue color.
I want the 2nd sector to start where the first sector ended, but it overlaps?
So how do i make it start where the previous one stopped?

You say, that you have a function to draw a vector with a certain angle right? Then you can have a loop 360 times and increase the angle by 1 degree per loop and draw the vector. You'll get a circle.
For a pie chart all you have to do is change colours at certain intervals depending upon your segment's angle...
If you're working on a voting system, here's the FULL source code for a PHP image generator which takes in n number of QueryString arguments and makes a pie chart with all those QueryString arguements and puts in a legend for them:
<?php
$size = 600;
$img = imagecreatetruecolor($size, $size);
$white = imagecolorallocate($img, 255, 255, 255);
$black = imagecolorallocate($img, 0, 0, 0);
imagefilledrectangle($img,0,0,$size,$size,$white);
function Vector($palette,$startx,$starty,$angle,$length,$colour){
$angle = deg2rad($angle);
$endx = $startx+cos($angle)*$length;
$endy = $starty-sin($angle)*$length;
return(imageline($palette,$startx,$starty,$endx,$endy,$colour));
}
$sum__ = array_sum($_GET);
$items = array();
foreach($_GET as $key => $value){
$items[$key] = ($value/$sum__)*360;
}
$items2 = array();
$cur = 0;
foreach($items as $key => $value){
$cur += $value;
$items2[$key]=$cur;
}
$colors = array();
foreach($items as $key => $value){
while(array_key_exists($key,$colors) == False){
$tempcolor = imagecolorallocate($img, rand(0,255), rand(0,255), rand(0,255));
if(in_array($tempcolor,$colors) == False){
$colors[$key] = $tempcolor;
}
}
}
$int = 0;
foreach($items2 as $key => $value){
while($int <= $value){
Vector($img,$size/2,$size/2,$int,200,$colors[$key]);
$int += 0.01;
}
}
$container = 10;
foreach($items2 as $key => $value){
imagefilledrectangle($img, 4, $container, 50, $container+15, $colors[$key]);
imagestring($img,5,4+60,$container,$key,$black);
$container += 20;
}
header("Content-type: image/png");
imagepng($img);
?>
hope that helps...

Just FYI, you only need to change two lines of your original code to do what you want. Delete the second $int = 0; and make a change to the next line so that:
$int = 0;
while($int <= $_GET['angle']){
Vector($img,$size/2,$size/2,$int,200,$blue);
$int += 0.01;
}
Becomes:
//delete '$int = 0;'
while($int <= ($_GET['angle']) * 2){
Vector($img,$size/2,$size/2,$int,200,$blue);
$int += 0.01;
}
It's not a general solution but hopefully will allow you to see what you were originally doing wrong.

Related

How I can apply color threshold into an image created from `imagecreatefromstring`?

I have the following piece of code:
define(RED_THESHOLD,100);
define(GREEN_THESHOLD,200);
define(BLUE_THESHOLD,100);
function thresholdImage(String $imgdata){
$original_limit = ini_get('memory_limit');
ini_set('memory_limit', '-1');
$imageResource = imagecreatefromstring($imgData);
// Limit red green and blue color channels here
}
But I do not know how I can apply the color the constants:
RED_THESHOLD
GREEN_THESHOLD
BLUE_THESHOLD
According to the classic algorithms I need to read pixel by pixel each channel and apply the threshold by the following piece of code (I use images red channel as an example):
$new_pixel_value = ($red_pixel_value>RED_THESHOLD)?RED_THESHOLD:$red_pixel_value;
Do you know how I can do this?
This can be done by finding the color index for each pixel, converting that into RGBA, then constraining those values, converting it back into a color index and setting the pixel.
<?php
const RED_THESHOLD = 255;
const GREEN_THESHOLD = 10;
const BLUE_THESHOLD = 10;
$image = imagecreatefrompng('test.png');
$maxX = imagesx($image);
$maxY = imagesy($image);
for ($y = 0; $y < $maxY; ++$y) {
for ($x = 0; $x < $maxX; ++$x) {
$existing = imagecolorsforindex($image, imagecolorat($image, $x, $y));
$red = ($existing['red'] > RED_THESHOLD) ? RED_THESHOLD : $existing['red'];
$green = ($existing['green'] > GREEN_THESHOLD) ? GREEN_THESHOLD : $existing['green'];
$blue = ($existing['blue'] > BLUE_THESHOLD) ? BLUE_THESHOLD : $existing['blue'];
$new = imagecolorexact($image, $red, $green, $blue);
imagesetpixel($image, $x, $y, $new);
}
}
imagepng($image, 'test2.png');
Here is a comparison picture:

Iterate through an image to replace all colors except one with black in php

I need to iterate through all pixels in an image to replace all but one color with black so that I can define all regions of a particular color. The code below is not working, the image remains unchanged. What am I doing wrong?
header('Content-Type: image/jpeg');
// open an image
$im = imagecreatefromjpeg('sunset.jpg');
$x_val = imagesx($im);
$y_val = imagesy($im);
$black = imagecolorallocate($im, 0, 0, 0);
for ($i = 0; $i < $x_val; $i++) {
$color_index = imagecolorat($im, $i, $i);
$colourarray = imagecolorsforindex($im, $color_index);
if ($colourarray[0] != 170 && $colourarray[1] != 0 && $colourarray[2] != 0) {
$color_index = imagecolorat($im, $i, $i);
imagecolorset($im, $color_index, 0, 0, 0);
} else {
$color_index = imagecolorat($im, $i, $i);
imagecolorset($im, $color_index, 170, 0, 0);
}
}
imagejpeg($im);
imagedestroy($im);

Simple captcha php script not displaying text on image

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.

PHP GD for merging two icons

I am using PHP GD library to merge two icons into one. But in one of the cases the smaller icon goes into back and bigger icon overlaps it completely, I need the small icon to be on top.
Here is my code for merging two icons,
MergeIcons.php
$firstIcon = $_GET['icon1'];
$secondIcon = $_GET['icon2'];
$image = imagecreatefrompng($firstIcon);
$x1 = -1;
$y1 = -1;
$i = 0;
$xCords = array(); // Array to save non-transperent x cords
$yCords = array(); // Array to save non-transperent y cords
for($x=0;$x<16;$x++)
{
for($y=0;$y<16;$y++)
{
if (!transparent(imagecolorat($image, $x, $y)))
{
$xCords[$i] = $x;
$yCords[$i] = $y;
$i++;
}
}
}
$minX = min($xCords);
$minY = min($yCords);
$width = 16 - $minX;
$height = 16 - $minY;
$canvas = imagecreatetruecolor(16,16);
$col = imagecolorallocatealpha($canvas,0,0,0,127);
imagefilledrectangle($canvas,0,0,16,16,$col);
imagealphablending($canvas, true);
imagesavealpha($canvas, true);
imagefill($canvas, 0, 0, $col);
imagecopy($canvas, $image, 0, 0, $minX , $minY, $width, $height);
$dest = $canvas;
$src = imagecreatefrompng($secondIcon);
imagealphablending($dest, true);
imagesavealpha($dest, true);
$swidth = imagesx($src);
$sheight = imagesy($src);
imagecopy($dest, $src, 0,0,0,0,$swidth,$sheight);
header('Content-Type: image/png');
imagepng($dest);
imagedestroy($dest);
imagedestroy($src);
function transparent($pixelValue)
{
$alpha = ($pixelValue & 0x7F000000) >> 24;
$red = ($pixelValue & 0xFF0000) >> 16;
$green = ($pixelValue & 0x00FF00) >> 8;
$blue = ($pixelValue & 0x0000FF);
if($alpha == 127)
return true;
else
return false;
}
Here is how I call the mergeicons.php
echo '<li><img src="MergeIcons.php?icon1='.$secondIconPath.'&icon2='.$firstIconPath.'"/></li>';
In this case, second icon is a small icon and first icon is bigger icon, I want smaller icon on top of bigger icon ( assume its like "Bring it to Front ").
Is that possible?
"bring it front " - i think you want to put one image as a layer on the other
http://phpimageworkshop.com/

Generate random checkerboard image with a variety of colors in PHP

I have the following PHP method that generates new users a profile image when they first sign up, before they upload their own. All it does is just create them a brightly colored square - something to make the interface look a little more interesting when showing a list of users without profile photos.
How could I adapt this method so it created a checkerboard of random colors? Something like this: http://krazydad.com/bestiary/thumbs/random_pixels.jpg
public function generate_random_image($filename, $w = 200, $h = 200, $chosen_color = NULL) {
if(!$chosen_color) {
$color_options = Array("#6f0247", "#FF0569", "#FFF478", "#BAFFC0", "#27DB2D", "#380470", "#9D69D6");
$random = rand(0,sizeof($color_options));
$chosen_color = $color_options[$random];
}
$rgb = self::hex2rgb($chosen_color);
$image = imagecreatetruecolor($w, $h);
for($row = 1; $row <= $h; $row++) {
for($column = 1; $column <= $w; $column++) {
$color = imagecolorallocate ($image, $rgb[0] , $rgb[1], $rgb[2]);
imagesetpixel($image,$column - 1 , $row - 1, $color);
}
$row_count++;
}
$filename = APP_PATH.$filename;
imagepng($image, $filename);
return $chosen_color;
}
How about you just change
$color = imagecolorallocate ($image, $rgb[0] , $rgb[1], $rgb[2]);
to
$color = imagecolorallocate ($image, rand(0,255), rand(0,255), rand(0,255));
Then, each pixel will have it's own colour. Just draw to a small image, then scale by 200% or 300% (or some other arbitrary number) and you'll get nice, big chunky pixels like the image you linked.
While iterating through $rows and $columns you should increase step to desired pixel size and choose another color with each iteration.
example for pixel width = 20x20 :
$pixel = 20;
for($row = 0; $row <= $h / $pixel; $row++) {
for($column = 0; $column <= $w/ $pixel; $column++) {
$rgb = self::hex2rgb($color_options[rand(0,sizeof($color_options))]);
$color = imagecolorallocate ($image, $rgb[0] , $rgb[1], $rgb[2]);
imagefilledrectangle(
$image,
$column*$pixel,
$row*pixel,
$column*$pixel+$pixel,
$row*pixel+$pixel,
$color
);
}
}

Categories