I am familiar with several PHP random image loaders. The only thing I can not seem to find very easily with these scripts is one that prevents repeats for so many reloads.

I have a directory containing 3500 images. What I have noticed is that I can cycle through the random image scripts and many times come across the same images several times within 20-30 reloads.

I am looking for a way to set some sort of specified history with what has been loaded. I'd say 50 or so would be fine. Any help would be greatly appreciated as I do not want to have to resort to SQL random lookup which seems to work a bit better.

<?php

$folder = 'stash/';

$exts = 'jpg jpeg png gif';

$files = array(); $i = -1; // Initialize some variables
if ('' == $folder) $folder = './';

$handle = opendir($folder);
$exts = explode(' ', $exts);
while (false !== ($file = readdir($handle))) {
foreach($exts as $ext) { // for each extension check the extension
if (preg_match('/\.'.$ext.'$/i', $file, $test)) { // faster than ereg, case insensitive
$files[] = $file; // it's good
++$i;
}
}
}
closedir($handle); // We're not using it anymore
mt_srand((double)microtime()*253568-count($files)*646/12); // seed for PHP < 4.2
$rand = mt_rand(0,count($files)); // $i was incremented as we went along

header('Location: '.$folder.$files[$rand]); // Voila!
?>

this is another one that i've tried. it does seem to be more random, but has slower load times.

<?php

	$folder = 'Z:/Pics/_NON-GROUP/';

    $extList = array();
	$extList['gif'] = 'image/gif';
	$extList['jpg'] = 'image/jpeg';
	$extList['jpeg'] = 'image/jpeg';
	$extList['png'] = 'image/png';

// --------------------- END CONFIGURATION -----------------------

$img = null;

if (substr($folder,-1) != '/') {
	$folder = $folder.'/';
}

if (isset($_GET['img'])) {
	$imageInfo = pathinfo($_GET['img']);
	if (
	    isset( $extList[ strtolower( $imageInfo['extension'] ) ] ) &&
        file_exists( $folder.$imageInfo['basename'] )
    ) {
		$img = $folder.$imageInfo['basename'];
	}
} else {
	$fileList = array();
	$handle = opendir($folder);
	while ( false !== ( $file = readdir($handle) ) ) {
		$file_info = pathinfo($file);
		if (
		    isset( $extList[ strtolower( $file_info['extension'] ) ] )
		) {
			$fileList[] = $file;
		}
	}
	closedir($handle);

	if (count($fileList) > 0) {
		$imageNumber = time() % count($fileList);
		$img = $folder.$fileList[$imageNumber];
	}
}

if ($img!=null) {
	$imageInfo = pathinfo($img);
	$contentType = 'Content-type: '.$extList[ $imageInfo['extension'] ];
	header ($contentType);
	readfile($img);
} else {
	if ( function_exists('imagecreate') ) {
		header ("Content-type: image/png");
		$im = @imagecreate (100, 100)
		    or die ("Cannot initialize new GD image stream");
		$background_color = imagecolorallocate ($im, 255, 255, 255);
		$text_color = imagecolorallocate ($im, 0,0,0);
		imagestring ($im, 2, 5, 5,  "IMAGE ERROR", $text_color);
		imagepng ($im);
		imagedestroy($im);
	}
}

?>

Recommended Answers

All 15 Replies

Use a session to store the $rand value for the last x images:

$_SESSION['rand_img'][] = $rand;

You could add in an if to that to remove the first item of the array once 50 items are stored.

Then, use the In array function to see if the rand number generated is in the session and regenerate if it has been seen in the last x times.

use a session if you want random per person.


if you want random per site....here's the concept.

file_put_contents, file_get_contents, array(), serialize, unserialize, rand, in_array, flock

pretty much all of the functions you'll need. all found on php.net

- get a random int with 1 and # of images corresponding to your images (maybe load file names into an array and use the index for the # and count() for max)
while (flocked(history.txt)) retry
flock file
get the contents of history.txt file
unserialize it into an array
if random # is in array, get a new random # until not in array
serialize array
file put contents array
unflock file

