Php Sonata媒体包-如何编写自定义图像大小调整器

Php Sonata媒体包-如何编写自定义图像大小调整器,php,symfony,symfony-sonata,Php,Symfony,Symfony Sonata,我正在使用,我需要为图像大小调整器编写一个特定的行为,因为默认的SimpleResizer和SquareResizer类不适合我的需要 我想要一个简单的图像大小调整器,如果我同时指定宽度和高度参数,它可以让我精确地调整图像大小。我还希望,如果我没有指定height参数,它可以回退到简单的调整器行为 我刚刚搜索了文档,但没有找到解决方案。首先,您必须在捆绑包中创建一个resizer服务,以便将其放入Sonata Media bundle配置中 # Acme/Bundle/CoreBundle/Re

我正在使用,我需要为图像大小调整器编写一个特定的行为,因为默认的SimpleResizerSquareResizer类不适合我的需要

我想要一个简单的图像大小调整器,如果我同时指定
宽度
高度
参数,它可以让我精确地调整图像大小。我还希望,如果我没有指定
height
参数,它可以回退到简单的调整器行为


我刚刚搜索了文档,但没有找到解决方案。

首先,您必须在捆绑包中创建一个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]
在本例中,第二个服务参数必须是“outbound”。允许的参数是
ImageInterface::THUMBNAIL\u INSET
ImageInterface::THUMBNAIL\u 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);
        }
    }

谢谢@fra_casula,非常翔实和有益的解释。除了你的问题和答案,我还需要为我的大小调整器添加自定义区域。想象一下Facebook的个人资料照片编辑器,你可以在通过用户界面上传照片后设置特定的界限。有没有办法做到这一点?谢谢。在这种情况下,您需要在通过用户界面进行任何裁剪/调整大小之前上载图像。因此,在第一次上传中,您可能不需要任何大小调整器。在第一次上传之后,您可以使用jquery插件(如Jcrop)来提供用户界面,如果您使用SonatAdminBundle,您可以指定一个自定义CRUD控制器来处理这种类型的定制。最后,考虑RESIZER甚至是一个服务,所以尝试通过@ Service Engy容器在您的服务,以捕捉请求,并读取从JSGRUP提供的调整大小的数据。我也尝试创建一个自定义RISSIZER。缩放裁剪样式大小调整器。你的榜样很有魅力。首先,我复制粘贴了它,并计划在上面编写代码。但看起来您已经在这里实现了缩放裁剪大小调整器?您可以通过从应用于高度的原始纵横比计算宽度来将宽度设置为可选值。通过这种方式,您可以将“RuntimeException”行(38)替换为:
$settings['width']=$settings['height']*$media->getWidth()/$media->getHeight()
public function resize()
中改为
if(!(isset($settings['width'])和&$settings['width'])
如果(!(isset($settings['width'])和&!(isset($settings['height'])和&$settings['height'])
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