2

I am trying to randomly set the background image of a webpage from a folder via PHP.

I have the following code:

<!DOCTYPE HTML>
<html>
    <head>
        <link rel="stylesheet" type="text/css" href="style.css">
        <title>404</title>
    </head>

    <body id="Background404">
        <p>404-Page not found. <a href="http://url.com>Home.</a></p>
    <?php
        $dir = '/var/www/html/Images';
        $fileNames = array();
        if(is_dir($dir)){
            $handle = opendir($dir);
            while(false !== ($file = readdir($handle))){
                if(is_file($dir.'/'.$file) && is_readable($dir.'/'.$file)){
                $fileNames[] = $file;
                }
            }
            closedir($handle);
            $fileNames = array_reverse($fileNames);
            print_r($fileNames);
        }
        $totalLength = sizeof($fileNames);
        $randInt = rand(0, $totalLength);
        $randFile = $fileNames[$randInt];
        echo '<style> #Background404{background: url($randFile);}</style>';

    ?>

    </body>
</html>

Note: the printing of the files is just to ensure I reach that point in code and to see what the files are called. I found a similar question here: Random Background Image PHP but when I used that answer I got just a pure white background.

Here is a copy of printed array:

Array ( 
        [0] => GraniteBridge.png
        [1] => mobileBackground.png
        [2] => OtherKingdom.png
        [3] => NetherBase.png
        [4] => BackgroundTablet.png
        [5] => Snowy.png
        [6] => Village.png
        [7] => background2.png
        [8] => CactusFarm.png
        [9] => FrontView.png
        [10] => CreditsPortal.png
        [11] => FrontNight.png
        [12] => background4.png
        [13] => XPFarmRailway.png
        [14] => GoldIronFarms.png
        [15] => Pyramid.png
        [16] => NetherFortress.png
        [17] => TheEnd.png
        [18] => Library.png
        [19] => Background.png
        [20] => twitter.png
        [21] => mobileBackground1.png
        [22] => mobileBackground2.png
        [23] => BirdsEyeView.png
        [24] => EndPortal.png
        [25] => AboveVillage.png
        [26] => TowerToTheHeavens.png
        [27] => TowerArmorStands.png
        [28] => FullSizeBackground.png
        [29] => Mansion.png
        [30] => Night.png
        [31] => Dojo.png
)

4 Answers 4

2

You can use array_rand to get a random index in the array. Then you can use that random index to get an image from your array

$randomImage = $images[array_rand($images)];

This is a complete example which uses glob to fetch the images in the folder

<?php 
$imagesDir = '/var/www/html/images';
$images = glob($imagesDir . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);

$randomImage = $images[array_rand($images)];
?>

<img style="background-image:url('/path/to/images/<?php echo $randomImage ?>');"/>
Sign up to request clarification or add additional context in comments.

Comments

1

We can see that elements in array are ordered ascending by they array key. We can use this information to create a proper approach for grabbing random array element.

First of all you have to grab the count of array so:

$count = count($fileNames);

Then just use rand() function to generate random number from 0 to the count of array:

$random = rand(0, $count) - 1;

Now you've got random array key so you can use it:

<img style="background-image:url('path/to/image/<?=$fileNames[$random]?>');"/>

4 Comments

I've just edited the post cause I did a misstake and didnt assign random value to variable for later use.
I've tried this and now I see an image element, but it doesn't find the image and when I copy the image address I get "96.19.31.19/var/www/html/Images/$fileNames[%3C?=$random?%3E]" so it's aparanetly not switching the php to plain text to use in the html
I added a "- 1" since the array is zero-based,otherwise it will produce an occasional error. Also, personally I always use mt_rand instead of rand. It's not a big deal either way for a task like this, but is generally preferred since it produces a "more random" number (but the syntax is identical to rand.)
Also you need the -1 within the parenthesis right now you're getting an int [-1, $count -1] where you want: $random = rand(0, $count -1);
1

Taking it a step further...

  • this randomly chooses a jpg, png or gif image from the specified folder,
  • displays the "entire" (contained) picture as the background-image (via the html <body> tag)
  • set the page background-color to the average color of the image,
  • shows the "short" filename of the background image in a <div>, and,
  • sets the <div>'s text color to Black or White: whichever will best contrast the image colors.
<html>
<?php
  // get array of image filenames (jpg/png/gif) from specified folder
  $img_path="../images/";
  $imgs=glob($img_path."*.{jpg,png,gif}", GLOB_BRACE);

  // choose an image randomly
  $rnd_img = $imgs[mt_rand(0, count($imgs)-1)];

  // calc average $r,$g,$b + recommended $text_color  
  extract(text_color_from_avg_img_color($rnd_img));

  // print html <body> tag with bg image + avg bg color
  echo "<body style=\"background: rgb($r,$g,$b) url('$rnd_img'); " 
      ."background-position:center; background-size:contain; "
      ."background-repeat:no-repeat; height:100%; \">";

  //print image title in appropriate color
  echo "<div style='color:$txt_color; font-size:5vmin;'>"
      ."Random image: '".basename($rnd_img)."'</div>";


  function text_color_from_avg_img_color( $fname ) {
  /* adapted from gist.github.com/8098215 + stackoverflow.com/q/1331591 */  
    try  {  $image = new Imagick($fname); //uses Imagick to...
          $image->scaleimage(1, 1);  // scale to 1x1 pixel to get avg color
          if(!$pixels = $image->getimagehistogram())  { return 'black'; }
        } catch(ImagickException $e)                  { return 'black'; }
          catch(Exception $e)                         { return 'black'; }
    extract(reset($pixels)->getcolor()); //next calc best contrast color: 
    $L=0.2126*pow($r/255,2.2)+0.7152*pow($g/255,2.2)+0.0722*pow($b/255,2.2);
    $txt_color=((int)($L>0?(($L+0.05)/0.05):(0.05/($L+0.05)))>5?'black':'white');
    return compact("txt_color", "r", "g", "b");  //return array
  }

1 Comment

Heh nice, can't say I need this code anymore and it's interesting to see how simple my questions were 3 years ago, but your answer is the most complete. Cheers!
0

For posterity's sake here is the original code working as intended.

<!DOCTYPE HTML>
<html>
    <head>
        <link rel="stylesheet" type="text/css" href="style.css">
        <title>404</title>
    </head>

    <body id="Background404">
        <p>404-Page not found. <a href="http://url.com">Home.</a></p>
    <?php
        $dir = './images';
        $fileNames = array();
        if(is_dir($dir)){
            $handle = opendir($dir);
            while(false !== ($file = readdir($handle))){
                if(is_file($dir.'/'.$file) && is_readable($dir.'/'.$file)){
                    $fileNames[] = $file;
                }
            }
            closedir($handle);
            $fileNames = array_reverse($fileNames);
            print_r($fileNames);
        }
        $totalLength = count($fileNames);
        $randInt = rand(0, $totalLength -1);
        $randFile = $fileNames[$randInt];
        echo $randFile;
        echo "<style> #Background404{background: url('./images/$randFile');}</style>";
    ?>

    </body>
</html>

Switched from using sizeof($fileNames) to count($fileNames) to avoid confusion coming from other languages expecting sizeof to return allocated memory size.

Add complete path as $fileNames just contains the file name where html expects a path from webroot.

Add -1 to end of rand range to ensure a valid index is retrieved.

Switch single quotes to double quotes so variable would be output properly

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.