You are here

function focal_point_smartcrop_estimation in Focal Point 7

Given an image, use smartcrop to estimate a good focal point.

See also

image_gd_smartcrop_crop()

http://envalo.com/image-cropping-php-using-entropy-explained/

1 call to focal_point_smartcrop_estimation()
focal_point_get_smartcrop_focal_point in ./focal_point.module
Callback function.

File

./focal_point.smartcrop.inc, line 20

Code

function focal_point_smartcrop_estimation(stdClass $image_data) {

  // To avoid bad performance with large images, we calculate the focal point on
  // a smaller version of the image. 500px should be far enough.
  // @todo Consider making this configurable.
  static $px_needed = 500;
  $image_data = clone $image_data;

  // If the current image toolkit is ImageMagick, GD resource has to be
  // populated.
  if (image_get_toolkit() != 'gd') {
    image_gd_load($image_data);
  }
  $image_width = $image_data->info['width'];
  $image_height = $image_data->info['height'];
  $ratio = max($px_needed / $image_width, $px_needed / $image_height);
  $resized = FALSE;
  if ($ratio <= 1) {
    $resized = image_gd_resize($image_data, round($ratio * $image_width), round($ratio * $image_height));
  }
  $full_width = imagesx($image_data->resource);
  $full_height = imagesy($image_data->resource);

  // Given that most of the time, cropped images have a width/height ratio
  // between 4:1 and 1:4, the width of a cropped image will be greater than
  // (original height)/4 and the height greater than (original width)/4.
  // Based on this assumption, we will try to find the most interesting area
  // (max entropy) of this size.
  // The focal point will simply be the center of the resulting area.
  // @todo Consider making this configurable.
  static $highest_ratio = 4;
  static $largest_ratio = 4;
  $target_width = round($full_height / $highest_ratio);
  $target_height = round($full_width / $largest_ratio);

  // First, we will cut our image into 25 vertical and horizontal slices, to get
  // 25x25 areas, then calculate their entropy.
  // @todo Consider making this configurable.
  static $slices_count = 25;
  $area_width = $full_width / $slices_count;
  $area_height = $full_height / $slices_count;
  $area_entropies = array();
  for ($i = 0; $i < $slices_count; $i++) {
    $area_entropies[$i] = array();
    for ($j = 0; $j < $slices_count; $j++) {
      $area_entropies[$i][$j] = _smartcrop_gd_entropy_slice($image_data, round($i * $area_width), round($j * $area_height), $area_width, $area_height);
    }
  }

  // We calculate how many areas are needed to get the target width and height.
  $target_areas_counts = array(
    ceil(min($target_width / $area_width, $slices_count)),
    ceil(min($target_height / $area_height, $slices_count)),
  );

  // We get the adjacent areas that lead to the maximum entropy.
  $best_first_area = _focal_point_smartcrop_get_best_first_area($area_entropies, $target_areas_counts);

  // We calculate the middle of the resulting area.
  $x = $area_width * ($best_first_area[0] + $target_areas_counts[0] / 2);
  $y = $area_height * ($best_first_area[1] + $target_areas_counts[1] / 2);
  if ($resized) {

    // We return the center of the resulting area, but for the original image,
    // not the small one.
    $x = $x / $ratio;
    $y = $y / $ratio;
  }
  return array(
    round($x),
    round($y),
  );
}