This sounds like an easy solution. Would there be any server impact having so many session variables? is up to 50 per visitor alot?

Use a session to store the $rand value for the last x images:

$_SESSION['rand_img'][] = $rand;

You could add in an if to that to remove the first item of the array once 50 items are stored.

Then, use the In array function to see if the rand number generated is in the session and regenerate if it has been seen in the last x times.

this was kind of my initial attempt. a friend gave me a script which did something along these lines, but i was unsuccessful at integrating it with the random image scripts. great minds think alike, unfortunately i don't have one of those. the site history would not matter to much to me being that i am only concerned with the visitors seeing duplicates.

use a session if you want random per person.


if you want random per site....here's the concept.

file_put_contents, file_get_contents, array(), serialize, unserialize, rand, in_array, flock

pretty much all of the functions you'll need. all found on php.net

- get a random int with 1 and # of images corresponding to your images (maybe load file names into an array and use the index for the # and count() for max)
while (flocked(history.txt)) retry
flock file
get the contents of history.txt file
unserialize it into an array
if random # is in array, get a new random # until not in array
serialize array
file put contents array
unflock file

Providing you clean up after yourself with session_destroy(); you shouldn't have too many issues. Sessions are small files :)

We'll it still loads images, but i fubared the array somewhere. also, not sure how i should throw in the if statement to check for last 50

EDIT: i just realized that i'm even more lost now that i threw that jibberish in there. lol... maybe sql isnt a bad idear at this point. any help would be great.

<?php

$folder = 'stash/';
$exts = 'jpg jpeg png gif';

$files = array(); $i = -1; // Initialize some variables
if ('' == $folder) $folder = './';

$handle = opendir($folder);
$exts = explode(' ', $exts);
while (false !== ($file = readdir($handle))) {
foreach($exts as $ext) { // for each extension check the extension
if (preg_match('/\.'.$ext.'$/i', $file, $test)) { // faster than ereg, case insensitive
$files[] = $file; // it's good
++$i;
}
}
}
closedir($handle); // We're not using it anymore
mt_srand((double)microtime()*1000000); // seed for PHP < 4.2
 // $i was incremented as we went along

session_start();
$_SESSION['rand_img'][] = array();

   for($i = 0; $i < 10; $i++) {
      $rand = mt_rand(0, count($files));
      
      while(in_array($rand,$_SESSION['rand_img'])) {
        $rand = mt_rand(0, count($files));
      }
      
      $_SESSION['rand_img'][$i] = $rand;
   }

// $_SESSION['rand_img'][$i] = $rand;
// echo $_SESSION['rand_img'];
// print_r($_SESSION['rand_img']);

header('Location: '.$folder.$files[$rand]); // Voila!
// header('Location: '.$folder.$files[$rand]); // Voila!
?>

The $_SESSION variable is an array anyway, so no need to declare it as an array.

A few slight errors in your code though, look through the below and comments:

session_start();
      $rand = mt_rand(0, count($files));
      while(in_array($rand,$_SESSION['rand_img'])) {
        $rand = mt_rand(0, count($files));
      }
      // Check if the array has 50 indexes, and remove the first index if it does
      if(count($_SESSION['rand_img']) >= 50) {
        $removed = array_shift($_SESSION['rand_img']);
      }
      // No need for $i, [] will insert the $rand in the next location.
      $_SESSION['rand_img'][] = $rand;
   }

That should work, but I have not tested it, but hopefully you get the general idea..

that worked great. just had to remove the trailing } and integrate it into the script. thanks for your help Will.

Next i need to figure a way for it to look in the subdirectories too. :P

is this solved? OMG! im too late! yeah will is right? i recommend use session, it's the best approach to your problem.

I wonder if people are trying to farm "solved"

I mean, I already caught you doing it once. and I can't believe you are still doing it. try doing some of your own work instead of attempting to take credit for others, vaultdweller123

yes this issue is solved... unless you'd like to add code to check in subdirectories, but that may be best as another post

I mean, I already caught you doing it once. and I can't believe you are still doing it. try doing some of your own work instead of attempting to take credit for others, vaultdweller123

yeah your right :D

yeah your right :D

you're

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.