Skip to content

Instantly share code, notes, and snippets.

@jnrbsn
Created December 19, 2012 03:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jnrbsn/4334075 to your computer and use it in GitHub Desktop.
Save jnrbsn/4334075 to your computer and use it in GitHub Desktop.
Calculates the "busiest" square area of an image to use for a thumbnail.
<?php
/**
* An example of how to use the `squarize()` function below.
*/
$path_input = 'input.png';
$path_output = 'output.png';
$thumb_w = 100;
$thumb_h = 100;
$input = imagecreatefrompng($path_input);
$output = imagecreatetruecolor($thumb_w, $thumb_h);
list($crop_x, $crop_y, $crop_w, $crop_h) = squarize($source);
imagecopyresampled($output, $input, 0, 0, $crop_x, $crop_y, $thumb_w, $thumb_h, $crop_w, $crop_h);
imagepng($output, $path_output, 9);
imagedestroy($input);
imagedestroy($output);
/**
* Calculates the "busiest" square area of an image to use for a thumbnail.
*
* Samples a grid of pixels from an image, calculates the standard deviation of the RGB values of
* those pixels, and returns information about the biggest square area of the image with the largest
* standard deviation of colors (i.e. the "busiest" part of the image).
*
* @param resource $img A GD image link resource.
* @param integer $width The width of the source image (optional).
* @param integer $height The height of the source image (optional).
* @param integer $pixels The distance between each pixel to sample (default: 10).
*
* @return array An array containing the x-coordinate of the top left corner of the crop area, the
* y-coordinate of the top left corner of the crop area, the width of the crop area,
* and the height of the crop area.
*/
function squarize($img, $width = null, $height = null, $pixels = 10)
{
if ($width === null || $height === null) {
$width = imagesx($img);
$height = imagesy($img);
}
$rgb = array();
for ($x = 0; $x < $width; $x += $pixels) {
for ($y = 0; $y < $height; $y += $pixels) {
$color = imagecolorat($img, $x, $y);
$rgb[$x][$y] = array(($color >> 16) & 0xFF, ($color >> 8) & 0xFF, $color & 0xFF);
}
}
$dev_max = 0;
$diff = abs($height - $width);
$x_bound = array(0, $width);
$y_bound = array(0, $height);
$count = pow((int)(min($height, $width) / $pixels), 2);
for ($i = 0, $r = 0, $g = 0, $b = 0, $dev = 0; $i < $diff; $i += $pixels) {
if ($height > $width) {
$y_bound = array($i, $width + $i);
} elseif ($height < $width) {
$x_bound = array($i, $height + $i);
}
for ($x = $x_bound[0]; $x < $x_bound[1]; $x += $pixels) {
for ($y = $y_bound[0]; $y < $y_bound[1]; $y += $pixels) {
$r += $rgb[$x][$y][0];
$g += $rgb[$x][$y][1];
$b += $rgb[$x][$y][2];
}
}
$r /= $count;
$g /= $count;
$b /= $count;
for ($x = $x_bound[0]; $x < $x_bound[1]; $x += $pixels) {
for ($y = $y_bound[0]; $y < $y_bound[1]; $y += $pixels) {
$tmp = ($rgb[$x][$y][0] - $r) * ($rgb[$x][$y][0] - $r);
$tmp += ($rgb[$x][$y][1] - $g) * ($rgb[$x][$y][1] - $g);
$tmp += ($rgb[$x][$y][2] - $b) * ($rgb[$x][$y][2] - $b);
$dev += sqrt($tmp);
}
}
$dev /= $count;
if ($dev > $dev_max) {
$dev_max = $dev;
$crop_x = $x_bound[0];
$crop_y = $y_bound[0];
}
}
$crop_w = min($width, $height);
$crop_h = $crop_w;
return array($crop_x, $crop_y, $crop_w, $crop_h);
}//end squarize()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment