/**
  * {@inheritdoc}
  */
 public function load(ImageInterface $image, array $options = array())
 {
     $background = $image->palette()->color(isset($options['color']) ? $options['color'] : '#fff', isset($options['transparency']) ? $options['transparency'] : null);
     $topLeft = new Point(0, 0);
     $size = $image->getSize();
     if (isset($options['size'])) {
         list($width, $height) = $options['size'];
         $position = isset($options['position']) ? $options['position'] : 'center';
         switch ($position) {
             case 'topleft':
                 $x = 0;
                 $y = 0;
                 break;
             case 'top':
                 $x = ($width - $image->getSize()->getWidth()) / 2;
                 $y = 0;
                 break;
             case 'topright':
                 $x = $width - $image->getSize()->getWidth();
                 $y = 0;
                 break;
             case 'left':
                 $x = 0;
                 $y = ($height - $image->getSize()->getHeight()) / 2;
                 break;
             case 'center':
                 $x = ($width - $image->getSize()->getWidth()) / 2;
                 $y = ($height - $image->getSize()->getHeight()) / 2;
                 break;
             case 'right':
                 $x = $width - $image->getSize()->getWidth();
                 $y = ($height - $image->getSize()->getHeight()) / 2;
                 break;
             case 'bottomleft':
                 $x = 0;
                 $y = $height - $image->getSize()->getHeight();
                 break;
             case 'bottom':
                 $x = ($width - $image->getSize()->getWidth()) / 2;
                 $y = $height - $image->getSize()->getHeight();
                 break;
             case 'bottomright':
                 $x = $width - $image->getSize()->getWidth();
                 $y = $height - $image->getSize()->getHeight();
                 break;
             default:
                 throw new \InvalidArgumentException("Unexpected position '{$position}'");
                 break;
         }
         $size = new Box($width, $height);
         $topLeft = new Point($x, $y);
     }
     $canvas = $this->imagine->create($size, $background);
     return $canvas->paste($image, $topLeft);
 }
예제 #2
0
 /**
  * {@inheritdoc}
  */
 public function generate($toFile = null)
 {
     $fontSize = max(min($this->dimension->getWidth() / strlen($this->text) * 1.15, $this->dimension->getHeight() * 0.5), 5);
     $palette = new RGB();
     $image = $this->imagine->create(new Box($this->dimension->getWidth(), $this->dimension->getHeight()), $palette->color($this->backgroundColor->getColor()));
     $font = ImagineFactory::createFontInstance($this->instanceType, __DIR__ . '/resource/mplus.ttf', $fontSize, $palette->color($this->stringColor->getColor()));
     $textProperties = $font->box($this->text);
     $image->draw()->text($this->text, $font, new Point(($this->dimension->getWidth() - $textProperties->getWidth()) / 2, ($this->dimension->getHeight() - $textProperties->getHeight()) / 2));
     if ($toFile !== null) {
         $image->save($toFile);
     }
     return new Result($image, $toFile);
 }
 /**
  * {@inheritdoc}
  */
 public function load(ImageInterface $image, array $options = array())
 {
     $background = new Color(isset($options['color']) ? $options['color'] : '#fff', isset($options['transparency']) ? $options['transparency'] : 0);
     $topLeft = new Point(0, 0);
     $size = $image->getSize();
     if (isset($options['size'])) {
         list($width, $height) = $options['size'];
         $size = new Box($width, $height);
         $topLeft = new Point(($width - $image->getSize()->getWidth()) / 2, ($height - $image->getSize()->getHeight()) / 2);
     }
     $canvas = $this->imagine->create($size, $background);
     return $canvas->paste($image, $topLeft);
 }
예제 #4
0
 /**
  * {@inheritDoc}
  */
 public function apply(ImageInterface $image)
 {
     if ($this->size) {
         list($width, $height) = $this->size;
         $size = new Box($width, $height);
         $topLeft = new Point(($width - $image->getSize()->getWidth()) / 2, ($height - $image->getSize()->getHeight()) / 2);
     } else {
         $topLeft = new Point(0, 0);
         $size = $image->getSize();
     }
     $background = $image->palette()->color($this->color);
     $canvas = $this->imagine->create($size, $background);
     return $canvas->paste($image, $topLeft);
 }
