Imagick setColor not working with php - php

I've tried setting all pixels to black. But it isn't working. I am getting the same image as original.
Here is my code:
$image = new Imagick(__DIR__."/image_new.jpg");
$i=0;
$j=0;
while ($i < 100)
{
$j=0;
while($j < 100)
{
$pixel = $image->getImagePixelColor($i, $j);
$pixel->setColor("#000000");
$j++;
}
$i++;
}
header("content-type:image/jpeg");
echo $image;
Image size is 100x100.
Any ideas?

The Imagick::getImagePixelColor will return an ImagickPixel object; which, would have copied data from the originating Imagick object. After altering the pixel's data/state, you would need to "sync" the pixel back to the image. To help with this process, a ImagickPixelIterator object has been provided -- see Imagick::getPixelIterator. Here's a quick example
$image = new Imagick(__DIR__."/image_new.jpg");
$pixel_iterator = $image->getPixelIterator();
foreach($pixel_iterator as $i => $pixels)
{
if( $i < 100 )
{
foreach($pixels as $j => $pixel)
{
if( $j < 100 )
{
$pixel->setColor("#000000");
}
}
}
$pixel_iterator->syncIterator();
}
header("content-type:image/jpeg");
echo $image;

Related

Star rating with half star support

I am running into a problem rendering a star rating and was hoping I can get some extra eyeballs on my problem. I have the normal rating working just fine with whole numbers but I am struggling to display the half star. For example I created a service that provides me with a rating 0-5 so I get a value like 2.5, 3 or 5 etc...
Before I go and create a switch case and create an svg for each variation I was hoping to get a little a pointer. Below is what I have currently, any tips would be greatly appreciated.
<?php
for ($i = 1; $i <= $totalRating; $i++) {
if($starRating < $i ) {
echo "<img src=\"/icons/star-empty.svg\">";
}
else {
echo "<img src=\"/icons/star.svg\">";
}
}
?>
Ideally I would like to add a condition at the end of the loop and check for the half and echo "";
There is probably an easier way to do it but this works, checks if $starRating is a float and then rounds it up and checks against $i to place the half star in the correct position.
<?php
$totalRating = 5;
$starRating = 2.5;
for ($i = 1; $i <= $totalRating; $i++) {
if($starRating < $i ) {
if(is_float($starRating) && (round($starRating) == $i)){
echo "<img src=\"/icons/star-half.svg\">";
}else{
echo "<img src=\"/icons/star-empty.svg\">";
}
}else {
echo "<img src=\"/icons/star.svg\">";
}
}
?>
You can verify if the value of $starRating is an integer, doing something like this (considering only half values):
<?php
for ($i = 1; $i <= $totalRating; $i++) {
if ($starRating < $i ) {
echo "<img src=\"/icons/star-empty.svg\">";
} elseif(is_int($starRating) === false) {
echo "<img src=\"/icons/star_half.svg\">";
} else {
echo "<img src=\"/icons/star.svg\">";
}
}
?>
If you want to show stars with a more precise value you can create images with the float values in the name, like "star-3.svg" (representing a .3 float value, and do something like this:
<?php
for ($i = 1; $i <= $totalRating; $i++) {
if ($starRating < $i ) {
echo "<img src=\"/icons/star-empty.svg\">";
} elseif(is_int($starRating) === false) {
echo "<img src=\"/icons/star-" . floatval($starRating)) . ".svg\">";
} else {
echo "<img src=\"/icons/star.svg\">";
}
}
?>
But in this case you need to take care to only receive float values with one number (2.2, 3.4, etc.).
I hope it helps...

Trying to create a grid map in an array returns a fatal memory error in php

