/**
  * Returns a cropped image
  *
  * @param \WideImage\Image $img
  * @param smart_coordinate $left
  * @param smart_coordinate $top
  * @param smart_coordinate $width
  * @param smart_coordinate $height
  * @return \WideImage\Image
  */
 public function execute($img, $left, $top, $width, $height)
 {
     $width = Coordinate::fix($width, $img->getWidth(), $width);
     $height = Coordinate::fix($height, $img->getHeight(), $height);
     $left = Coordinate::fix($left, $img->getWidth(), $width);
     $top = Coordinate::fix($top, $img->getHeight(), $height);
     if ($left < 0) {
         $width = $left + $width;
         $left = 0;
     }
     if ($width > $img->getWidth() - $left) {
         $width = $img->getWidth() - $left;
     }
     if ($top < 0) {
         $height = $top + $height;
         $top = 0;
     }
     if ($height > $img->getHeight() - $top) {
         $height = $img->getHeight() - $top;
     }
     if ($width <= 0 || $height <= 0) {
         throw new Exception("Can't crop outside of an image.");
     }
     $new = $img->doCreate($width, $height);
     if ($img->isTransparent() || $img instanceof PaletteImage) {
         $new->copyTransparencyFrom($img);
         if (!imagecopyresized($new->getHandle(), $img->getHandle(), 0, 0, $left, $top, $width, $height, $width, $height)) {
             throw new GDFunctionResultException("imagecopyresized() returned false");
         }
     } else {
         $new->alphaBlending(false);
         $new->saveAlpha(true);
         if (!imagecopyresampled($new->getHandle(), $img->getHandle(), 0, 0, $left, $top, $width, $height, $width, $height)) {
             throw new GDFunctionResultException("imagecopyresampled() returned false");
         }
     }
     return $new;
 }