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 filter to perform a relative resize, thus keeping the aspect ratio, and not exceeding a max width and a max height #206

Closed
wants to merge 3 commits into from
Closed
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
33 changes: 33 additions & 0 deletions Imagine/Filter/Loader/TwoWayRelativeResizeFilterLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Liip\ImagineBundle\Imagine\Filter\Loader;

use Imagine\Image\ImageInterface;

use Liip\ImagineBundle\Imagine\Filter\Loader\LoaderInterface;
use Liip\ImagineBundle\Imagine\Filter\TwoWayRelativeResize;

/**
* Loader for this bundle's two-way relative resize filter.
*
* @author Robert-Jan Bijl <[email protected]>
*/
class TwoWayRelativeResizeFilterLoader implements LoaderInterface
{
/**
* {@inheritDoc}
*/
public function load(ImageInterface $image, array $options = array())
{
$newHeight = isset($options['height']) ? $options['height'] : null;
$newWidth = isset($options['width']) ? $options['width'] : null;

// if no resize is given, just return the original image
if (null === $newHeight && null === $newWidth) {
return $image;
}

$filter = new TwoWayRelativeResize($newHeight, $newWidth);
return $filter->apply($image);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing empty line before return.

}
}
90 changes: 90 additions & 0 deletions Imagine/Filter/TwoWayRelativeResize.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace Liip\ImagineBundle\Imagine\Filter;

use Imagine\Filter\FilterInterface;
use Imagine\Image\Box;
use Imagine\Image\ImageInterface;

/**
* Filter for resizing an image, by keeping the aspect ratio and not exceeding the maxWidth and maxHeight parameters
*
* @author Robert-Jan Bijl <[email protected]>
*/
class TwoWayRelativeResize implements FilterInterface
{
/**
* @var int
*/
private $newWidth;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make all private members and methods protected. There is no reason to have them private.


/**
* @var int
*/
private $newHeight;

/**
* Constructor
*
* @param int $newHeight
* @param int $newWidth
*/
public function __construct($newHeight, $newWidth)
{
$this->newHeight = $newHeight;
$this->newWidth = $newWidth;
}

/**
* {@inheritDoc}
*/
public function apply(ImageInterface $image)
{
// if we don't have any new dimensions, return the original
if (null === $this->newHeight && null === $this->newWidth) {
return $image;
}

list($newWidth, $newHeight) = $this->calculateNewDimensions(
$image->getSize()->getWidth(),
$image->getSize()->getHeight(),
$this->newWidth,
$this->newHeight
);

// resize the image accordingly
return $image->resize(new Box($newWidth, $newHeight));
}

/**
* Calculates new width and height for an image by keeping the aspect ratio,
* not exceeding the maxWidth and maxHeight parameters
*
* @param int $width
* @param int $height
* @param int $maxWidth
* @param int $maxHeight
* @return array
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing empty line before @return.

*/
private function calculateNewDimensions($width, $height, $maxWidth, $maxHeight)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method should be public static, it's not bound to the state of this filter.

In addition, this method has to be tested.

{
$widthFactor = $maxWidth / $width;
$heightFactor = $maxHeight / $height;

// if one of the factors is 0, we need the other one.
if ($widthFactor === 0) {
$factor = $heightFactor;
} elseif ($heightFactor === 0) {
$factor = $widthFactor;
} else {
$factor = $widthFactor >= $heightFactor ? $heightFactor : $widthFactor;
}

// none of the new dimensions should be 0, so take care of that...
// this could happen, for example, if we scale done an image with a width of 1 px
$newWidth = max(array(intval($width * $factor), 1));
$newHeight = max(array(intval($height * $factor), 1));

return array($newWidth, $newHeight);
}
}
5 changes: 5 additions & 0 deletions Resources/config/imagine.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<!-- Filter loaders' classes -->

<parameter key="liip_imagine.filter.loader.relative_resize.class">Liip\ImagineBundle\Imagine\Filter\Loader\RelativeResizeFilterLoader</parameter>
<parameter key="liip_imagine.filter.loader.two_way_relative_resize.class">Liip\ImagineBundle\Imagine\Filter\Loader\TwoWayRelativeResizeFilterLoader</parameter>
<parameter key="liip_imagine.filter.loader.resize.class">Liip\ImagineBundle\Imagine\Filter\Loader\ResizeFilterLoader</parameter>
<parameter key="liip_imagine.filter.loader.thumbnail.class">Liip\ImagineBundle\Imagine\Filter\Loader\ThumbnailFilterLoader</parameter>
<parameter key="liip_imagine.filter.loader.crop.class">Liip\ImagineBundle\Imagine\Filter\Loader\CropFilterLoader</parameter>
Expand Down Expand Up @@ -126,6 +127,10 @@
<tag name="liip_imagine.filter.loader" loader="relative_resize" />
</service>

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

<service id="liip_imagine.filter.loader.resize" class="%liip_imagine.filter.loader.resize.class%">
<tag name="liip_imagine.filter.loader" loader="resize" />
</service>
Expand Down
28 changes: 28 additions & 0 deletions Resources/doc/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,34 @@ liip_imagine:
relative_resize: { scale: 2.5 } # Transforms 50x40 to 125x100
```

### The `two_way_relative_resize` filter

The `two_way_relative_resize` filter does the same thing `relative_resize` filter does,
but bounds the resulting image to a given height and/or width.

Given an input image sized 50x40 (width, height), consider the following
annotated configuration examples:

``` yaml
liip_imagine:
filter_sets:
my_only_height:
filters:
two_way_relative_resize: { height: 60 } # Transforms 50x40 to 75x60
my_only_width:
filters:
two_way_relative_resize: { width: 32 } # Transforms 50x40 to 32x26
my_width_wins:
filters:
two_way_relative_resize: { height: 60, width: 32 } # Transforms 50x40 to 32x26
my_height_wins:
filters:
two_way_relative_resize: { height: 60, width: 100 } # Transforms 50x40 to 75x60
my_no_change:
filters:
two_way_relative_resize: { } # Transforms 50x40 to 50x40, so actually does no transformation at all
```

### The `crop` filter

The crop filter, as the name implies, performs a crop transformation
Expand Down