Load Random Images from Directory

Multi tool use
Load Random Images from Directory
I'd like to randomly load images from a directory and have a button somewhere that refreshes the entire page. Here's the current code I have now:
<?php
$a = array();
$dir = '../public/wp-content/uploads/2012/01';
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if (preg_match("/.png$/", $file)) $a = $file;
elseif (preg_match("/.jpg$/", $file)) $a = $file;
elseif (preg_match("/.jpeg$/", $file)) $a = $file;
}
closedir($handle);
}
foreach ($a as $i) {
echo "<img src='" . $dir . '/' . $i . "' />";
}
?>
The problem is it loads all 400,000 images at once. I only want 30 to load. 30 random images from the directory. I tried looking up some code such as modifying the above to this:
<?php
$a = array();
$dir = '../public/wp-content/uploads/2012/01';
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if (preg_match("/.png$/", $file)) $a = $file;
elseif (preg_match("/.jpg$/", $file)) $a = $file;
elseif (preg_match("/.jpeg$/", $file)) $a = $file;
}
closedir($handle);
}
foreach ($a as $i) {
echo "<img src='" . $dir . '/' . $i . "' />";
if (++$i == 2) break;
}
?>
But it seems to do absolutely nothing.. So if someone can help me get 30 random photos from that directory to load and have some type of reload button, that would be of great help.
Thank you in advance
$i
++$i
6 Answers
6
Here is my solution with a cache:
<?php
define('CACHE_FILE', 'mycache.tmp');
define('CACHE_TIME', 20); // 20 seconds (for testing!)
define('IMG_COUNT', 30);
define('IMG_DIR', '../public/wp-content/uploads/2012/01');
/**
* Loads the list (an array) from the cache
* Returns FALSE if the file couldn't be opened or the cache was expired, otherwise the list (as an array) will be returned.
*/
function LoadListFromCache($cacheFile, $cacheTime)
{
if ( file_exists($cacheFile) )
{
$fileHandle = fopen($cacheFile, 'r');
if ( !$fileHandle )
return false;
// Read timestamp (separated by "n" from the content)
$timestamp = intval( fgets($fileHandle) );
fclose($fileHandle);
// Expired?
if ( $timestamp+$cacheTime > time() )
return false;
else
{
// Unserialize the content!
$content = file_get_contents($cacheFile);
$content = substr( $content, strpos($content, "n") );
$list = unserialize($content);
return $list;
}
}
return false;
}
/**
* Caches the passed array
* Returns FALSE if the file couldn't be opened, otherwise TRUE.
*/
function SaveListToCache($cacheFile, $list)
{
$fileHandle = fopen($cacheFile, 'w');
if ( $fileHandle === FALSE ) return false;
fwrite($fileHandle, time());
fwrite($fileHandle, "n");
fwrite($fileHandle, serialize($list));
fclose($fileHandle);
return true;
}
/**
* Generates the list of all image files (png, jpg, jpeg) and caches it.
* Returns the list as an array.
*/
function GenerateList()
{
$a = array();
$dir = IMG_DIR;
if ($handle = opendir($dir))
{
while (false !== ($file = readdir($handle)))
{
if (preg_match("/.png$/", $file)) $a = $file;
elseif (preg_match("/.jpg$/", $file)) $a = $file;
elseif (preg_match("/.jpeg$/", $file)) $a = $file;
}
closedir($handle);
}
SaveListToCache(CACHE_FILE, $a);
return $a;
}
function GetRandomImages($list, $count)
{
$listCount = count($list);
$randomEntries = array();
for ($i=0; $i<$count; $i++)
{
$randomEntries = $list[ rand(0, $listCount) ];
}
return $randomEntries;
}
// This code will execute the other functions!
$list = LoadListFromCache(CACHE_FILE, CACHE_TIME);
if ( $list === FALSE )
{
$list = GenerateList();
}
$images = GetRandomImages($list, IMG_COUNT);
foreach ($images as $image)
{
echo '<img src="', IMG_DIR.DIRECTORY_SEPARATOR.$image, '" />';
}
It's not showing my random echo "<img src='" . $dir . '/' . $a[random] . "' />"; anywhere!
– JD Audi
Jan 12 '12 at 18:27
@JDAudi Updated!
– ComFreek
Jan 12 '12 at 18:33
I get this: fopen requires two params 1 given on line
– JD Audi
Jan 12 '12 at 18:34
Sorry, updated.
– ComFreek
Jan 12 '12 at 18:38
Thank you ComFreek, your a php wizard!
– JD Audi
Jan 12 '12 at 18:40
If you have 400,000 images then I think reading the entire directory everytime is going to be an expensive means of showing random images. I would use a database instead and store the file paths in it.
If you want to use your existing code then think of it this way. You have an array of length n
containing image names. You want to generate thirty random numbers between 0
and n-1
. Then display the image associated with that position in the array. I'm not a php expert, but here is some pseudocode:
n
0
n-1
$a = array();
$dir = '../public/wp-content/uploads/2012/01';
if (preg_match("/.png$/", $file)) $a = $file;
elseif (preg_match("/.jpg$/", $file)) $a = $file;
elseif (preg_match("/.jpeg$/", $file)) $a = $file;
for ( i=0; i < 30; i++) {
//generate a random number between 0 and N-1
random = rand(0, $a.length - 1);
//display that image in the array
echo "<img src='" . $dir . '/' . $a[random] . "' />";
}
You need to create a new variable for the counter instead of using $i
$i
For example, you can do this instead
$j = 0;
foreach ($a as $i) {
echo "<img src='" . $dir . '/' . $i . "' />";
$j++;
if ($j >= 30)
{
break;
}
}
EDIT: Perhaps for the random part you can first generate a random number between 0 and n-1 where n is the total number of the images and then just echo out the image from the array with the index number.
Instead of using foreach
, I think you'll need a for
loop instead.
foreach
for
$totalImgs = count($a);
$imgUsed = array();
for ($j = 0; $j < 30; $j++)
{
do
{
$randIndex = mt_rand(0, $totalImgs);
}
while ($imgUsed[$randIndex] === TRUE);
$imgUsed[$randIndex] = TRUE;
echo "<img src='" . $dir . '/' . $a[$randIndex] . "' />";
}
That works! now how about randomizing the images on page load or by a button
– JD Audi
Jan 12 '12 at 17:39
Just put this before the
foreach(...)
: shuffle($a);
.– ComFreek
Jan 12 '12 at 17:45
foreach(...)
shuffle($a);
@ComFreek - won't shuffling 400k array elements be needlessly expensive?
– mrtsherman
Jan 12 '12 at 17:47
I thought he limited it to 30 images. @JD Audi This code will always add the same images to the array. You need to use
scandir()
and shuffle the array returned by it (but please cache the results!).– ComFreek
Jan 12 '12 at 17:51
scandir()
@ComFreek how would I add that into this? Submit an answer with cache enabled!
– JD Audi
Jan 12 '12 at 17:54
You should maybe only read 30 file from your directory. Stop looking in the directory when readdir return false or your array's length is 30.
This should work
$a = array();
$dir = '../public/wp-content/uploads/2012/01';
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle)) && (count($a) <= 30) {
if (preg_match("/.png$/", $file)) $a = $file;
elseif (preg_match("/.jpg$/", $file)) $a = $file;
elseif (preg_match("/.jpeg$/", $file)) $a = $file;
}
closedir($handle);
}
It may not execute (I didn't try). But the idea is here
For randomize the image: shuffle($a) should do the trick
Could you give me a code example? The entire thing was copy and pasted and modified the paths to get it to work. I really don't understand the readdir commands.
– JD Audi
Jan 12 '12 at 17:36
Sorry I didn't do php since a while so I may be a little rusty. The readdir command return the next file from the directory you open until you reach the end, so here you only stop when you read all the content on the directory. I edit my question for a example in a minute.
– Marc Simon
Jan 12 '12 at 17:38
Okay thanks I appreciate it, I understand now!
– JD Audi
Jan 12 '12 at 17:40
Thanks for the edit but it didn't work - how can I randomize on page load though?
– JD Audi
Jan 12 '12 at 17:43
Try shuffle() => php.net/manual/en/function.shuffle.php
– Marc Simon
Jan 12 '12 at 17:52
in simplest way ,
you can use
find , sort , head
commands in linux,in conjuction with PHP's built in
exec()
function to get 30 random image links easily , the folowing snippet lists how to do it
(How to get random 30 image links in an array.)
<?php
$picdir = "directory/containing/pictures"; // directory containing only pictures
exec("find " . $picdir . " | sort -R | head -30 ",$links);
while(list($index,$val) = each($links) ) {
echo "<img src =" .$val . "> <br/>"; // shows image
}
?>
Here $links array contain random 30 image names(from folder) with complete path . This is used with img tag in echo to generate images
Here $picdir has the path of the directory having images and it is assumed that dirrectory is having only image files . in other case its only matter of modifying find command to exclude non image files(such as using grep command to exclude )
This single line of code facilitates the random display of n number of
images (image_1.png, image_2.png, image_3.png, etc.) located in the
target directory (http://domain.tld/path/random/).
<img src="http://domain.tld/path/random/image_<?php $random = rand(1,n); echo $random; ?>.png" />
https://perishablepress.com/drop-dead-easy-random-images-via-php/
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
$i
is a string apparently so++$i
doesn't make sense. The subsequent equality comparison wouldn't work either.– mrtsherman
Jan 12 '12 at 17:37