Skip to content

Instantly share code, notes, and snippets.

@djaney
Last active September 21, 2015 02:20
Show Gist options
  • Select an option

  • Save djaney/6b3edd1500edfaad85ea to your computer and use it in GitHub Desktop.

Select an option

Save djaney/6b3edd1500edfaad85ea to your computer and use it in GitHub Desktop.
Symfony2 sonata media bundle custom re-sizer that does not lose the image ratio.
<?php namespace Application\Sonata\MediaBundle\Resizer;
use Imagine\Image\ImagineInterface;
use Imagine\Image\Box;
use Gaufrette\File;
use Sonata\MediaBundle\Model\MediaInterface;
use Sonata\MediaBundle\Resizer\ResizerInterface;
use Imagine\Image\ImageInterface;
use Imagine\Image\Point;
use Imagine\Exception\InvalidArgumentException;
use Sonata\MediaBundle\Metadata\MetadataBuilderInterface;
class ExactResizer implements ResizerInterface
{
protected $adapter;
protected $mode;
protected $metadata;
/**
* @param ImagineInterface $adapter
* @param string $mode
*/
public function __construct(ImagineInterface $adapter, $mode, MetadataBuilderInterface $metadata)
{
$this->adapter = $adapter;
$this->mode = $mode;
$this->metadata = $metadata;
}
/**
* {@inheritdoc}
*/
public function resize(MediaInterface $media, File $in, File $out, $format, array $settings)
{
if (!(isset($settings['width']) && $settings['width']))
throw new \RuntimeException(sprintf('Width parameter is missing in context "%s" for provider "%s"', $media->getContext(), $media->getProviderName()));
$image = $this->adapter->load($in->getContent());
$size = $media->getBox();
if (isset($settings['height']) && $settings['height']){
$ratio = $settings['width']/$settings['height'];
if($settings['width']>$settings['height']){
$width = $size->getWidth();
$height = $width/$ratio;
}else{
$height = $size->getHeight();
$width = $height*$ratio;
}
// re adjust if too big
if($width>$size->getWidth()){
$width = $size->getWidth();
$height = $width/$ratio;
}
if($height>$size->getHeight()){
$height = $size->getHeight();
$width = $height*$ratio;
}
$cropBox = new Box($width,$height);
$y = $size->getHeight() / 2 - $height / 2;
$x = $size->getWidth() / 2 - $width / 2;
if($y<0) $y = 0;
if($x<0) $x = 0;
$image->crop(new Point($x, $y), $cropBox);
$image->resize(new Box($settings['width'],$settings['height']));
}else{
$thumbBox = $this->getBox($media, $settings);
$image->thumbnail($thumbBox, $this->mode);
}
$content = $image->get($format, array('quality' => $settings['quality']));
$out->setContent($content, $this->metadata->get($media, $out->getName()));
}
/**
* {@inheritdoc}
*/
public function getBox(MediaInterface $media, array $settings)
{
$size = $media->getBox();
$hasWidth = isset($settings['width']) && $settings['width'];
$hasHeight = isset($settings['height']) && $settings['height'];
if (!$hasWidth && !$hasHeight)
throw new \RuntimeException(sprintf('Width/Height parameter is missing in context "%s" for provider "%s". Please add at least one parameter.', $media->getContext(), $media->getProviderName()));
if ($hasWidth && $hasHeight)
return new Box($settings['width'], $settings['height']);
if (!$hasHeight)
$settings['height'] = intval($settings['width'] * $size->getHeight() / $size->getWidth());
if (!$hasWidth)
$settings['width'] = intval($settings['height'] * $size->getWidth() / $size->getHeight());
return $this->computeBox($media, $settings);
}
/**
* @throws InvalidArgumentException
*
* @param MediaInterface $media
* @param array $settings
*
* @return Box
*/
private function computeBox(MediaInterface $media, array $settings)
{
if ($this->mode !== ImageInterface::THUMBNAIL_INSET && $this->mode !== ImageInterface::THUMBNAIL_OUTBOUND)
throw new InvalidArgumentException('Invalid mode specified');
$size = $media->getBox();
$ratios = [
$settings['width'] / $size->getWidth(),
$settings['height'] / $size->getHeight()
];
if ($this->mode === ImageInterface::THUMBNAIL_INSET)
$ratio = min($ratios);
else
$ratio = max($ratios);
return $size->scale($ratio);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment