我正在使用Sonata Media Bundle,我需要为图像缩放器编写特定的行为,因为默认的 SimpleResizer 和 SquareResizer 类不会适合我的需要。
我想要一个简单的图像缩放器,如果我同时指定width
和height
参数,则可以让我精确调整图像大小。如果我没有指定height
参数,我还希望它可以回退到简单缩放器行为。
我刚刚搜索了文档但我无法找到解决方案。
答案 0 :(得分:11)
首先,您必须在捆绑包中创建一个resizer服务,以便将其放入 Sonata Media Bundle 配置中。
# Acme/Bundle/CoreBundle/Resources/config/services.yml
services:
sonata.media.resizer.custom:
class: Acme\Bundle\CoreBundle\Resizer\CustomResizer
arguments: [@sonata.media.adapter.image.gd, 'outbound', @sonata.media.metadata.proxy]
在这种情况下,第二个服务参数必须是“出站”。允许的参数为ImageInterface::THUMBNAIL_INSET
和ImageInterface::THUMBNAIL_OUTBOUND
。
现在是Acme\Bundle\CoreBundle\Resizer\CustomResizer
代码:
<?php
namespace Acme\Bundle\CoreBundle\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\Exception\InvalidArgumentException;
use Sonata\MediaBundle\Metadata\MetadataBuilderInterface;
class CustomResizer 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());
$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();
$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);
}
}
做得好。您的服务已定义。你必须在app/config.yml
中链接它,一切都完成了。
我已经包含了整个sonata_media
配置以提供一个很好的示例,但请记住,您只需要最后三行。
sonata_media:
default_context: default
db_driver: doctrine_orm # or doctrine_mongodb, doctrine_phpcr
contexts:
default: # the default context is mandatory
providers:
- sonata.media.provider.dailymotion
- sonata.media.provider.youtube
- sonata.media.provider.image
- sonata.media.provider.file
formats:
small: { width: 100, height: 100, quality: 70 }
big: { width: 500, height: 300, quality: 70 }
download:
strategy: sonata.media.security.public_strategy
cdn:
server:
path: /uploads/media # http://media.sonata-project.org/
filesystem:
local:
directory: %kernel.root_dir%/../web/uploads/media
create: true
providers:
image:
resizer: sonata.media.resizer.custom # THIS IS OUR NEW RESIZER SERVICE