Can I improve this code?

Soldato
Joined
18 Apr 2004
Posts
2,613
Location
London
Ok so I have a bit of PHP code which I use to generate my signature only when there are new images on my flickr profile and its fast because it caches the image until its actually needed but I was wondering if their is a way to make it quicker at all?

<?php

// Set headers + turn off error reporting
header('Content-type: image/jpeg');
header("Location: image.jpg");
error_reporting(0);

// Set configure location for the build.txt file
$location = "/";
$buildfile = $location . "build.txt";

// This is the add image function
function addImage($source, $destination, $offset) {

// Create a temporary image
$temp = imagecreatefromjpeg($source);

// Calculate image offset and 5px gap
$woffset = ((75 + 5) * $offset);

// Resample image into place
imagecopyresampled($destination, $temp, $woffset, 0, 0, 0, 75, 75, 75, 75);

// Destroy temp image
imagedestroy($temp);
}

// Get rss file
$xmldata = file_get_contents('http://www.flickr.com/services/feeds/photos_public.gne?id=62834984@N00&format=rss_200');

// Because PHP doesnt support flickrs semicolons, simply find and replace them
$xmldata = str_replace('media:thumbnail', 'mediathumbnail', $xmldata);

// Parse xml
$xml = simplexml_load_string($xmldata);

// Open build.txt file
$file = fopen($buildfile, 'r+');
$old = fread($file, filesize($buildfile));

// Read rss build date
$new = $xml->channel->lastBuildDate;

// Compare or if force option set then force a regeneration
if (trim($new) != trim($old) OR $_REQUEST['force']) {

// Save rss build to build.txt
ftruncate($file, 0);
fwrite($file, $new);

// Create image
$image = imagecreatetruecolor(395, 75);

// Define colours, (ocuk is 28,87,128 RGB)
$colour = imagecolorallocate($image, 28, 87, 128);
$white = imagecolorallocate($image, 255, 255, 255);

// Fill image background
imagefill($image, 0, 0, $colour);

// Add images (its 4 because it goes 0, 1, 2, 3, 4 not 1, 2, 3, 4, 5 as you might expect)
for ($i=0; $i <= 4; $i++) {
addImage($xml->channel->item[$i]->mediathumbnail['url'], $image, $i);
}

// Save image out
imagejpeg($image, 'image.jpg', 90);

// Destroy image
imagedestroy($image);

}

?>

Also the PHP forum tag still doesn't work.
 
Also the PHP forum tag still doesn't work.
PHP:
<?php

// Set headers + turn off error reporting
header('Content-type: image/jpeg');
header("Location: image.jpg");
error_reporting(0);

// Set configure location for the build.txt file
$location = "/";
$buildfile = $location . "build.txt";

// This is the add image function
function addImage($source, $destination, $offset) {

// Create a temporary image
$temp = imagecreatefromjpeg($source);

// Calculate image offset and 5px gap
$woffset = ((75 + 5) * $offset);

// Resample image into place
imagecopyresampled($destination, $temp, $woffset, 0, 0, 0, 75, 75, 75, 75);

// Destroy temp image
imagedestroy($temp);
}

// Get rss file
$xmldata = file_get_contents('http://www.flickr.com/services/feeds/photos_public.gne?id=62834984@N00&format=rss_200') ;

// Because PHP doesnt support flickrs semicolons, simply find and replace them
$xmldata = str_replace('media:thumbnail', 'mediathumbnail', $xmldata);

// Parse xml
$xml = simplexml_load_string($xmldata);

// Open build.txt file
$file = fopen($buildfile, 'r+');
$old = fread($file, filesize($buildfile));

// Read rss build date
$new = $xml->channel->lastBuildDate;

// Compare or if force option set then force a regeneration
if (trim($new) != trim($old) OR $_REQUEST['force']) {

// Save rss build to build.txt
ftruncate($file, 0);
fwrite($file, $new);

// Create image
$image = imagecreatetruecolor(395, 75);

// Define colours, (ocuk is 28,87,128 RGB)
$colour = imagecolorallocate($image, 28, 87, 128);
$white = imagecolorallocate($image, 255, 255, 255);

// Fill image background
imagefill($image, 0, 0, $colour);

// Add images (its 4 because it goes 0, 1, 2, 3, 4 not 1, 2, 3, 4, 5 as you might expect)
for ($i=0; $i <= 4; $i++) {
addImage($xml->channel->item[$i]->mediathumbnail['url'], $image, $i);
}

// Save image out
imagejpeg($image, 'image.jpg', 90);

// Destroy image
imagedestroy($image);

}