예제 #5
0
 protected function doRotate($x, $y, $angle)
 {
     list($currentImage, $point) = $this->getCurrentClip();
     $size = $currentImage->getSize();
     $y = $size->getHeight() - $y;
     $pointsToRotate = array(new Point(0, 0), new Point($size->getWidth(), 0), new Point($size->getWidth(), $size->getHeight()), new Point(0, $size->getHeight()));
     $xs = array();
     $ys = array();
     $rotatePoint = new Point($x, $y);
     foreach ($pointsToRotate as $pointToRotate) {
         $rotatedPoint = $this->rotatePoint($angle, $pointToRotate, $rotatePoint);
         $xs[] = $rotatedPoint->getX();
         $ys[] = $rotatedPoint->getY();
     }
     $firstPoint = new Point(min($xs), min($ys));
     $diagonalPoint = new Point(max($xs), max($ys));
     $middlePoint = new Point(($diagonalPoint->getX() - $firstPoint->getX()) / 2, ($diagonalPoint->getY() - $firstPoint->getY()) / 2);
     $width = $diagonalPoint->getX() - $firstPoint->getX();
     $height = $diagonalPoint->getY() - $firstPoint->getY();
     $image = $this->imagine->create($size);
     $angleInDegrees = rad2deg($angle);
     $clipPoint = new Point(0, 0);
     $rotatePoint = new Point(-$middlePoint->getX() + $x, -$middlePoint->getY() + $y);
     $this->state['clips'][] = array($image, $clipPoint, $angleInDegrees, $rotatePoint);
 }
예제 #6
0
 /**
  * Re-sizes the image. If $height is not specified, it will default to $width, creating a square.
  *
  * @param int      $targetWidth
  * @param int|null $targetHeight
  *
  * @return Image
  */
 public function resize($targetWidth, $targetHeight = null)
 {
     $this->normalizeDimensions($targetWidth, $targetHeight);
     if ($this->_isAnimatedGif) {
         $this->_image->layers()->coalesce();
         // Create a new image instance to avoid object references messing up our dimensions.
         $newSize = new \Imagine\Image\Box($targetWidth, $targetHeight);
         $gif = $this->_instance->create($newSize);
         $gif->layers()->remove(0);
         foreach ($this->_image->layers() as $layer) {
             $resizedLayer = $layer->resize($newSize, $this->_getResizeFilter());
             $gif->layers()->add($resizedLayer);
             // Let's update dateUpdated in case this is going to take awhile.
             if ($index = craft()->assetTransforms->getActiveTransformIndexModel()) {
                 craft()->assetTransforms->storeTransformIndexData($index);
             }
         }
         $this->_image = $gif;
     } else {
         if (craft()->images->isImagick()) {
             $this->_image->smartResize(new \Imagine\Image\Box($targetWidth, $targetHeight), (bool) craft()->config->get('preserveImageColorProfiles'), $this->_quality);
         } else {
             $this->_image->resize(new \Imagine\Image\Box($targetWidth, $targetHeight), $this->_getResizeFilter());
         }
     }
     return $this;
 }
예제 #7
0
	/**
	 * Re-sizes the image. If $height is not specified, it will default to $width, creating a square.
	 *
	 * @param int      $targetWidth
	 * @param int|null $targetHeight
	 *
	 * @return Image
	 */
	public function resize($targetWidth, $targetHeight = null)
	{
		$this->_normalizeDimensions($targetWidth, $targetHeight);

		if ($this->_isAnimatedGif)
		{

			// Create a new image instance to avoid object references messing up our dimensions.
			$newSize = new \Imagine\Image\Box($targetWidth, $targetHeight);
			$gif = $this->_instance->create($newSize);
			$gif->layers()->remove(0);

			foreach ($this->_image->layers() as $layer)
			{
				$resizedLayer = $layer->resize($newSize, $this->_getResizeFilter());
				$gif->layers()->add($resizedLayer);
			}

			$this->_image = $gif;
		}
		else
		{
			$this->_image->resize(new \Imagine\Image\Box($targetWidth, $targetHeight), $this->_getResizeFilter());
		}

		return $this;
	}
예제 #8
0
 /**
  * Generate the static map image and add blips to it if any are found
  *
  * @return ImageInterface The resulting image
  *
  * @return void
  */
 public function generate()
 {
     $box = Geo::calculateBox($this->size, $this->centerPoint);
     $this->resultImage = $this->imagine->create($box['base']);
     $jj = 0;
     $xStart = $box['tiles']['start']->getX();
     $xStop = $box['tiles']['stop']->getX();
     $yStart = $box['tiles']['start']->getY();
     $yStop = $box['tiles']['stop']->getY();
     for ($i = $yStart - 1; $i < $yStop; $i++) {
         $ii = 0;
         for ($j = $xStart - 1; $j < $xStop; $j++) {
             $this->addTile($this->tiles->getTile($j, $i), new Point($ii * Geo::TILE_SIZE, $jj * Geo::TILE_SIZE));
             $ii++;
         }
         $jj++;
     }
     $this->loader->run();
     $this->resultImage->crop($box['crop'], $this->size);
     foreach ($this->blips as $blip) {
         $this->drawBlip($blip);
     }
     $this->loader->run();
     return $this->resultImage;
 }
예제 #9
0
 /**
  * Creates an image object
  *
  * @param array|\Imagine\Image\ImageInterface $source
  * @throws \InvalidArgumentException On unsupported source type
  * @return \Imagine\Image\ImageInterface
  */
 public function create($source)
 {
     if ($source instanceof ImageInterface) {
         return $source;
     }
     if (isset($source['file'])) {
         return $this->imagine->open($source['file']);
     }
     if (isset($source['data'])) {
         return $this->imagine->load($source['data']);
     }
     if (isset($source['resource'])) {
         return $this->imagine->read($source['resource']);
     }
     if (isset($source['width']) && isset($source['height'])) {
         return $this->imagine->create(new Box($source['width'], $source['height']));
     }
     throw new InvalidArgumentException();
 }
예제 #10
0
 public function getImagineImage(ImagineInterface $imagine, FontCollection $fontCollection, $width, $height)
 {
     $fontPath = $fontCollection->getFontById($this->font)->getPath();
     if ($this->getAbsoluteSize() !== null) {
         $fontSize = $this->getAbsoluteSize();
     } elseif ($this->getRelativeSize() !== null) {
         $fontSize = (int) $this->getRelativeSize() / 100 * $height;
     } else {
         throw new \LogicException('Either relative or absolute watermark size must be set!');
     }
     if (true || !class_exists('ImagickDraw')) {
         // Fall back to ugly image.
         $palette = new \Imagine\Image\Palette\RGB();
         $font = $imagine->font($fontPath, $fontSize, $palette->color('#000'));
         $box = $font->box($this->getText());
         $watermarkImage = $imagine->create($box, $palette->color('#FFF'));
         $watermarkImage->draw()->text($this->text, $font, new \Imagine\Image\Point(0, 0));
     } else {
         // CURRENTLY DISABLED.
         // Use nicer Imagick implementation.
         // Untested!
         // @todo Test and implement it!
         $draw = new \ImagickDraw();
         $draw->setFont($fontPath);
         $draw->setFontSize($fontSize);
         $draw->setStrokeAntialias(true);
         //try with and without
         $draw->setTextAntialias(true);
         //try with and without
         $draw->setFillColor('#fff');
         $textOnly = new \Imagick();
         $textOnly->newImage(1400, 400, "transparent");
         //transparent canvas
         $textOnly->annotateImage($draw, 0, 0, 0, $this->text);
         //Create stroke
         $draw->setFillColor('#000');
         //same as stroke color
         $draw->setStrokeColor('#000');
         $draw->setStrokeWidth(8);
         $strokeImage = new \Imagick();
         $strokeImage->newImage(1400, 400, "transparent");
         $strokeImage->annotateImage($draw, 0, 0, 0, $this->text);
         //Composite text over stroke
         $strokeImage->compositeImage($textOnly, \Imagick::COMPOSITE_OVER, 0, 0, \Imagick::CHANNEL_ALPHA);
         $strokeImage->trimImage(0);
         //cut transparent border
         $watermarkImage = $imagine->load($strokeImage->getImageBlob());
         //$strokeImage->resizeImage(300,0, \Imagick::FILTER_CATROM, 0.9, false); //resize to final size
     }
     return $watermarkImage;
 }
