Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • SensioLabs Professional services to help you with Symfony
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by
  1. Home
  2. Documentation
  3. Bundles
  4. LiipImagineBundle
  5. Post-Processors

Post-Processors

Edit this page

We already know that filters perform image transformation. This may leave you wondering how post-processors fit into the runtime. To help illustrate the difference between filters and post-processors, it is important to highlight the following.

  • Filters modify the image.
  • Post-processors modify the image binary.

After all filters have run, the result is an image binary. This is then provided to, processed by, and returned from all configured post-processors.

Tip

Post-Processors can be safely chained, even if they operate on different mime-types. This makes them perfect for image-specific optimisation techniques.

Built-in processors

A number of built-in post-processors are provided by default.

Image Optimizers

Post-processors of the image optimizer classification are intended to reduce the final image file size, and therefore improve the load performance of your application's assets.

  • cwebp
  • Moz JPEG
  • JPEG Optim
  • Opti PNG
  • PNG Quant

Custom processors

You can define your own post-processors to perform any image binary operations required. Post-processor need to implement the PostProcessorInterface:

1
2
3
4
interface PostProcessorInterface
{
    public function process(BinaryInterface $binary);
}

As defined in PostProcessorInterface, the only required method is one named process, which is provided an instance of BinaryInterface as its singular parameter, and subsequently provides an instance of BinaryInterface in return.

Tip

You may optionally implement ConfigurablePostProcessorInterface in your post-processor to allow it to be configurable.

The following is a template for creating your own post-processor that calls an executable. You must set the EXECUTABLE_PATH class constant to the absolute path of the desired executable. You may also want to change ['image/png'] to the supported mime types for your custom post-processor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
namespace App\Service;

use Liip\ImagineBundle\Binary\BinaryInterface;
use Liip\ImagineBundle\Model\Binary;
use Liip\ImagineBundle\Imagine\Filter\PostProcessorInterface;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\ProcessBuilder;

class MyCustomPostProcessor implements PostProcessorInterface
{
    public const EXECUTABLE_PATH = '/path/to/your/executable';

    /**
     * @param BinaryInterface $binary
     *
     * @return BinaryInterface
     */
    public function process(BinaryInterface $binary)
    {
        // ensure the passed binary is a png
        if (!in_array(strtolower($binary->getMimeType()), ['image/png'])) {
            return $binary;
        }

        // create a temporary input file
        if (false === $input = tempnam($path = sys_get_temp_dir(), 'custom_')) {
            throw new \Exception(sprintf('Error created tmp file in "%s".', $path));
        }

        // populate temporary file with passed file contents
        file_put_contents($input, $binary->getContent());

        // create a process builder, add the input file as argument
        $pb = new ProcessBuilder([self::EXECUTABLE_PATH]);
        $pb->add($input);

        // get a process instance and run it
        $process = $pb->getProcess();
        $process->run();

        // error out if command returned non-zero
        if (0 !== $process->getExitCode()) {
            unlink($input);
            throw new ProcessFailedException($process);
        }

        // retrieve the result
        $result = new Binary(
            file_get_contents($input),
            $binary->getMimeType(),
            $binary->getFormat()
        );

        // remove temporary file
        unlink($input);

        // return the result
        return $result;
    }
}

Register it: automatically

By default, your post-processor will be automatically registered as it implements the PostProcessorInterface.

You will be able to reference and use your custom post-processor in your configuration by using its Fully Qualified Class Name.

Register it: manually

If you want to give it a different name you need to configure a service with your custom post-processor and tag it with liip_imagine.filter.post_processor.

To register App\Service\MyCustomPostProcessor with the name my_custom_post_processor, you would use the following configuration.

1
2
3
4
5
6
# app/config/services.yml

app.post_processor.my_custom_post_processor:
    class: App\Service\MyCustomPostProcessor
    tags:
        - { name: 'liip_imagine.filter.post_processor', post_processor: 'my_custom_post_processor' }
1
2
3
4
5
<!-- app/config/services.xml -->

<service id="app.post_processor.my_custom_post_processor" class="App\Service\MyCustomPostProcessor">
    <tag name="liip_imagine.filter.post_processor" post_processor="my_custom_post_processor" />
</service>

Now your custom post-processor can be referenced in a filter set using the name assigned via the post_processor tag attribute above (in this example, my_custom_post_processor).

1
2
3
4
5
6
7
# app/config/config.yml

liip_imagine:
    filter_sets:
        my_special_style:
            post_processors:
                my_custom_post_processor: { }
This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version
    Online exam, become Symfony certified today

    Online exam, become Symfony certified today

    Make sure your project is risk free

    Make sure your project is risk free

    Version:

    Table of Contents

    • Built-in processors
      • Image Optimizers
    • Custom processors

    Symfony footer

    Avatar of Andrew Tch, a Symfony contributor

    Thanks Andrew Tch for being a Symfony contributor

    1 commit • 66 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • What is Symfony?
      • Symfony at a Glance
      • Symfony Components
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • Symfony Community
      • SymfonyConnect
      • Events & Meetups
      • Projects using Symfony
      • Contributors
      • Symfony Jobs
      • Backers
      • Code of Conduct
      • Downloads Stats
      • Support
    • Blog

      • All Blog Posts
      • A Week of Symfony
      • Case Studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Living on the edge
      • Releases
      • Security Advisories
      • Symfony Insight
      • Twig
      • SensioLabs Blog
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Powered by

    Follow Symfony