I am working on a random RPG Map generator that get's inserted into the database for later retrieval. Basically the user will enter some minor details on the form and specify how many tiles of each terrain they need to have on the map. Then the tiles are randomly inserted into the map and database. I insert the tiles into an Array and then shuffle the results. I do a loop through the array and loop through and X & Y grid to insert the terrain data. But everytime I do that, I get a memory error: Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 32 bytes) This is my code:
$gridarray = array();
for ($jungle1 = 0; $jungle1 <= $jungle -1; $jungle1++) {
array_push($gridarray,"jungle");
}
for ($swamp1 = 0; $swamp1 <= $swamp -1; $swamp1++) {
array_push($gridarray,"swamp");
}
for ($cave1 = 0; $cave1 <= $cave -1; $cave1++) {
array_push($gridarray,"cave");
}
for ($mountain1 = 0; $mountain1 <= $mountain -1; $mountain1++) {
array_push($gridarray,"mountain");
}
for ($ocean1 = 0; $ocean1 <= $ocean -1; $ocean1++) {
array_push($gridarray,"ocean");
}
for ($volcanic1 = 0; $volcanic1 <= $volcanic -1; $volcanic1++) {
array_push($gridarray,"volcanic");
}
for ($desert1 = 0; $desert1 <= $desert -1; $desert1++) {
array_push($gridarray,"desert");
}
for ($dirt1 = 0; $dirt1 <= $dirt -1; $dirt1++) {
array_push($gridarray,"dirt");
}
for ($forest1 = 0; $forest1 <= $forest -1; $forest++) {
array_push($gridarray,"dirt");
}
for ($arctic1 = 0; $arctic1 <= $arctic -1; $arctic++) {
array_push($gridarray,"arctic");
}
for ($grass1 = 0; $grass1 <= $grass -1; $grass++) {
array_push($gridarray,"grass");
}
echo '<table cellspacing="0" cellpadding="0" border="0">';
$gridsquare = $xsize * $ysize;
$grid = 0;
shuffle($gridarray);
for ($x = 1; $x <= $xsize; $x++) {
echo '<tr>';
for ($y = 1; $y <= $ysize; $y++) {
$terrain = $gridarray[$grid];
$terrain_img = 'http://www.sw-bfs.com/images/grids/' . $terrain . '.png';
$query2 = " INSERT INTO terrain ( ent_id, ent_type, grid_img, grid_type, grid_exit_e, grid_exit_w, grid_exit_s, grid_exit_n, grid_exit_u, grid_exit_d, x, y) VALUES ( '$loc_id', 'terrain', '$terrain_img', '$terrain','1', '1', '1', '1', '0', '0', '$x', '$y') ";
$result2 = mysql_query($query2) or die(mysql_error());
echo '<td><img src="' . $terrain_img . '" title="' . $terrain . '"/></td>';
$grid++;
}
echo '</tr>';
}
echo "</table>";
It is telling me that the error is occurring on the line that reads like this:
array_push($gridarray,"arctic");
}
Obviously I am doing something wrong or at least I am not writing the code efficiently enough. Forgive me, I am still learning. Can someone provide some better assistance? Thank you in advance.
Never mind. This:
for ($arctic1 = 0; $arctic1 <= $arctic -1; $arctic++) {
array_push($gridarray,"arctic");
Is missing a 1 in $arctic++. Should be like this:
for ($arctic1 = 0; $arctic1 <= $arctic -1; $arctic1++) {
array_push($gridarray,"arctic");
Now works perfectly. Feel free to use my snippet above to create random maps for the database.

Fill the gradient colour in my custom shape polygon jpgraph

I am working with the jpgraph and creating radar chart.
Facing the issue with fill custom shape polygon with gradient colour.
I have function to fill a gradient colour polygon with a flat bottom and i want to fill the gradient colour in my custom shape polygon.
Can anyone help me? How can i do this?
Current Output:
Desired Output:
You can find the gradient class at here.
http://code.google.com/r/linksoftafrica-maison-george/source/browse/libs/jpgraph/jpgraph_gradient.php
// Fill a special case of a polygon with a flat bottom
// with a gradient. Can be used for filled line plots.
// Please note that this is NOT a generic gradient polygon fill
// routine. It assumes that the bottom is flat (like a drawing
// of a mountain)
function FilledFlatPolygon($pts,$from_color,$to_color) {
if( count($pts) == 0 ) return;
$maxy=$pts[1];
$miny=$pts[1];
$n = count($pts) ;
for( $i=0, $idx=0; $i < $n; $i += 2) {
$x = round($pts[$i]);
$y = round($pts[$i+1]);
$miny = min($miny,$y);
$maxy = max($maxy,$y);
}
$colors = array();
$this->GetColArray($from_color,$to_color,abs($maxy-$miny)+1,$colors,$this->numcolors);
for($i=$miny, $idx=0; $i <= $maxy; ++$i ) {
$colmap[$i] = $colors[$idx++];
}
$n = count($pts)/2 ;
$idx = 0 ;
while( $idx < $n-1 ) {
$p1 = array(round($pts[$idx*2]),round($pts[$idx*2+1]));
$p2 = array(round($pts[++$idx*2]),round($pts[$idx*2+1]));
// Find the largest rectangle we can fill
$y = max($p1[1],$p2[1]) ;
for($yy=$maxy; $yy > $y; --$yy) {
$this->img->current_color = $colmap[$yy];
$this->img->Line($p1[0],$yy,$p2[0]-1,$yy);
}
if( $p1[1] == $p2[1] ) continue;
// Fill the rest using lines (slow...)
$slope = ($p2[0]-$p1[0])/($p1[1]-$p2[1]);
$x1 = $p1[0];
$x2 = $p2[0]-1;
$start = $y;
if( $p1[1] > $p2[1] ) {
while( $y >= $p2[1] ) {
$x1=$slope*($start-$y)+$p1[0];
$this->img->current_color = $colmap[$y];
$this->img->Line($x1,$y,$x2,$y);
--$y;
}
}
else {
while( $y >= $p1[1] ) {
$x2=$p2[0]+$slope*($start-$y);
$this->img->current_color = $colmap[$y];
$this->img->Line($x1,$y,$x2,$y);
--$y;
}
}
}
}
It looks to me that your current code is not suitable for this task. You need code for Gouraud shaded triangles (3-sided polygons).
When you have code for that, you simply draw three triangles where on point of the triangle is in the center of the graph and two points are on the radar axles.
Unfortunately, I didn't find ready-made code for jpgraph.

array_slice page numbering

This script takes every image in a folder and shows it on a webpage. Is there a way to show like an simple page number like 1,2,3,4,5 every 10 images or so? everything I tried thus far is not working.
<?php
# To prevent browser error output
header('Content-Type: text/javascript; charset=UTF-8');
# Path to image folder
$imagefolder = 'img/';
# Show only these file types in the image folder
$imagetypes = '{*.jpg,*.JPG,*.JPEG,*.png,*.PNG,*.gif,*.GIF}';
# Add images to array
$images = glob($imagefolder.$imagetypes, GLOB_BRACE);
# Sort the images based on its 'last modified' time stamp
$sortedImages = array();
$count = count($images);
for ($i = 0; $i < $count; $i++) {
$sortedImages[date ('YmdHis', filemtime($images[$i])).$i] = $images[$i];
}
# Set to 'false' if you want the oldest images to appear first
$newest_images_first = true;
# Sort images in array
if($newest_images_first) {
krsort($sortedImages);
} else {
ksort($sortedImages);
}
# Generate the HTML output
writeHtml('<ul class="ins-imgs">');
foreach ($sortedImages as $image) {
# Get the name of the image, stripped from image folder path and file type extension
$name = 'Image name: '.substr($image,strlen($imagefolder),strpos($image, '.')-strlen($imagefolder));
# Get the 'last modified' time stamp, make it human readable
$last_modified = '(last modified: '.date('F d Y H:i:s', filemtime($image)).')';
# Begin adding
writeHtml('<li class="ins-imgs-li">');
writeHtml('<div class="ins-imgs-label">'.$name.' '.$last_modified.'</div>');
writeHtml('<div class="ins-imgs-img"><a name="'.$image.'" href="#'.$image.'">');
writeHtml('<img src="'.$image.'" alt="'. $name.'" title="'. $name.'">');
writeHtml('</a></div>');
writeHtml('</li>');
}
writeHtml('</ul>');
writeHtml('<link rel="stylesheet" type="text/css" href="ins-imgs.css">');
# Convert HTML to JS
function writeHtml($html) {
echo "document.write('".$html."');\n";
}
?>
Given that you said you are not a PHP master I'll show my solution and explain it step by step.
I hope you can find it helpful.
Here is the loop I use for pagination:
for($i = (($page-1)*$perPage); $i < min(($page*$perPage), $total); $i++) {
}
I'll gonna use this to create a new array with the elements 11-20, 21-30 and so on.
First of all I removed the .$i in your $sortedImages array's index (15th row of your code)
for ($i = 0; $i < $count; $i++) {
$sortedImages[date ('YmdHis', filemtime($images[$i]))] = $images[$i]; #15th Row
}
because it makes the index a bit messy (it is necessary for a next step).
Then I create a new array with 0 to N indexes which makes the code tidy (I do it to change your code as less as possible) and then I populate it with the elements of $sortedImages array.
$k = 0; # The new index
$newArray = array(); # The new array
foreach($sortedImages as $soImg) {
$newArray[$k] = $soImg;
$k++;
}
Finally the pagination's implementation:
$page = $_GET["page"];
$perPage = 3;
$total = $count;
for ($i = (($page-1)*$perPage); $i < min(($page*$perPage), $total); $i++) {
$newSortedImages[$i] = $newArray[$i];
}
Variables:
$page = $_GET["page"]; is the page number retrived from the url ($_GET[] is a superglobal array)
$perPage is the number of elements to show per page
$total = $count; is the number of $images array (13th line)
The loop:
$i = (($page-1)*$perPage) is the start of the loop, if the page is 1 the loop should start from 0 then the expression (($page-1)*$perPage) makes it work.
$i < min(($page*$perPage), $total) is the end of the loop, min() function finds the lowest value between its arguments, it is helpful when e.g. the last page contains 4 elements while 6 are expected.
Then you just need to change the array to loop through in 29th row of your code from $sortedImages to $newSortedImages.
For pagination controls use this:
$nextPage = $page + 1;
$prevPage = $page - 1;
Here is the new code implementation:
# To prevent browser error output
header('Content-Type: text/javascript; charset=UTF-8');
# Path to image folder
$imagefolder = 'img/';
# Show only these file types in the image folder
$imagetypes = '{*.jpg,*.JPG,*.JPEG,*.png,*.PNG,*.gif,*.GIF}';
# Add images to array
$images = glob($imagefolder.$imagetypes, GLOB_BRACE);
# Sort the images based on its 'last modified' time stamp
$sortedImages = array();
$count = count($images);
for ($i = 0; $i < $count; $i++) {
$sortedImages[date ('YmdHis', filemtime($images[$i])).$i] = $images[$i];
}
# Set to 'false' if you want the oldest images to appear first
$newest_images_first = true;
# Sort images in array
if($newest_images_first) {
krsort($sortedImages);
} else {
ksort($sortedImages);
}
# Now I give an index from 0 to N to the new array to make it work with pagination loop
$k = 0; # The new index
$newArray = array(); # The new array
foreach($sortedImages as $soImg) {
$newArray[$k] = $soImg;
$k++;
}
$page = $_GET["page"];
$perPage = 3;
$total = $count;
for ($i = (($page-1)*$perPage); $i < min(($page*$perPage), $total); $i++) {
$newSortedImages[$i] = $newArray[$i];
}
# Generate the HTML output
writeHtml('<ul class="ins-imgs">');
foreach ($newSortedImages as $image) {
# Get the name of the image, stripped from image folder path and file type extension
$name = 'Image name: '.substr($image,strlen($imagefolder),strpos($image, '.')-strlen($imagefolder));
# Get the 'last modified' time stamp, make it human readable
$last_modified = '(last modified: '.date('F d Y H:i:s', filemtime($image)).')';
# Begin adding
writeHtml('<li class="ins-imgs-li">');
writeHtml('<div class="ins-imgs-label">'.$name.' '.$last_modified.'</div>');
writeHtml('<div class="ins-imgs-img"><a name="'.$image.'" href="#'.$image.'">');
writeHtml('<img src="'.$image.'" alt="'. $name.'" title="'. $name.'">');
writeHtml('</a></div>');
writeHtml('</li>');
}
writeHtml('</ul>');
writeHtml('<link rel="stylesheet" type="text/css" href="ins-imgs.css">');
# Convert HTML to JS
function writeHtml($html) {
echo "document.write('".$html."');\n";
}
For page numbering you have to know the total of elements and divide it by $perPage elements, obviously the result must be an integer, so you'll gonna use ceil() function
From php.net
Returns the next highest integer value by rounding up value if necessary.
$pages = ceil($count / $perPage);
And then use this to display peges numbers:
for($i = 1; $i <= $pages; $i++) {
writeHtml('' . $i . ' ');
}
You don't need a database to implement simple pagination.
$currentpage = $_GET['p'];
for ($i = ($currentpage*$pageSize); $i<sortedImages as $image) {
// your HTML output here
}
for($i = 0; $i < $sortedImages/$pageSize; $i++){
writeHtml('<a href=/?p='.$i + 1.'/>');
}
That's just an example, probably won't work if you cut 'n paste. But there to give you a good idea of how it could be implemented.

php ProgressBar class displaying only 99% of completed jobs

I am using the ProgressBar class from the following link for displaying a progress bar for image downloads..
http://pastebin.com/KSxjC01r
I am using the following code..
echo 'Starting Image Download...<br />';
$p = new ProgressBar();
echo '<div style="width: 300px;">';
$p->render();
echo '</div>';
//progress bar
for ($i = 0; $i < ($size = 100); $i++) {
$p->setProgressBarProgress($i*100/$size);
usleep(1000000*0.01);
}
fetch_image("$item", "../cbimages/$img ");
echo "Downloaded $img <br />";
}
echo "Finished downloading images....";
Everything is working fine..But for each download it is displaying only 99.0% in progress bar. After completion too it displays as 99.0% . What is wrong the code above. Where am i going wrong. Help requested..
Update:
Resolved the issue by changing the following line in the class file:
From:
if ($percentDone == 100) {
print('document.getElementById("'.$this->pbid.'").style.display = "none";');
}
To:
if ($percentDone == 100) {
print('document.getElementById("'.$this->pbid.'").style.width = "'.$percentDone.'%";');
Your for loop currently only counts to 99 because you used < instead of <=.
Changing it to this should work:
<?php
for ($i = 0; $i <= ($size = 100); $i++) {
$p->setProgressBarProgress($i * 100 / $size);
usleep(1000000 * 0.01);
}
Your loop isn't quite right
you have this:
for ($i = 0; $i < ($size = 100); $i++) {
The rule is that i < 100 so, when i == 100 the loop is not run. Meaning it is never passed to setProgressBarProgress()
This will work:
for ($i = 0; $i <= ($size = 100); $i++) {
The loop will still run when i == 100

Categories