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

[Filter] Add resolution filter loader #941

Merged
merged 2 commits into from
Aug 31, 2017

Conversation

robfrawley
Copy link
Collaborator

@robfrawley robfrawley commented May 22, 2017

Q A
Branch? 1.0
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #123, #938
License MIT
Doc PR

Many questions have been asked about "retina support" including #123 and #938. While I do not believe this bundle needs to enable any retina-specific functionality, as it already allows users to define any number of "filter sets" to generate any number of variations required, we should expose a filter to properly handle changing the image resolution, or "resampling".

This PR adds a ResampleFilterLoader that allows for creating different "filter sets" with different resulting image resolution (not to be confused with dimensions). Included is the ability to set x and y resolution integers, a corresponding unit (one of "inch" or "centimeter"), and an optional resampling filter (one of \Imagine\Image\ImageInterface::FILTER_%s).

This is a first-pass at adding resampling support, and as such I'm looking for comments about the manner in which this is implemented, specifically ResampleFilterLoader.php:45. The imagine-library package this bundle leverages for image transformations doesn't offer any means for resampling outside of saving out the file and reading it back in, which isn't the most straightforward manner to handle this operation.

Any thought on this implementation or ideas for an alternate?

This PR also introduces the following items intrinsically need for the filter loader implemented:

  • \Liip\ImagineBundle\Exception\Imagine\Filter\LoadFilterException
    Added for exceptions thrown from within filters loader implementations
  • Utility/OptionsResolver/OptionsResolver:setDefined()
    Added to allow for setting optional options that should not have a corresponding default value

Tests for all added functionality have now been implemented, as well. Additions to the documentation are now yet implemented.

@lsmith77 lsmith77 added the State: Reviewing This item is being reviewed to determine if it should be accepted. label May 22, 2017
@robfrawley robfrawley force-pushed the feature-add-resolution-filter branch 2 times, most recently from 481fb8a to 1d71c29 Compare May 23, 2017 02:37
@robfrawley
Copy link
Collaborator Author

robfrawley commented May 23, 2017

Looks like Packagist endpoints are having some trouble right now (or another similar issue), resulting in Composer failing to build anything in our Travis tests. I've gone ahead and made @Seldaek aware.

The Travis issue mentioned above has been closed and fixed in composer/composer#6342 by @Seldaek.

@robfrawley robfrawley force-pushed the feature-add-resolution-filter branch 4 times, most recently from c697f12 to cfa79f2 Compare May 23, 2017 20:38
@robfrawley robfrawley self-assigned this May 23, 2017
@robfrawley robfrawley added this to the 1.8.1 milestone May 23, 2017
));

