I am building a web application that will use the Amazon Product Advertising API. The problem is that the API returns images of different sizes and aspect ratios for each product. If I resize all images to a static width/height, then some of them look odd due to the change in ratio. The images will be laid out in rows of four each. I was thinking that I will only make the width of the images the same while keeping the aspect ratio the same and then having some sort of max threshold for the height just in case the API returns some oddly sized image.
But, I wanted to see if people here have ran into this before and what their thoughts on this design problem are?
What a co-incidence. I was facing a similar problem and this is how I've decided to move forward. It might not be the best solution, but it works for me.
First I get the original height and width of the image
list($width, $height) = getimagesize("path to image");
Then I find out the greatest common divisor for the two and store the width and height ratios in variables, such as $wr and $hr
Then check for image orientation is made (horizontal or vertical) by comparing $wr > $hr for horizontal orientation and $hr > $wr for vertical
If horizontal, I make sure the thumb size does not exceed a certain value, say 120px and make the height corresponding to 120px based on aspect ratio. The same is done if the orientation is vertical.
I came across the same problem trying to standardize logos. At first, I thought that I could choose a standard area and resize all the images to that area, but there are two problems with that strategy. First, you have to set limits for height and width, so sometimes you end up images with a smaller area because they are very wide or tall. Secondly, that might make your layout look ugly. In my case I have a header on top, an image and then text below. I realized that a very wide image would leave a big gap between the header and the text. Because of that, I needed a solution that would give preference to width. What I mean by that is that the image can change a lot in width without changing the height a lot. Different applications may have different requirements, but I think my solution allows for any situation such as a preference for height as well:
function width_to_height($width, $slope, $icpt){
if ($width == 0){
return FALSE;
}
return floor(($icpt + sqrt(pow($icpt, 2) + 4*$slope*pow($width, 2)))/(2*$width));
}
function ratio_to_height($ratio, $slope, $icpt){
if ($ratio == 0){
return FALSE;
}
$area = $ratio*$slope + $icpt;
return floor(sqrt($area/$ratio));
}
function calc_dims($width, $height, $max_w=168, $max_h=100){
$slope = 2500;
$icpt = 6000;
$ratio = $width/$height;
$max_ratio = $max_w/$this->width_to_height($max_w, $slope, $icpt);
if ($ratio > $max_ratio){
$ht = floor($max_w/$ratio);
return array('width' => $max_w, 'height' => $ht);
}
$ht = $this->ratio_to_height($ratio, $slope, $icpt);
if ($ht > $max_h){
$wd = floor($max_h*$ratio);
return array('width' => $wd, 'height' => $max_h);
}
$wd = floor($ht*$ratio);
return array('width' => $wd, 'height' => $ht);
}
The main function is calc_dims() which calls the other two functions. Since I almost always work with classes, these functions are called with the "this->" operator. If you don't use classes, you can simply delete the operator.
You can see that I hard-coded some variables. (In my real life application, these are called from a configuration file.) $max_w and $max_h are pretty self explanatory as the maximum height and width of the images. However $slope and $icpt may be a little more difficult to understand. As you can see in the ratio_to_height() function, $slope and $icpt (intercept) are components in a linear relationship between area and the aspect ratio of the image.
You can use the values that I provide ($slope = 2500; $icpt = 6000), or you can calculate your own. I thought of automating the process a little more, but since the parameters are highly subjective, it didn't seem very practical. In order to calculate them, it's necessary to define areas for two different instances of the aspect ratios, where the ratio is $width/$height. For example, when the ratio is 1 ($width = $height), you might want the area to be 8000 pixels^2, and when the ratio is 2 ($width = 2*$height) the area could be 12000 pixels^2. With these values we have:
$A1 = 8000;
$A2 = 12000;
$r1 = 1;
$r2 = 2;
You can calculate slope and intercept as follows:
$slope = ($A2 - $A1)/($r2 - $r1);
$icpt = $A1 - $slope*$r1;
Related
In PDFlib we can define the boxsize for an image using boxsize={65 65} (for example). Since we need two values, is there any way to set the height value and leave the width value to be dynamically? In my use case I want to add all images with a set height of 65, but the images can be different in their width so the boxsize should dynamically update according to the image.
I also tried using scale in the option list, but that makes no sense, since the height than also changes according to the image.
Currently I load all images I want to place using a for loop, which looks like this:
foreach ($awardImages as $awardImage) {
$image = $p->load_image('auto', $awardImage, '');
if (0 == $image) {
echo "Couldn't load $image: ".$p->get_errmsg();
exit(1);
}
if ($x > (565 - 70)) {
$y = $y - 65;
$x = $elementStartLeft + 2;
}
// $buf = "scale=1 position={left center} matchbox={name=awardimage}";
$buf = 'boxsize={65 65} fitmethod=auto showborder position={left center} matchbox={name=awardimage}';
$p->fit_image($image, $x, $y, $buf);
++$awardNo;
$awardX2 = $p->info_matchbox('awardimage', $awardNo, 'x2');
$x = $awardX2 + 5;
}
I think the easiest way is simply to specify the height or width a large value. This could look like this, for example
$p->fit_image($image, 0.0, 0.0, "boxsize {65 1000} fitmethod=meet position={left center}");
$p->fit_image($image, 0, 300, "boxsize {1000 65} fitmethod=meet position={left center}");
It could make sense to set the large width or height (here 1000) to a value that might prevent the content from protruding over the page.
The value here (1000) would suffice for images with a ratio of 1:15 at the value 65.
In general, you can also use info_image() to determine the height and width of the image and thus determine the aspect ratio. Based on this, you could also determine and specify the box size yourself.
First question, so sorry if I do something wrong!
My issue is, I have a product catalog, which displays up to 18 thumbnails, each approx 6kb, in a product catalog. Each of the thumbnails calls a script get_db_image which searches for and returns the image relating to the product. Simple, so far. The issue only arises when approx 3 or 4 requests are made at the same time for a product catalog page, each user is expecting 18 thumbnails and details to be returned, but when they all do it at the same time I get out of memory errors and sometimes the server crashes. I've stripped down the code that retrieves and displays the image, and the hosting people have raised the memory limit to 256M, but it's all to no avail. As far as I can tell I'm destroying the images I've created and the virtual memory goes back to zero split seconds after the requests are made, but at the peak all the memory is being utilised, hence the crashes, so the only thing I can think off doing is getting, displaying and destroying each image before I start the next one, but I don't know how to go about that, but maybe there is a better solution? Please help, pulling my hair out and I don't have a lot to waste!
// executes the query searching for the image
$res = execPDORetRes($query, $vars);
// if there is no image, load a default
if(sizeof($res) == 0)
{
$query_parts = explode(" ", $query);
$query = "select * from ".$query_parts[3]." where id = :id";
$vars = array(':id-int' => 1);
$res = execPDORetRes($query, $vars);
}
$data = $res[0];
// create the image from the DB
$img = imagecreatefromstring($data[$name]);
$type = "image/pjpeg";
Header( "Content-type: image/pjpeg");
$width = imagesx($img);
$height = imagesy($img);
// if the image is too big
if($size_w != $width || $size_h != $height)
{
// set widths and heights
if ($width <= $size_w)
{
$new_w = $width;
$new_h = $height;
}
else
{
$new_w = $size_w;
$new_h = $size_h;
}
// create a new image of the specified width and height
$new_img = imagecreatetruecolor($new_w,$new_h);
// resize the original
imagecopyresized($new_img,$img,0,0,0,0,$new_w,$new_h,$width,$height);
// determine image type and send it to the client
imagejpeg($new_img,"","80");
// clear the image from memory
imagedestroy($new_img);
imagedestroy($img);
unset($width, $height, $new_h, $new_w, $new_img, $img);
}
else
{
// if the image is smaller than or the right size
// determine image type and send it to the client
imagejpeg($img,"","80");
// clear the image from memory
imagedestroy($img);
unset($width, $height, $img);
}
ob_flush();
Thanks for the help.
I think you should generate your thumbnails in advance if you want to this it this way.
This means you should have your normal product images under e.g. "public/images/products/main" and then your thumbs under "public/images/products/thumbs" and then store in the database your paths to the product images and your thumbs.
This approach is better then creating them on the fly.
Otherwise you could just scale them down with css, if bandwidth is not a problem, but I guess it is.
You can even keep your thumbs script and check in the db if a thumbnail exists, if it does not, call your script: generate thumb, save thumb, update db. The next time a user comes and you need to display this thumbnail, it will already be there.
256 megabytes should be plenty. Nothing in your code looks bad and you're even using unset. I recommend debugging with Xdebug and WinCacheGrind, they can produce in-depth logs...
I've come across something that I'd like to accomplish without using any frameworks or other graphing tools that are out there on the internet, which is graphing trigonometric functions using only PHP and if needed, SQL. I'm aware of the GD library, but none of the functions were helpful. I wrote a small script, although it doesn't really work either. My goal is to do the following:
Allow for trig function name, starting value and end value to be added as parameters.
Check whether a function is cos, tan or sin.
Loop through all values given starting and end values in degrees, and convert to radians.
"Add" all values to an array, if needed, and graph the function given the points.
After looping through all the values of the function, what needs to be done to graph the function? Do the values have to be in a seperate array? What functions need to be used for graphing?
<?php
header("Content-type: image/png");
function graphFunction($function, $startDegree, $endDegree)
{
$functionList = array('cos', 'sin', 'tan');
if (strtolower($function) == 'cos')
{
$cosValues = array();
for ($c = $startDegree; $c < $endDegree; $c++)
{
array_push($cosValues, cos(deg2rad($c)));
$graph = imagecreatetruecolor(500,250);
$col_poly = imagecolorallocate($graph, 255, 255, 255);
imagepolygon($graph, [the cosine values] , 34, $col_poly);
imagepng($graph);
imagedestroy($graph);
}
}
}
echo graphFunction('cos', 0, 360);
?>
This is supposed to be a sample function, so no need to be criticizing the useless control structure as there are ways to store many things in a database, whatsoever. I hope for some feedback, and hopefully it is possible with PHP.
You can do this with PHP. I just tried with the following inside your if statement, and it seems to work.
$height = 250;
$offset = $height/2;
$graph = imagecreatetruecolor(500, $height);
$col_poly = imagecolorallocate($graph, 255, 255, 255);
for ($c = $startDegree; $c < $endDegree; $c++)
{
$this_x = $c;
$next_x = $this_x + 1;
$this_y = cos(deg2rad($this_x)) * $offset + $offset;
$next_y = cos(deg2rad($next_x)) * $offset + $offset;
imageline($graph, $this_x, $this_y, $next_x, $next_y, $col_poly);
}
imagepng($graph);
imagedestroy($graph);
So what I did was define a graph height, because the y coordinates of the points in the graph need to be set to they fit inside. Then inside the for loop I just take the current degree value as my x coordinate, calculate the y coordinate for it, then the same for the next degree value, and then I draw a line between those two points.
It's a bit cludgy, so I'm sure you'll wan to clean it up a bit. Also, you need to think about the width of your graph as well (what I've posted here will stop at 500 px wide, so if you want to graph a wider range, or if you want to plot 300 - 600 degrees it will just start halfway into your graphing area.
You also defined your image and colours inside the for loop, which I changed so you're not recreating an image resource each step and losing all previous data.
Anyway, it was just an example function, right? But using your degree values as x coordinates (adjusted to your graphing area sise), computing y coordinates based on the chosen function, the degree values and your graphing area size and then drawing lines between the points should work.
I am trying to replicate the functionality that Dribbble.com does with detecting the predominant colors in an Image. In the image below you can see a screenshot from Dribbble.com that shows the 8 predominant colors in the image to the left. Here is the actual page in the image http://dribbble.com/shots/528033-Fresh-Easy?list=following
I need to be able to do this in PHP, once I get the colors I need I will save them to a database so the processing does not need to be run on every page load.
After some research on how to get these colors out of an Image, some people said you simply examine an image pixel by pixel and then save the colors that occur the most. Other say there is more to it and that getting the colors that exist the most frequent won't give the desired affect. They say you need to Quantize the image/colors (I am lost at this point).
In the image below the Dribble shot below is a Javascript library that does the same thing, that page can be viewed here http://lokeshdhakar.com/projects/color-thief/
Viewing the source of that page I can see there is a Javascript file named quantize.js and the results are really good. So I am hoping to be able to do what that Javascript library does but with PHP and GD/ImageMagick
I had found this function that will return the colors and count in an Image with PHP but the results are different from the Javascript version above and the Dribble results
/**
* Returns the colors of the image in an array, ordered in descending order, where the keys are the colors, and the values are the count of the color.
*
* #return array
*/
function Get_Color()
{
if (isset($this->image))
{
$PREVIEW_WIDTH = 150; //WE HAVE TO RESIZE THE IMAGE, BECAUSE WE ONLY NEED THE MOST SIGNIFICANT COLORS.
$PREVIEW_HEIGHT = 150;
$size = GetImageSize($this->image);
$scale=1;
if ($size[0]>0)
$scale = min($PREVIEW_WIDTH/$size[0], $PREVIEW_HEIGHT/$size[1]);
if ($scale < 1)
{
$width = floor($scale*$size[0]);
$height = floor($scale*$size[1]);
}
else
{
$width = $size[0];
$height = $size[1];
}
$image_resized = imagecreatetruecolor($width, $height);
if ($size[2]==1)
$image_orig=imagecreatefromgif($this->image);
if ($size[2]==2)
$image_orig=imagecreatefromjpeg($this->image);
if ($size[2]==3)
$image_orig=imagecreatefrompng($this->image);
imagecopyresampled($image_resized, $image_orig, 0, 0, 0, 0, $width, $height, $size[0], $size[1]); //WE NEED NEAREST NEIGHBOR RESIZING, BECAUSE IT DOESN'T ALTER THE COLORS
$im = $image_resized;
$imgWidth = imagesx($im);
$imgHeight = imagesy($im);
for ($y=0; $y < $imgHeight; $y++)
{
for ($x=0; $x < $imgWidth; $x++)
{
$index = imagecolorat($im,$x,$y);
$Colors = imagecolorsforindex($im,$index);
$Colors['red']=intval((($Colors['red'])+15)/32)*32; //ROUND THE COLORS, TO REDUCE THE NUMBER OF COLORS, SO THE WON'T BE ANY NEARLY DUPLICATE COLORS!
$Colors['green']=intval((($Colors['green'])+15)/32)*32;
$Colors['blue']=intval((($Colors['blue'])+15)/32)*32;
if ($Colors['red']>=256)
$Colors['red']=240;
if ($Colors['green']>=256)
$Colors['green']=240;
if ($Colors['blue']>=256)
$Colors['blue']=240;
$hexarray[]=substr("0".dechex($Colors['red']),-2).substr("0".dechex($Colors['green']),-2).substr("0".dechex($Colors['blue']),-2);
}
}
$hexarray=array_count_values($hexarray);
natsort($hexarray);
$hexarray=array_reverse($hexarray,true);
return $hexarray;
}
else die("You must enter a filename! (\$image parameter)");
}
So I am asking if anyone knows how I can do such a task with PHP? Possibly something exist already that you know of or any tips to put me a step closer to doing this would be appreciated
Here's exactly what you're looking for in PHP: https://github.com/thephpleague/color-extractor
Example :
use League\ColorExtractor\Palette;
$palette = Palette::fromFilename('some/image.png');
$topEightColors = $palette->getMostUsedColors(8);
This is my simple method to get the main color of an image
$image=imagecreatefromjpeg('image.jpg');
$thumb=imagecreatetruecolor(1,1);
imagecopyresampled($thumb,$image,0,0,0,0,1,1,imagesx($image),imagesy($image));
$mainColor=strtoupper(dechex(imagecolorat($thumb,0,0)));
echo $mainColor;
You need to scale down the picture and you will get the main colors of the picture. If you need 4 colors in the pallet, scale it down to about 8x8, 6 colors to about 12x8 and so on...
imagecopyresized for scaled down image then check every pixels and store them in array imagecolorat($image,px,py)
Try this out
<?php
// EXAMPLE PICTURE
$url='https://www.nordoff-robbins.org.uk/sites/default/files/google.jpg';
//var_dump(getColorPallet($url));
echoColors(getColorPallet($url));
function echoColors($pallet){ // OUTPUT COLORSBAR
foreach ($pallet as $key=>$val)
echo '<div style="display:inline-block;width:50px;height:20px;background:#'.$val.'"> </div>';
}
function getColorPallet($imageURL, $palletSize=[16,8]){ // GET PALLET FROM IMAGE PLAY WITH INPUT PALLET SIZE
// SIMPLE CHECK INPUT VALUES
if(!$imageURL) return false;
// IN THIS EXEMPLE WE CREATE PALLET FROM JPG IMAGE
$img = imagecreatefromjpeg($imageURL);
// SCALE DOWN IMAGE
$imgSizes=getimagesize($imageURL);
$resizedImg=imagecreatetruecolor($palletSize[0],$palletSize[1]);
imagecopyresized($resizedImg, $img , 0, 0 , 0, 0, $palletSize[0], $palletSize[1], $imgSizes[0], $imgSizes[1]);
imagedestroy($img);
//CHECK IMAGE
/*header("Content-type: image/png");
imagepng($resizedImg);
die();*/
//GET COLORS IN ARRAY
$colors=[];
for($i=0;$i<$palletSize[1];$i++)
for($j=0;$j<$palletSize[0];$j++)
$colors[]=dechex(imagecolorat($resizedImg,$j,$i));
imagedestroy($resizedImg);
//REMOVE DUPLICATES
$colors= array_unique($colors);
return $colors;
}
?>
Works perfect for me.
The page you linked to has a link to the source code on GitHub so if you want to know exactly how they are doing you could replicate their source in PHP.
The big difference between how they are doing it and how you are doing it, is that they are using clustering to find the color. Instead of rounding the color when they store it, they are storing all of the raw colors in an array. Then they loop through this array until they find a cluster that has the highest ratio of points in the cluster to number of colors in the cluster. The center point of this is the most common color. The palette is then defined by the next highest sets of clusters, with some logic to prevent near complete overlap of the clusters.
Try this: http://www.coolphptools.com/color_extract
Works with JPEG and PNG.
And best!: no hustle with composer, just require_once
require_once 'colorextract/colors.inc.php';
$ex=new GetMostCommonColors();
$num_results=20;
$reduce_brightness=1;
$reduce_gradients=1;
$delta=24;
$colors=$ex->Get_Color( 'image.png', $num_results, $reduce_brightness, $reduce_gradients, $delta);
print_r($colors);
give you something like this:
Array (
[3060a8] => 0.55827380952381
[f0a848] => 0.19791666666667
[000000] => 0.069642857142857
[483018] => 0.02047619047619
[786018] => 0.01827380952381
[183060] => 0.01797619047619
[4878a8] => 0.016011904761905
[181800] => 0.015119047619048
[a87830] => 0.014345238095238
[a8c0d8] => 0.011904761904762
[6090c0] => 0.01172619047619
[d89030] => 0.011011904761905
[90a8d8] => 0.0071428571428571
[ffffff] => 0.0070238095238095
[604830] => 0.006547619047619
[f0f0f0] => 0.0063095238095238
[d8d8f0] => 0.005297619047619
[c0d8d8] => 0.0044047619047619
[f0f0ff] => 0.00041666666666667
[181830] => 0.00011904761904762 )
I tried it with different images and it seems reliable.
The idea of getting the predominant colors of the image is a bit tricky, because for example the most frequent pixel color could be so widely scattered in the image that it is not perceived as a predominant color at all.
I think an algorithm like Color coherence vector will be good enough to overcome this issue, because it clusters the colors into coherent and incoherent (which is quite intuitive), and then you can use them to discard those false positive predominant colors.
I see it is an easy algorithm to implement, this tutorial Image Retrieval: Color Coherence Vector describes describes its steps with examples of how it works and there is even a matlab implementation mentioned at the end of it.
I have a Unix bash shell script with ImageMagick called dominantcolor that may do what you want. See my scripts web site at http://www.fmwconcepts.com/imagemagick/index.php. You an run it from PHP exec(). See my pointers for use on my home page.
Input:
dominantcolor -n 6 -p all -s save plate.png
count,hexcolor
586,#5ECADC
520,#AFA85D
469,#3C3126
462,#B9C8BB
258,#488A70
205,#B06928
The -n 6 is the desired number of colors in the color quantization. The -p all means print all counts and colors for the resulting 6 colors. The -s save indictates to save a swatch image.
Colors below are shown with the dominant color on the left and decreasing count colors towards the right according to the list above.
I have a table with 150x150 cells which each have a colored background and a small image/symbol in them. Additionally each cell can have zero or more of it's borders set also. The user can change and add borders and change the cell color and cell. This all works pretty well using jquery and it is just a plain html table.
At the end of the user experience I am making a pdf of this table for them to download. This is a big job and takes a while, which is not my main concern now. jQuery gathers the table data in an array and sends it to php to recreate it as an image using the gd library.
So for each cell I was drawing a rectangle of the correct color on a large image, loading the symbol image and resampling it on to the large image, drawing the borders and imagedestroy the symbol image, it worked but took 1 minute. I changed my strategy to make a small colored rectangke impose the image on it and cache it in an array to be quickly used again. That sped my time up and brought it down to 30ish seconds, but now I am exhausting memory.
I am breaking the table down into 50 cell blocks so each fits on a page, each block is made into an image and saved to disk, the next is made and saved, etc. Each time the gd image is destroyed. Then all the blocks are inserted into the pdf.
So after all that, my question is how do I figure out where the memory is being used so I can try to free it up? I have posted the main function I think is causing the issue below. In my test there are up to 30 different symbols/colors images that are 25pxX25px, these are the images that are cached in an array.
I hope I have provided enough info and my problem is clear enough.
Thank you for your time,
Todd
//make one "block" of stitches returns image file name.
//function makeStitchChartBlock($img, $startX, $startY, $endX, $endY, $caption, $brand){
function makeStitchChartBlock($stitchChartArray, $startX, $startY, $endX, $endY, $caption, $brand,$blockNumber){
global $threadColours;
$stitchCache=array();
$saveTo = 'result'.$blockNumber.'.jpeg';
// calculate size of block
$numRows=($endY-$startY);
$numColumns=($endX-$startX);
$heightOfBlock = $numRows*SYMBOL_SIZE; //in pixels --- used to determine size of image to make for block
$widthOfBlock = $numColumns*SYMBOL_SIZE; //in pixels
//----plus any extra for captions grid lines
$heightOfBlock += (($endY-$startY)+1); //each stitch has a grid line before it and the last one also has on after it
$widthOfBlock += (($endX-$startX)+1);
// create image size of block to put stitches in
$newBlockImage = imagecreatetruecolor($widthOfBlock,$heightOfBlock);
$backStitchColor = imagecolorallocate($newBlockImage, 0, 0, 0);
// insert caption????
//draw grid lines
//$newBlockImage = addGridToImage($newBlockImage);
//keep track of where to start next cell top left
$blockX=0;
$blockY=0;
for($y = $startY; $y < $endY; $y++){ //for each pixel in height, move down 1 "row" each iteration
//echo "<tr>";
for($x = $startX; $x < $endX; $x++){ // "draws" a row (for each y pixel)
//rgb(75, 90, 60)
//x and y are column and row #'s
list($r, $g, $b) = getRGBs($stitchChartArray[$y][$x][0]); //get the rgb values for the cell
$stitchColor = imagecolorallocate($newBlockImage, $r, $g, $b);
//calculate x & y start positons
$stitchStartX=($blockX*SYMBOL_SIZE)+$blockX+1; //account for each previous stitch and the grid line, then add one for new grid line
$stitchStartY=($blockY*SYMBOL_SIZE)+$blockY+1;
$stitchEndX=$stitchStartX+(SYMBOL_SIZE);
$stitchEndY=$stitchStartY+(SYMBOL_SIZE);
/* make a symbol cell image with/without color and save it in the cache */
if(!isset($stitchCache[$r][$g][$b]))
{
//create new image
$stitchCache[$r][$g][$b] = imagecreatetruecolor(SYMBOL_SIZE,SYMBOL_SIZE);
$stitchCacheColor = imagecolorallocate($stitchCache[$r][$g][$b], $r, $g, $b);
//draw colored rectangle
imagefilledrectangle($stitchCache[$r][$g][$b], 0, 0, SYMBOL_SIZE-1, SYMBOL_SIZE-1, $stitchCacheColor);
//add the symbol
$symbolFile=$stitchChartArray[$y][$x][1];
if($symbolFile){
$symbolImage = imagecreatefrompng($symbolFile);
imagecopyresampled ($stitchCache[$r][$g][$b],$symbolImage,0,0,0,0,SYMBOL_SIZE-1,SYMBOL_SIZE-1,imagesx($symbolImage), imagesy($symbolImage) );
imagedestroy($symbolImage);
}
}
//add image from cache to the block image
imagecopyresampled ($newBlockImage,$stitchCache[$r][$g][$b],$stitchStartX, $stitchStartY,0,0,SYMBOL_SIZE,SYMBOL_SIZE,SYMBOL_SIZE,SYMBOL_SIZE);
//add the backstitch lines(borders)
if($stitchChartArray[$y][$x][2]>1) //top
{
imagefilledrectangle($newBlockImage, $stitchStartX, $stitchStartY, $stitchEndX, $stitchStartY+1, $backStitchColor);
}
if($stitchChartArray[$y][$x][3]>1) //right
{
imagefilledrectangle($newBlockImage, $stitchEndX-1, $stitchStartY, $stitchEndX, $stitchEndY, $backStitchColor);
}
if($stitchChartArray[$y][$x][4]>1) //bottom
{
imagefilledrectangle($newBlockImage, $stitchStartX, $stitchEndY-1, $stitchEndX, $stitchEndY, $backStitchColor);
}
if($stitchChartArray[$y][$x][5]>1) //left
{
imagefilledrectangle($newBlockImage, $stitchStartX, $stitchStartY, $stitchStartX+1, $stitchEndY, $backStitchColor);
}
//advance x position
$blockX++;
}
//advance y position
//reset x
$blockX=0;
$blockY++;
}
imagejpeg($newBlockImage, $saveTo);
imagedestroy($newBlockImage);
//dump stitch cache
foreach($stitchCache as $r)
{
foreach($r as $g)
{
foreach($g as $b=>$data)
{
imagedestroy($data);
}
}
}
return $saveTo;
}
I would start (if you haven't already) by getting a good IDE and a debugger as these will be invaluable tools. In this instance you may be able to use a profiler to work out where the memory is being used. Failing that some good ole' manual debugging code, say
$memory = memory_get_usage();
as the first line inside your inner loop. Then when you step through using the debugger you'll be able to see where the memory is ramping up.
btw, using global variables is generally not a good idea. You might want to pass in $threadColours as a parameter or look at other ways of getting that data into the function.