Skip to content

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.

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' }

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