?>
What doesn't work about it? That's a legitimate question as I don't know how it's supposed to behave except for what I'm seeing it do.
 
The OP used QUOTE and not PHP

<?php

// Set headers + turn off error reporting
header('Content-type: image/jpeg');
header("Location: image.jpg");
error_reporting(0);
?>
instead of

PHP:
                              <?php
    
    // Set headers + turn off error reporting
    header('Content-type: image/jpeg');
    header("Location: image.jpg");
    error_reporting(0);
?>

Although its still got the dark blue background. Which isn't terribly helpful :p
 
your script is generating the image on the fly everytime it runs. you haven't got caching enabled at all i'm afraid. this is creating un-necessary cpu load on your server and on flickr - it's reading the xml file and fetching the images with every hit..... :p

use a combination of file_exists and filemtime - if the file doesn't exist or it's too old (using 6 hours = 21600 seconds in this example), then we create a new file.

edited: to include force option for update

Code:
<?php
$filename = 'image.jpg';
if(($_GET['force'] == 'yes') || (!file_exists($filename)) || (time()-filemtime($filename) > 21600)) {
	function addImage($source, $destination, $offset) {
		$temp = imagecreatefromjpeg($source);
		$woffset = ((75 + 5) * $offset);
		imagecopyresampled($destination, $temp, $woffset, 0, 0, 0, 75, 75, 75, 75);
		imagedestroy($temp);
	}
	$xmldata = file_get_contents('http://www.flickr.com/services/feeds/photos_public.gne?id=62834984@N00&format=rss_200') ;
	$xmldata = str_replace('media:thumbnail', 'mediathumbnail', $xmldata);
	$xml = simplexml_load_string($xmldata);
	$image = imagecreatetruecolor(395, 75);
	$colour = imagecolorallocate($image, 28, 87, 128);
	$white = imagecolorallocate($image, 255, 255, 255);
	imagefill($image, 0, 0, $colour);
	for ($i=0; $i <= 4; $i++) {
		addImage($xml->channel->item[$i]->mediathumbnail['url'], $image, $i);
	}
	imagejpeg($image, $filename, 90);
	imagedestroy($image);
}
header('Content-type: image/jpeg');
readfile($filename);
?>
 
Last edited:
your script is generating the image on the fly everytime it runs. you haven't got caching enabled at all i'm afraid. this is creating un-necessary cpu load on your server and on flickr - it's reading the xml file and fetching the images with every hit..... :p

use a combination of file_exists and filemtime - if the file doesn't exist or it's too old (using 6 hours = 21600 seconds in this example), then we create a new file.

edited: to include force option for update

Code:
<?php
$filename = 'image.jpg';
if(($_GET['force'] == 'yes') || (!file_exists($filename)) || (time()-filemtime($filename) > 21600)) {
	function addImage($source, $destination, $offset) {
		$temp = imagecreatefromjpeg($source);
		$woffset = ((75 + 5) * $offset);
		imagecopyresampled($destination, $temp, $woffset, 0, 0, 0, 75, 75, 75, 75);
		imagedestroy($temp);
	}
	$xmldata = file_get_contents('http://www.flickr.com/services/feeds/photos_public.gne?id=62834984@N00&format=rss_200') ;
	$xmldata = str_replace('media:thumbnail', 'mediathumbnail', $xmldata);
	$xml = simplexml_load_string($xmldata);
	$image = imagecreatetruecolor(395, 75);
	$colour = imagecolorallocate($image, 28, 87, 128);
	$white = imagecolorallocate($image, 255, 255, 255);
	imagefill($image, 0, 0, $colour);
	for ($i=0; $i <= 4; $i++) {
		addImage($xml->channel->item[$i]->mediathumbnail['url'], $image, $i);
	}
	imagejpeg($image, $filename, 90);
	imagedestroy($image);
}
header('Content-type: image/jpeg');
readfile($filename);
?>

Yeah I that is more efficient, I had it checking the build file against the xml so that it only generated an image when the rss feed had been rebuilt by flickr. However your code does this only once every 6 hrs which is good enough, and I can always force it any way. Thanks! if anyone else has any suggestions to this new code let me know!
 
I had it checking the build file against the xml so that it only generated an image when the rss feed had been rebuilt by flickr.

