Sonata Media fixed dimensions resizer
We assume that you have SonataMediaBundle up and running in your project and have extended the bundle with SonataEasyExtendsBundle in your Application folder.
Next, add the following class in your extended bundle in a Resizer folder
<!--?php
namespace ApplicationSonataMediaBundleResizer;
use ImagineImageImagineInterface;
use ImagineImageBox;
use GaufretteFile;
use SonataMediaBundleModelMediaInterface;
use ImagineImageImageInterface;
use ImagineExceptionInvalidArgumentException;
use SonataMediaBundleMetadataMetadataBuilderInterface;
use SonataMediaBundleResizerResizerInterface;
class FixedDimensionsResizer 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'])) {
throw new RuntimeException(sprintf('Width parameter is missing in context "%s" for provider "%s"', $media->getContext(), $media->getProviderName()));
}
$image = $this->adapter->load($in->getContent());
$content = $image
->thumbnail($this->getBox($media, $settings), $this->mode)
->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();
if ($settings['width'] == null && $settings['height'] == null) {
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($settings['constraint'] === false){
return new Box($settings['width'], $settings['height']);
}
if ($settings['height'] == null) {
$settings['height'] = (int) ($settings['width'] * $size->getHeight() / $size->getWidth());
}
if ($settings['width'] == null) {
$settings['width'] = (int) ($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 = array(
$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);
}
}
Then, add the following service in your config.yml
services:
sonata.media.resizer.fixedDimensions:
class: ApplicationSonataMediaBundleResizerFixedDimensionsResizer
arguments: [@sonata.media.adapter.image.gd, 'outbound', @sonata.media.metadata.proxy]
Finally enabled the provider in the sonata_media config
sonata_media:
[...]
providers:
image:
resizer: sonata.media.resizer.fixedDimensions
When you add a new context for your image you can now add the following parameter ton constraint your image dimensions to the width and height specified.
sonata_media:
[...]
contexts:
my_context:
providers:
- sonata.media.provider.image
formats:
small: { width: 400, height: 300, constraint: false}