예제 #11
0
 public function apply(ImageInterface &$image, ImagineInterface $imagine)
 {
     $box = $image->getSize();
     // x and y is the center of the crop
     $x = Helper::percentValue($this->_x, $boxw = $box->getWidth());
     $y = Helper::percentValue($this->_y, $boxh = $box->getHeight());
     $w = Helper::percentValue($this->_width, $boxw);
     $h = Helper::percentValue($this->_height, $boxh);
     if ($this->_ratio) {
         switch ($this->_ratio) {
             case self::COVER:
                 Helper::scaleSize($w, $h, $box);
                 $w = $h = min($w, $h);
                 break;
             case self::CONTAIN:
                 Helper::scaleSize($w, $h, $box);
                 $max = max($w, $h);
                 $img = $imagine->create(new Box($max, $max), new Color(0, 100));
                 $img->paste($image, new Point(($max - $boxw) * 0.5, ($max - $boxh) * 0.5));
                 $image = $img;
                 return;
             default:
                 // custom ratio
                 $this->fitByRatio($w, $h, $w && $h ? $w / $h : 0);
                 if (!$w || !$h) {
                     throw new \RuntimeException('Invalid ratio supplied');
                 }
                 break;
         }
     } else {
         Helper::scaleSize($w, $h, $box);
     }
     $halfw = $w / 2;
     $halfh = $h / 2;
     if ($x + $halfw > $boxw) {
         $x = $boxw - $halfw;
     }
     if ($y + $halfh > $boxh) {
         $y = $boxh - $halfh;
     }
     if ($x < $halfw) {
         $x = $halfw;
     }
     if ($y < $halfh) {
         $y = $halfh;
     }
     $image->crop(new Point($x - $w / 2, $y - $h / 2), new Box($w, $h));
 }
예제 #12
0
 /**
  * Re-sizes the image. If $height is not specified, it will default to $width, creating a square.
  *
  * @param int      $targetWidth
  * @param int|null $targetHeight
  *
  * @return Image
  */
 public function resize($targetWidth, $targetHeight = null)
 {
     $this->normalizeDimensions($targetWidth, $targetHeight);
     if ($this->_isAnimatedGif) {
         // Create a new image instance to avoid object references messing up our dimensions.
         $newSize = new \Imagine\Image\Box($targetWidth, $targetHeight);
         $gif = $this->_instance->create($newSize);
         $gif->layers()->remove(0);
         foreach ($this->_image->layers() as $layer) {
             $resizedLayer = $layer->resize($newSize, $this->_getResizeFilter());
             $gif->layers()->add($resizedLayer);
         }
         $this->_image = $gif;
     } else {
         if (craft()->images->isImagick()) {
             $this->_image->smartResize(new \Imagine\Image\Box($targetWidth, $targetHeight), (bool) craft()->config->get('preserveImageColorProfiles'), $this->_quality);
         } else {
             $this->_image->resize(new \Imagine\Image\Box($targetWidth, $targetHeight), $this->_getResizeFilter());
         }
     }
     return $this;
 }
예제 #13
0
 /**
  * Process image resizing, with borders or cropping. If $dest_width and $dest_height
  * are both null, no resize is performed.
  *
  * @param  ImagineInterface $imagine     the Imagine instance
  * @param  ImageInterface   $image       the image to process
  * @param  int              $dest_width  the required width
  * @param  int              $dest_height the required height
  * @param  int              $resize_mode the resize mode (crop / bands / keep image ratio)p
  * @param  string           $bg_color    the bg_color used for bands
  * @param  bool             $allow_zoom  if true, image may be zoomed to matchrequired size. If false, image is not zoomed.
  * @return ImageInterface   the resized image.
  */
 protected function applyResize(ImagineInterface $imagine, ImageInterface $image, $dest_width, $dest_height, $resize_mode, $bg_color, $allow_zoom = false)
 {
     if (!(is_null($dest_width) && is_null($dest_height))) {
         $width_orig = $image->getSize()->getWidth();
         $height_orig = $image->getSize()->getHeight();
         $ratio = $width_orig / $height_orig;
         if (is_null($dest_width)) {
             $dest_width = $dest_height * $ratio;
         }
         if (is_null($dest_height)) {
             $dest_height = $dest_width / $ratio;
         }
         if (is_null($resize_mode)) {
             $resize_mode = self::KEEP_IMAGE_RATIO;
         }
         $width_diff = $dest_width / $width_orig;
         $height_diff = $dest_height / $height_orig;
         $delta_x = $delta_y = $border_width = $border_height = 0;
         if ($width_diff > 1 && $height_diff > 1) {
             $resize_width = $width_orig;
             $resize_height = $height_orig;
             // When cropping, be sure to always generate an image which is
             //  no smaller than the required size, zooming it if required.
             if ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
                 if ($allow_zoom) {
                     if ($width_diff > $height_diff) {
                         $resize_width = $dest_width;
                         $resize_height = intval($height_orig * $dest_width / $width_orig);
                         $delta_y = ($resize_height - $dest_height) / 2;
                     } else {
                         $resize_height = $dest_height;
                         $resize_width = intval($width_orig * $resize_height / $height_orig);
                         $delta_x = ($resize_width - $dest_width) / 2;
                     }
                 } else {
                     // No zoom : final image may be smaller than the required size.
                     $dest_width = $resize_width;
                     $dest_height = $resize_height;
                 }
             }
         } elseif ($width_diff > $height_diff) {
             // Image height > image width
             $resize_height = $dest_height;
             $resize_width = intval($width_orig * $resize_height / $height_orig);
             if ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
                 $resize_width = $dest_width;
                 $resize_height = intval($height_orig * $dest_width / $width_orig);
                 $delta_y = ($resize_height - $dest_height) / 2;
             } elseif ($resize_mode != self::EXACT_RATIO_WITH_BORDERS) {
                 $dest_width = $resize_width;
             }
         } else {
             // Image width > image height
             $resize_width = $dest_width;
             $resize_height = intval($height_orig * $dest_width / $width_orig);
             if ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
                 $resize_height = $dest_height;
                 $resize_width = intval($width_orig * $resize_height / $height_orig);
                 $delta_x = ($resize_width - $dest_width) / 2;
             } elseif ($resize_mode != self::EXACT_RATIO_WITH_BORDERS) {
                 $dest_height = $resize_height;
             }
         }
         $image->resize(new Box($resize_width, $resize_height));
         if ($resize_mode == self::EXACT_RATIO_WITH_BORDERS) {
             $border_width = intval(($dest_width - $resize_width) / 2);
             $border_height = intval(($dest_height - $resize_height) / 2);
             $canvas = new Box($dest_width, $dest_height);
             return $imagine->create($canvas, $bg_color)->paste($image, new Point($border_width, $border_height));
         } elseif ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
             $image->crop(new Point($delta_x, $delta_y), new Box($dest_width, $dest_height));
         }
     }
     return $image;
 }
예제 #14
0
 /**
  * @param string $inFilename
  * @param Image  $spec
  * @param string $outFilename
  */
 public function convert($inFilename, Specification $spec, $outFilename)
 {
     $image = $this->imagine->open($inFilename);
     $options = array();
     if ($spec->getFormat()) {
         $options['format'] = $spec->getFormat();
     }
     if ($spec->getQuality()) {
         if (!empty($options['format']) && $options['format'] === 'png') {
             $options['png_compression_level'] = floor($spec->getQuality() / 10);
             $options['png_compression_filter'] = $spec->getQuality() % 10;
         } elseif (!empty($options['format']) && $options['format'] === 'jpg') {
             $options['jpeg_quality'] = $spec->getQuality();
         }
     }
     if ($spec->getColorspace()) {
         $image->strip();
         switch ($spec->getColorspace()) {
             case 'cmyk':
                 $image->usePalette(new CMYK());
                 break;
             case 'grayscale':
                 $image->usePalette(new Grayscale());
                 break;
             default:
                 $image->usePalette(new RGB());
         }
     }
     if ($spec->getScale()) {
         if ($spec->getScale() === 'up') {
             // only scale up
         } elseif ($spec->getScale() === 'down') {
             // only scale down
         }
     }
     $method = $spec->getResizeMode();
     if ($method === Image::RESIZE_METHOD_WIDTH) {
         $specSize = $image->getSize()->widen($spec->getWidth());
         $image->resize($specSize);
     } elseif ($method === Image::RESIZE_METHOD_HEIGHT) {
         $specSize = $image->getSize()->heighten($spec->getHeight());
         $image->resize($specSize);
     } elseif ($method === Image::RESIZE_METHOD_EXACT) {
         $specSize = new Box($spec->getWidth(), $spec->getHeight());
         $image->resize($specSize);
     } elseif ($method === Image::RESIZE_METHOD_FIT) {
         $specSize = new Box($spec->getWidth(), $spec->getHeight());
         $image = $image->thumbnail($specSize, ImageInterface::THUMBNAIL_INSET);
     } elseif ($method === Image::RESIZE_METHOD_EXACT_FIT) {
         $specSize = new Box($spec->getWidth(), $spec->getHeight());
         $layer = $image->thumbnail($specSize, ImageInterface::THUMBNAIL_INSET);
         $layerSize = $layer->getSize();
         $palette = new RGB();
         if ($spec->getBackgroundColor()) {
             $color = $palette->color($spec->getBackgroundColor(), 100);
         } else {
             $color = $palette->color('#fff', 0);
         }
         $image = $this->imagine->create($specSize, $color);
         $image->paste($layer, new Point(floor(($specSize->getWidth() - $layerSize->getWidth()) / 2), floor(($specSize->getHeight() - $layerSize->getHeight()) / 2)));
     } elseif ($method === Image::RESIZE_METHOD_CROP) {
         $specSize = new Box($spec->getWidth(), $spec->getHeight());
         $imageSize = $image->getSize();
         if (!$specSize->contains($imageSize)) {
             $ratios = array($specSize->getWidth() / $imageSize->getWidth(), $specSize->getHeight() / $imageSize->getHeight());
             $ratio = max($ratios);
             if (!$imageSize->contains($specSize)) {
                 $imageSize = new Box(min($imageSize->getWidth(), $specSize->getWidth()), min($imageSize->getHeight(), $specSize->getHeight()));
             } else {
                 $imageSize = $imageSize->scale($ratio);
                 $image->resize($imageSize);
             }
             if ($spec->getCenterX() && $spec->getCenterY()) {
                 $point = new Point($spec->getCenterX(), $spec->getCenterY());
             } else {
                 $point = new Point(max(0, round(($imageSize->getWidth() - $specSize->getWidth()) / 2)), max(0, round(($imageSize->getHeight() - $specSize->getHeight()) / 2)));
             }
             $image->crop($point, $specSize);
         }
     }
     $image->save($outFilename, $options);
 }
예제 #15
0
 /**
  * (non-PHPdoc)
  * @see Imagine\Filter\FilterInterface::apply()
  */
 public function apply(ImageInterface $image)
 {
     $canvas = $this->imagine->create($this->size, $this->background);
     $canvas->paste($image, $this->placement);
     return $canvas;
 }
 protected function setUp()
 {
     $this->imagine = new Imagine();
     $this->gcImage = $this->imagine->create(new Box(self::GC_WIDTH, self::GC_HEIGHT), new Color(self::GC_COLOR));
     $this->gc = new GraphicsContext($this->imagine, $this->gcImage);
 }