$resolver->setNormalizer('filter', function (Options $options, $value) {
foreach (array('\Imagine\Image\ImageInterface::FILTER_%s', '\Imagine\Image\ImageInterface::%s', '\%s', '%s') as $format) {
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need leading backslashes here?

Copy link
Collaborator Author

@robfrawley robfrawley Jun 14, 2017

Choose a reason for hiding this comment

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

I added them as a very "micro-optimization" as it does remove some opcodes (otherwise it first searches in the defined namespace, followed by the global namespace (right?), the latter of which we want to force for the first two formats, but now that you bring this up, we could likely change:

array('\Imagine\Image\ImageInterface::FILTER_%s', '\Imagine\Image\ImageInterface::%s', '\%s', '%s')

to

array('\Imagine\Image\ImageInterface::FILTER_%s', '\Imagine\Image\ImageInterface::%s', '%s')

Of course, we don't need them anywhere, but I think it adds clarity and acts as a small speedup.

@robfrawley robfrawley force-pushed the feature-add-resolution-filter branch from cfa79f2 to f3e013e Compare July 8, 2017 10:49
@robfrawley robfrawley force-pushed the feature-add-resolution-filter branch from f3e013e to 309690d Compare July 8, 2017 11:07
@robfrawley robfrawley changed the title [WIP] [Filter] Add resolution filter loader [Filter] Add resolution filter loader Jul 8, 2017
@robfrawley
Copy link
Collaborator Author

robfrawley commented Jul 13, 2017

@antoligy @cedricziel Pending any objections, I'm going to merge this for inclusion in the 0.9.0 release.

@robfrawley robfrawley added Type: Documentation This item pertains to documentation of this project. Level: New Feature 🆕 This item involves the introduction of new functionality. labels Jul 13, 2017
@robfrawley
Copy link
Collaborator Author

Last call for comments @antoligy @cedricziel

@alexwilson
Copy link
Collaborator

Seems like the obvious points have already been made, I'm very happy with this to be merged.

Is it possible to process the file with a buffered stream versus buffering it into a file? (I'm actually unfamiliar with the underlying IMagick operation so it may be a limitation there).

Also, as a more general point, do we have a given convention for when operations are IMagick only, because if so I think we can possibly start adding filters a little more quickly (I've got a few between projects relying on IMagick only features, including another attempt at DPR adjustment).

@robfrawley
Copy link
Collaborator Author

robfrawley commented Aug 4, 2017

@antoligy Thanks for the quick review. Here is a verbose response. ;-)

Is it possible to process the file with a buffered stream versus buffering it into a file? (I'm actually unfamiliar with the underlying IMagick operation so it may be a limitation there).

The resampling functionality exposed by the imagine-library package is not well documented, but from what I've been able to gather by looking at the brief explanation in their docs, as well as the source code itself, we must explicitly save the file for the resolution to be applied. I can't find any way around this.

Also, as a more general point, do we have a given convention for when operations are IMagick only, because if so I think we can possibly start adding filters a little more quickly (I've got a few between projects relying on IMagick only features, including another attempt at DPR adjustment).

The way I implemented the functional resample test case was confusing. It's not the filter implementation that is imagick-only, but only the test itself that required imagick, as the Imagine\Imagick\Imagine class was used to read the resulting image's resolution for the test's assertion.

I've gone ahead and abstracted the test case a bit to support both imagick and gmagick. It isn't currently possible for the test to support gd as its imageresolution() function wasn't added until PHP 7.2.

As to your question about driver-specific filters, I do not have any particular issue with allowing such implementation, so long as the following conditions are met:

  • [Requirement] The filter documentation is obvious and explicit about driver support.
  • [Requirement] An instructive and detailed exception is thrown when an unsupported filter is used.
  • [Recommendation] Pre-processing of the configuration to throw an immediate exception if unsupported filters are configured. This exception would be thrown regardless of whether the filter is ever actually called during the request. This would avoid surprises for the user by ensuring their configured filters are valid for their environment (for example, we don't want the exception to only crop up three months later when the user removed their cached images; we want it to be thrown the moment it enters their config).
  • [Recommendation] Coinciding with the above recommendation, we could add a new interface for filters that are driver-aware (DriverDependantFilterInterface or something) that adds a new method to return an array of supported drivers, like supportedDrivers(): string[] or something similar.

The latest commit (22d874c) enables multiple driver support for the resample filter test (as explained above) and adds some additional file types and resolution sizes to the resample test via a new data provider.

@robfrawley robfrawley force-pushed the feature-add-resolution-filter branch from cbbc9c4 to 22d874c Compare August 4, 2017 03:47
@robfrawley robfrawley merged commit f10ae8e into liip:1.0 Aug 31, 2017
@robfrawley robfrawley mentioned this pull request Aug 31, 2017
@gnutix
Copy link

gnutix commented Jul 16, 2019

@robfrawley I can't seem to find this code in the current version of this bundle, and yet I can't find any commit / remarks about it's deprecation or removal. Any idea what happened ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Level: New Feature 🆕 This item involves the introduction of new functionality. State: Reviewing This item is being reviewed to determine if it should be accepted. Type: Documentation This item pertains to documentation of this project.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants