Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flip filter implementation to core #920

Merged
merged 2 commits into from
May 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions Imagine/Filter/Loader/FlipFilterLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

/*
* This file is part of the `liip/LiipImagineBundle` project.
*
* (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
*
* For the full copyright and license information, please view the LICENSE.md
* file that was distributed with this source code.
*/

namespace Liip\ImagineBundle\Imagine\Filter\Loader;

use Imagine\Image\ImageInterface;
use Liip\ImagineBundle\Utility\OptionsResolver\OptionsResolver;
use Liip\ImagineBundle\Exception\InvalidArgumentException;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\Exception\ExceptionInterface;

class FlipFilterLoader implements LoaderInterface
{
/**
* @param ImageInterface $image
* @param array $options
*
* @return ImageInterface
*/
public function load(ImageInterface $image, array $options = array())
{
$options = $this->sanitizeOptions($options);

return $options['axis'] === 'x' ? $image->flipHorizontally() : $image->flipVertically();
}

/**
* @param array $options
*
* @return array
*/
private function sanitizeOptions(array $options)
{
$resolver = new OptionsResolver();
$resolver->setDefault('axis', 'x');
$resolver->setAllowedValues('axis', array('x', 'horizontal', 'y', 'vertical'));
$resolver->setNormalizer('axis', function (Options $options, $value) {
return $value === 'horizontal' ? 'x' : ($value === 'vertical' ? 'y' : $value);
});

try {
return $resolver->resolve($options);
} catch (ExceptionInterface $e) {
throw new InvalidArgumentException('The "axis" option must be set to "x", "horizontal", "y", or "vertical".');
}
}
}
41 changes: 27 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,39 @@
|:----------------------:|:-----------------------:|:-----------------------:|:-----------------------:|:-----------------------:|
| [![Travis](https://src.run/shield/liip/LiipImagineBundle/1.0/travis.svg)](https://src.run/service/liip/LiipImagineBundle/1.0/travis) | [![Style CI](https://src.run/shield/liip/LiipImagineBundle/1.0/styleci.svg)](https://src.run/service/liip/LiipImagineBundle/1.0/styleci) | [![Coverage](https://src.run/shield/liip/LiipImagineBundle/1.0/coveralls.svg)](https://src.run/service/liip/LiipImagineBundle/1.0/coveralls) | [![Downloads](https://src.run/shield/liip/LiipImagineBundle/packagist_dt.svg)](https://src.run/service/liip/LiipImagineBundle/packagist) | [![Latest Stable Version](https://src.run/shield/liip/LiipImagineBundle/packagist_v.svg)](https://src.run/service/liip/LiipImagineBundle/packagist) |

*This bundle provides an image manipulation abstraction toolkit for
[Symfony](http://symfony.com/)-based projects.*
*This bundle provides an image manipulation abstraction toolkit for [Symfony](http://symfony.com/)-based projects.*

## Overview

- [Filter Sets](http://symfony.com/doc/master/bundles/LiipImagineBundle/basic-usage.html):
Using any Symfony-supported configuration language (such as YML and XML),
you can create *filter set* definitions that specify transformation routines.
These include a set of *filters* and *post-processors*, as well as other,
optional parameters.
Using any Symfony-supported configuration language (such as YML and XML), you can create *filter set* definitions that
specify transformation routines. These definitions include a set of
*[filters](http://symfony.com/doc/current/bundles/LiipImagineBundle/filters.html)* and
*[post-processors](http://symfony.com/doc/current/bundles/LiipImagineBundle/post-processors.html)*,
as well as other optional parameters.

- [Filters](http://symfony.com/doc/master/bundles/LiipImagineBundle/filters.html):
Many built-in filters are provided, allowing the application of common
transformations. Examples include `thumbnail`, `scale`, `crop`, `strip`, `watermark`,
and many more. Additionally, [custom filters](http://symfony.com/doc/master/bundles/LiipImagineBundle/filters.html#filter-custom)
are supported.
Image transformations are applied using *filters*. A set of
[build-in filters](http://symfony.com/doc/current/bundles/LiipImagineBundle/filters.html) are provided by the bundle,
implementing the most common transformations; examples include
[thumbnail](http://symfony.com/doc/current/bundles/LiipImagineBundle/filters/sizing.html#thumbnails),
[scale](http://symfony.com/doc/current/bundles/LiipImagineBundle/filters/sizing.html#scale),
[crop](http://symfony.com/doc/current/bundles/LiipImagineBundle/filters/sizing.html#cropping-images),
[flip](http://symfony.com/doc/current/bundles/LiipImagineBundle/filters/orientation.html#flip),
[strip](http://symfony.com/doc/current/bundles/LiipImagineBundle/filters/general.html#strip), and
[watermark](http://symfony.com/doc/current/bundles/LiipImagineBundle/filters/general.html#watermark).
For more advances transformations, you can easily create your own
[custom filters](http://symfony.com/doc/master/bundles/LiipImagineBundle/filters.html#filter-custom).

- [Post-Processors](http://symfony.com/doc/master/bundles/LiipImagineBundle/post-processors.html):
This component allows for the modification of the resulting binary file
created by filters. Examples include `jpegoptim`, `optipng`, `cjpeg`,
and `pngquant`. Additionally, [custom post-processors](http://symfony.com/doc/master/bundles/LiipImagineBundle/post-processors.html#post-processors-custom)
are supported.
Modification of the resulting binary image file (created from your *filters*) are handled by *post-processors*.
Examples include
[JPEG Optim](http://symfony.com/doc/current/bundles/LiipImagineBundle/post-processors/jpeg-optim.html),
[Moz JPEG](http://symfony.com/doc/current/bundles/LiipImagineBundle/post-processors/jpeg-moz.html),
[Opti PNG](http://symfony.com/doc/current/bundles/LiipImagineBundle/post-processors/png-opti.html), and
[PNG Quant](http://symfony.com/doc/current/bundles/LiipImagineBundle/post-processors/png-quant.html). Just like filters
you can easily create your own
[custom post-processors](http://symfony.com/doc/master/bundles/LiipImagineBundle/post-processors.html#post-processors-custom).


### Example
Expand Down
5 changes: 5 additions & 0 deletions Resources/config/imagine.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<parameter key="liip_imagine.filter.loader.downscale.class">Liip\ImagineBundle\Imagine\Filter\Loader\DownscaleFilterLoader</parameter>
<parameter key="liip_imagine.filter.loader.auto_rotate.class">Liip\ImagineBundle\Imagine\Filter\Loader\AutoRotateFilterLoader</parameter>
<parameter key="liip_imagine.filter.loader.rotate.class">Liip\ImagineBundle\Imagine\Filter\Loader\RotateFilterLoader</parameter>
<parameter key="liip_imagine.filter.loader.flip.class">Liip\ImagineBundle\Imagine\Filter\Loader\FlipFilterLoader</parameter>
<parameter key="liip_imagine.filter.loader.interlace.class">Liip\ImagineBundle\Imagine\Filter\Loader\InterlaceFilterLoader</parameter>

<!-- Data loaders' classes -->
Expand Down Expand Up @@ -221,6 +222,10 @@
<tag name="liip_imagine.filter.loader" loader="rotate" />
</service>

<service id="liip_imagine.filter.loader.flip" class="%liip_imagine.filter.loader.flip.class%">
<tag name="liip_imagine.filter.loader" loader="flip" />
</service>

<service id="liip_imagine.filter.loader.interlace" class="%liip_imagine.filter.loader.interlace.class%">
<tag name="liip_imagine.filter.loader" loader="interlace" />
</service>
Expand Down
41 changes: 39 additions & 2 deletions Resources/doc/filters/orientation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,43 @@ Rotate Options
Sets the "rotation angle" that defines the degree to rotate the image. Must be a
positive number.

.. _`BoxInterface`: http://imagine.readthedocs.io/en/latest/usage/coordinates.html#boxinterface
.. _`Imagine Library`: http://imagine.readthedocs.io/en/latest/

.. _filter-flip:

Flip
----

The built-in ``flip`` filter performs orientation transformations (specifically
image flipping). This filter exposes `flip options`_ which may be used to
configure its behavior.

Example configuration:

.. code-block:: yaml

# app/config/config.yml

liip_imagine:
filter_sets:

# name our filter set "my_flip_filter"
my_flip_filter:
filters:

# use the "flip" filter
flip:

# set the axis to flip on
axis: x


Flip Options
~~~~~~~~~~~~

:strong:`axis:` ``string``
Sets the "flip axis" that defines the axis on which to flip the image. Valid values:
``x``, ``horizontal``, ``y``, ``vertical``.


.. _`BoxInterface`: http://imagine.readthedocs.io/en/latest/usage/coordinates.html#boxinterface
.. _`Imagine Library`: http://imagine.readthedocs.io/en/latest/
29 changes: 29 additions & 0 deletions Tests/Functional/Imagine/Filter/Loader/FlipFilterLoaderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/*
* This file is part of the `liip/LiipImagineBundle` project.
*
* (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
*
* For the full copyright and license information, please view the LICENSE.md
* file that was distributed with this source code.
*/

namespace Liip\ImagineBundle\Tests\Functional\Imagine\Filter\Loader;

use Liip\ImagineBundle\Tests\Functional\AbstractWebTestCase;

/**
* @covers \Liip\ImagineBundle\Imagine\Filter\Loader\FlipFilterLoader
*/
class FlipFilterLoaderTest extends AbstractWebTestCase
{
public function testCouldBeGetFromContainerAsService()
{
$this->createClient();
$this->assertInstanceOf(
'\Liip\ImagineBundle\Imagine\Filter\Loader\FlipFilterLoader',
self::$kernel->getContainer()->get('liip_imagine.filter.loader.flip')
);
}
}
93 changes: 93 additions & 0 deletions Tests/Imagine/Filter/Loader/FlipFilterLoaderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

/*
* This file is part of the `liip/LiipImagineBundle` project.
*
* (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
*
* For the full copyright and license information, please view the LICENSE.md
* file that was distributed with this source code.
*/

namespace Liip\ImagineBundle\Tests\Filter;

use Liip\ImagineBundle\Imagine\Filter\Loader\FlipFilterLoader;
use Liip\ImagineBundle\Tests\AbstractTest;

/**
* @covers \Liip\ImagineBundle\Imagine\Filter\Loader\FlipFilterLoader
*/
class FlipFilterLoaderTest extends AbstractTest
{
/**
* @return array
*/
public static function provideLoadWithAxisXOptionData()
{
return array(
array('x'),
array('horizontal'),
);
}

/**
* @param string $axis
*
* @dataProvider provideLoadWithAxisXOptionData
*/
public function testLoadWithAxisXOption($axis)
{
$image = $this->getImageInterfaceMock();
$image->expects($this->once())
->method('flipHorizontally')
->willReturn($image);

$this->createFlipFilterLoaderInstance()->load($image, array('axis' => $axis));
}

/**
* @return array
*/
public static function provideLoadWithAxisYOptionData()
{
return array(
array('y'),
array('vertical'),
);
}

/**
* @param string $axis
*
* @dataProvider provideLoadWithAxisYOptionData
*/
public function testLoadWithAxisYOption($axis)
{
$image = $this->getImageInterfaceMock();
$image->expects($this->once())
->method('flipVertically')
->willReturn($image);

$this->createFlipFilterLoaderInstance()->load($image, array('axis' => $axis));
}

/**
* @expectedException \Liip\ImagineBundle\Exception\InvalidArgumentException
* @expectedExceptionMessage The "axis" option must be set to "x", "horizontal", "y", or "vertical".
*/
public function testThrowsOnInvalidOptions()
{
$loader = new FlipFilterLoader();
$loader->load($this->getImageInterfaceMock(), array(
'axis' => 'invalid',
));
}

/**
* @return FlipFilterLoader
*/
private function createFlipFilterLoaderInstance()
{
return new FlipFilterLoader();
}
}
Loading