did that work for you then? because i couldn't get that working. it wasn't creating a text file for me when testing? besides it's still inefficient because you were (intending on) querying flickr on every hit just to compare values so that wasn't ideal anyway. i think a time based solution is better. :)

as for another idea, how about creating 75x75 samples of all images on your server and have your script generate a random patchwork each time? :cool:
 
did that work for you then? because i couldn't get that working. it wasn't creating a text file for me when testing? besides it's still inefficient because you were (intending on) querying flickr on every hit just to compare values so that wasn't ideal anyway. i think a time based solution is better. :)

as for another idea, how about creating 75x75 samples of all images on your server and have your script generate a random patchwork each time? :cool:

You have to give it a full path I think, i.e. you would have been telling it to go to /build.txt because thats what I put in to post (so you guys didnt get my directory structure - lol) but /build.txt probably isnt writable by php so you would need to point it at /home/username/folder/build.txt
 
I think marc's solution is better. Having all the images on your server means you don't have to hammer flikr all the time.

You could always run a script to grab more images at the end of every day or something, so you always have fresh images.
 
this new one isnt so bad its pulling the images only when needed and only checks for new images once every 6 hours, plus it only pulls 5 75x75 pixel images when it does update.
 
Code:
<?php
$path = '/home/unknown/www/flickr/';
$image_file = $path . 'image.jpg';
$version_file = $path . 'build.txt';
if(($_GET['force'] == 'yes') || (!file_exists($image_file)) || (time()-filemtime($version_file) > 21600)) {
	error_reporting(0);
	$xmldata = file_get_contents('http://www.flickr.com/services/feeds/photos_public.gne?id=62834984@N00&format=rss_200') ;
	$xmldata = str_replace('media:thumbnail', 'mediathumbnail', $xmldata);
	$xml = simplexml_load_string($xmldata);
	$new = $xml->channel->lastBuildDate;
	$old = file_get_contents($version_file);
	if (trim($new) != trim($old) || $_GET['force'] == 'yes') {
		file_put_contents($version_file, $new);
		function addImage($source, $destination, $offset) {
			$temp = imagecreatefromjpeg($source);
			$woffset = ((75 + 5) * $offset);
			imagecopyresampled($destination, $temp, $woffset, 0, 0, 0, 75, 75, 75, 75);
			imagedestroy($temp);
		}
		$image = imagecreatetruecolor(395, 75);
		$colour = imagecolorallocate($image, 28, 87, 128);
		$white = imagecolorallocate($image, 255, 255, 255);
		imagefill($image, 0, 0, $colour);
		for ($i=0; $i <= 4; $i++) {
			addImage($xml->channel->item[$i]->mediathumbnail['url'], $image, $i);
		}
		imagejpeg($image, $image_file, 90);
		imagedestroy($image);
	}

}

header('Content-type: image/jpeg');
readfile($image_file);

?>
 
^super efficient now. :)