예제 #17
0
파일: Image.php 프로젝트: alex63530/thelia
 /**
  * Process image resizing, with borders or cropping. If $dest_width and $dest_height
  * are both null, no resize is performed.
  *
  * @param  ImagineInterface $imagine     the Imagine instance
  * @param  ImageInterface   $image       the image to process
  * @param  int              $dest_width  the required width
  * @param  int              $dest_height the required height
  * @param  int              $resize_mode the resize mode (crop / bands / keep image ratio)p
  * @param  string           $bg_color    the bg_color used for bands
  * @return ImageInterface   the resized image.
  */
 protected function applyResize(ImagineInterface $imagine, ImageInterface $image, $dest_width, $dest_height, $resize_mode, $bg_color)
 {
     if (!(is_null($dest_width) && is_null($dest_height))) {
         $width_orig = $image->getSize()->getWidth();
         $height_orig = $image->getSize()->getHeight();
         if (is_null($dest_width)) {
             $dest_width = $width_orig;
         }
         if (is_null($dest_height)) {
             $dest_height = $height_orig;
         }
         if (is_null($resize_mode)) {
             $resize_mode = self::KEEP_IMAGE_RATIO;
         }
         $width_diff = $dest_width / $width_orig;
         $height_diff = $dest_height / $height_orig;
         $delta_x = $delta_y = $border_width = $border_height = 0;
         if ($width_diff > 1 && $height_diff > 1) {
             $next_width = $width_orig;
             $next_height = $height_orig;
             $dest_width = $resize_mode == self::EXACT_RATIO_WITH_BORDERS ? $dest_width : $next_width;
             $dest_height = $resize_mode == self::EXACT_RATIO_WITH_BORDERS ? $dest_height : $next_height;
         } elseif ($width_diff > $height_diff) {
             // Image height > image width
             $next_height = $dest_height;
             $next_width = intval($width_orig * $next_height / $height_orig);
             if ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
                 $next_width = $dest_width;
                 $next_height = intval($height_orig * $dest_width / $width_orig);
                 $delta_y = ($next_height - $dest_height) / 2;
             } elseif ($resize_mode != self::EXACT_RATIO_WITH_BORDERS) {
                 $dest_width = $next_width;
             }
         } else {
             // Image width > image height
             $next_width = $dest_width;
             $next_height = intval($height_orig * $dest_width / $width_orig);
             if ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
                 $next_height = $dest_height;
                 $next_width = intval($width_orig * $next_height / $height_orig);
                 $delta_x = ($next_width - $dest_width) / 2;
             } elseif ($resize_mode != self::EXACT_RATIO_WITH_BORDERS) {
                 $dest_height = $next_height;
             }
         }
         $image->resize(new Box($next_width, $next_height));
         if ($resize_mode == self::EXACT_RATIO_WITH_BORDERS) {
             $border_width = intval(($dest_width - $next_width) / 2);
             $border_height = intval(($dest_height - $next_height) / 2);
             $canvas = new Box($dest_width, $dest_height);
             return $imagine->create($canvas, $bg_color)->paste($image, new Point($border_width, $border_height));
         } elseif ($resize_mode == self::EXACT_RATIO_WITH_CROP) {
             $image->crop(new Point($delta_x, $delta_y), new Box($dest_width, $dest_height));
         }
     }
     return $image;
 }
 /**
  * @param array $images
  * @param string $uniqueId
  * @param int [optional] $width
  * @param int [optional] $height
  * @param int [optional] $limit
  * @return string | false
  */
 public function create($images, $uniqueId, $width = null, $height = null, $limit = 5)
 {
     if (count($images) < 1) {
         return false;
     }
     if ($this->hasCached($uniqueId) === true) {
         return $this->getHttpPath($uniqueId);
     }
     if (count($images) < $limit) {
         $limit = count($images);
     }
     $getMax = function ($key) {
         return function ($images, $item) use($key) {
             $processed = [];
             if (is_array($images)) {
                 foreach ($images as $image) {
                     if ($item->{$key} < $image->{$key}) {
                         $processed[] = $image;
                     }
                 }
             } else {
                 return $images;
             }
             return count($processed) ? $processed : $item->{$key};
         };
     };
     $maxWidth = array_reduce($images, $getMax('width'), $images);
     $maxHeight = array_reduce($images, $getMax('height'), $images);
     if ($width == null && $height === null) {
         $sqrt = sqrt($limit);
         $width = ceil(sqrt($limit)) * $maxWidth;
         $height = round($sqrt) * $maxHeight;
     } else {
         if ($width != null && $height === null) {
             $height = ceil($limit / ceil($width / $maxWidth)) * $maxHeight;
         } else {
             if ($width == null && $height != null) {
                 $width = ceil($limit / ceil($height / $maxHeight)) * $maxWidth;
             } else {
                 $height = ceil($height / $maxHeight) * $maxHeight;
                 $width = ceil($width / $maxWidth) * $maxWidth;
             }
         }
     }
     $collage = $this->imageService->create(new Image\Box($width, $height));
     $x = 0;
     $y = 0;
     foreach ($images as $image) {
         $photo = $this->imageService->open($image->url);
         // paste photo at current position
         $collage->paste($photo, new Image\Point($x, $y));
         // move position by 30px to the right
         $x += $maxWidth;
         if ($x >= $width) {
             // we reached the right border of our collage, so advance to the
             // next row and reset our column to the left.
             $y += $maxHeight;
             $x = 0;
         }
         if ($y >= $height) {
             break;
             // done
         }
     }
     try {
         $collage->save($this->getFilePath($uniqueId));
         return $this->getHttpPath($uniqueId);
     } catch (\Exception $ex) {
         return false;
     }
 }