9

I want to display images inside divs or tables as backgrounds. If they images aren't large enough, I'm going to need to find the outer most color of that image and apply it to the background of the containing div or table cell.

Does anyone have experience with this? In PHP. I'm a noob so please explain. Thank you so much

1 Answers1

23

Check out the GD functions.

Here's a solution of looping through the pixels to find the most common color. However, you could just resize the image to 1 pixel - that should be the average color - right?

An example of the 1px method (now including test page):

<?php
  $filename = $_GET['filename'];    
  $image = imagecreatefromjpeg($filename);
  $width = imagesx($image);
  $height = imagesy($image);
  $pixel = imagecreatetruecolor(1, 1);
  imagecopyresampled($pixel, $image, 0, 0, 0, 0, 1, 1, $width, $height);
  $rgb = imagecolorat($pixel, 0, 0);
  $color = imagecolorsforindex($pixel, $rgb);
?>
<html>
  <head>
    <title>Test Image Average Color</title>
  </head>
  <body style='background-color: rgb(<?php echo $color['red'] ?>, <?php echo $color['green'] ?>, <?php echo $color['blue'] ?>)'>
    <form action='' method='get'>
      <input type='text' name='filename'><input type='submit'>
    </form>
    <img src='<?php echo $filename ?>'>
  </body>
</html>

Here's some example code for finding the average border color, similar to the first link. For your use this may work better (I know this code is inefficient, but hopefully it's easy to follow):

<?php
  $filename = $_GET['filename'];    
  $image = imagecreatefromjpeg($filename);
  $width = imagesx($image);
  $height = imagesy($image);

  for($y = 0; $y < $height; $y++){
    $rgb = imagecolorat($image, 0, $y);
    $color = imagecolorsforindex($image, $rgb);
    $red += $color['red'];
    $green += $color['green'];
    $blue += $color['blue'];

    $rgb = imagecolorat($image, $width -1, $y);
    $color = imagecolorsforindex($image, $rgb);
    $red += $color['red'];
    $green += $color['green'];
    $blue += $color['blue'];
  }

  for($x = 0; $x < $height; $x++){
    $rgb = imagecolorat($image, $x, 0);
    $color = imagecolorsforindex($image, $rgb);
    $red += $color['red'];
    $green += $color['green'];
    $blue += $color['blue'];

    $rgb = imagecolorat($image, $x, $height -1);
    $color = imagecolorsforindex($image, $rgb);
    $red += $color['red'];
    $green += $color['green'];
    $blue += $color['blue'];
  }

  $borderSize = ($height=$width)*2;
  $color['red'] = intval($red/$borderSize);
  $color['green'] = intval($green/$borderSize);
  $color['blue'] = intval($blue/$borderSize);

?>

Update: I put some more refined code on github. This includes both averaging the border, and averaging the entire image. It should be noted that resizing to 1px is far more resource friendly than scanning every pixel (although I haven't run any real time tests), but the code does show the three different methods.

Tim Lytle
  • 17,549
  • 10
  • 60
  • 91
  • Sorry but I'm a beginner, how would I apply that to a div for the background color? Any idea Tim. Thanks for suggesting this too, it means a lot. –  Nov 17 '09 at 04:50
  • I added the code for a complete 'test page'. That should point you in the right direction. – Tim Lytle Nov 17 '09 at 04:53
  • Just replace the initial block of php code in the first example (which includes the HTML) with the second example. – Tim Lytle Nov 17 '09 at 05:38
  • I keep getting these errors after replacing "filename" with "image.jpg" Warning: imagecreatefromjpeg() [function.imagecreatefromjpeg]: Filename cannot be empty in /path/get-image-color.php on line 3 Warning: imagesx(): supplied argument is not a valid Image resource in /path/get-image-color.php on line 4 Warning: imagesy(): supplied argument is not a valid Image resource in /path/get-image-color.php on line 5 Warning: Division by zero in /path/get-image-color.php on line 36 Warning: Division by zero in /path/get-image-color.php on line 37 –  Nov 17 '09 at 13:49
  • I doubt SO is the place for this kind of trouble shooting. If you want to contact me off-site, my SO profile should provide the information needed to do so. – Tim Lytle Nov 17 '09 at 15:43