and as i was bored, i made a randomiser (i'm only using your scenery pics).... :p

it only updates from flickr by force but generates a new patchwork on every hit.

Code:
<?php
$dir = 'thumbs/';
if($_GET['update'] == 'yes') {
	$xmldata = file_get_contents('http://www.flickr.com/services/feeds/photos_public.gne?id=62834984@N00&format=rss_200') ;
	$xmldata = str_replace('media:thumbnail', 'mediathumbnail', $xmldata);
	$xml = simplexml_load_string($xmldata);
	$exist = false;
	foreach($xml->channel->item as $item) {
		$url = $item->mediathumbnail['url'];
		$name = md5($url).'.jpg';
		if(file_exists($dir.$name)) {
			break 2;
		} else {
			$im = imagecreatefromjpeg($url);
			imagejpeg($im, $dir.$name);
			imagedestroy($im);
		}
	}
}
		
$im = imagecreatetruecolor(395, 75);
$colour = imagecolorallocate($im, 28, 87, 128);
imagefill($im, 0, 0, $colour);

foreach(glob($dir.'*.jpg') as $image) {
	$array[] = $image;
}

shuffle($array);

for ($i=0; $i <= 4; $i++) {
	$temp = imagecreatefromjpeg($array[$i]);
	$woffset = ((75 + 5) * $i);
	imagecopyresampled($im, $temp, $woffset, 0, 0, 0, 75, 75, 75, 75);
	imagedestroy($temp);
}

header('Content-type: image/jpeg');
imagejpeg($im);
imagedestroy($im);
?>
 
Last edited:
Code:
<?php
$dir = 'thumbs/';

if($_GET['update'] == 'yes') {
	$xmldata = file_get_contents('http://api.flickr.com/services/feeds/photos_public.gne?id=62834984@N00&tags=phpsig&lang=en-us&format=rss_200');
	$xmldata = str_replace('media:thumbnail', 'mediathumbnail', $xmldata);
	$xml = simplexml_load_string($xmldata);
	$exist = false;
	$i = 0;
	foreach($xml->channel->item as $item) {
		$url = $item->mediathumbnail['url'];
		$name = md5($url).'.png';
		
		if(file_exists($dir.$name)) {
			break;
		} else {
			$im = imagecreatefromjpeg($url);
			imagepng($im, $dir.$name, 0);
			imagedestroy($im);
		}
		$i++;
	}
}
		
$im = imagecreatetruecolor(395, 75);
$colour = imagecolorallocate($im, 28, 87, 128);
imagefill($im, 0, 0, $colour);

foreach(glob($dir.'*.png') as $image) {
	$array[] = $image;
}

shuffle($array);

for ($i=0; $i <= 4; $i++) {
	$temp = imagecreatefrompng($array[$i]);
	$woffset = ((75 + 5) * $i);
	imagecopyresampled($im, $temp, $woffset, 0, 0, 0, 75, 75, 75, 75);
	imagedestroy($temp);
}

header('Content-type: image/jpeg');
imagejpeg($im, NULL, 90);
imagedestroy($im);
?>

I simply changed the image source so it reads from my tags so where I have got phpsig as a tag it puts it into my rss feed. I also made it store the images as full quallity png because, flickr already compressed these as jpeg once, I am now doing this another 2 times, the image quality is lost so by saving it out as png i dont loose quality and when I come to build the final image im shoing it a 90% as a jpeg so its compressed 2 times instead of 3.
 
looking good. :)

you can tell i'm a noob (using break 2 - thought i had to break out from the if statement as well :o)

edit: you can lose the $i=0 and $i++ from the first segment - left those in by mistake before i used foreach. :)
 
Ok so heres too more additions, I use other forums, god forbid and I would like the background colour to match... I can't use gif because the quality is so poor, nor png because the files are too large, so... it now takes a rgb element in the query string to tell it what colour to use... Not content with that I also wrote a .htaccess file to make it look nice...

Code:
RewriteEngine On
RewriteRule ^([0-9]+)/([0-9]+)/([0-9]+)/image.jpg?$ image.php?r=$1&g=$2&b=$3 [NC]

Code:
<?php
$dir = 'thumbs/';

if($_GET['update'] == 'yes') {
	$xmldata = file_get_contents('http://api.flickr.com/services/feeds/photos_public.gne?id=62834984@N00&tags=phpsig&lang=en-us&format=rss_200');
	$xmldata = str_replace('media:thumbnail', 'mediathumbnail', $xmldata);
	$xml = simplexml_load_string($xmldata);
	$exist = false;
	$i = 0;
	foreach($xml->channel->item as $item) {
		$url = $item->mediathumbnail['url'];
		$name = md5($url).'.png';
		
		if(file_exists($dir.$name)) {
			break;
		} else {
			$im = imagecreatefromjpeg($url);
			imagepng($im, $dir.$name, 0);
			imagedestroy($im);
		}
		$i++;
	}
}

$im = imagecreatetruecolor(395, 75);

$r = $_GET['r'];
$g = $_GET['g'];
$b = $_GET['b'];

if ($r == NULL OR $g == NULL OR $b == NULL OR $r > 255 OR $g > 255 OR $b > 255) {
	$r = 28;
	$g = 87;
	$b = 128;
}

$colour = imagecolorallocate($im, $r, $g, $b);
imagefill($im, 0, 0, $colour);

foreach(glob($dir.'*.png') as $image) {
	$array[] = $image;
}

shuffle($array);

for ($i=0; $i <= 4; $i++) {
	$temp = imagecreatefrompng($array[$i]);
	$woffset = ((75 + 5) * $i);
	imagecopyresampled($im, $temp, $woffset, 0, 0, 0, 75, 75, 75, 75);
	imagedestroy($temp);
}

header('Content-type: image/jpeg');
imagejpeg($im, NULL, 90);
imagedestroy($im);
?>
 
Back
Top Bottom