• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

liip / LiipImagineBundle / 6284547049

23 Sep 2023 03:28PM UTC coverage: 82.083% (+0.7%) from 81.372%
6284547049

push

github

web-flow
Merge pull request #1531 from liip/2-to-3

2 to 3

19 of 24 new or added lines in 6 files covered. (79.17%)

21 existing lines in 4 files now uncovered.

1860 of 2266 relevant lines covered (82.08%)

67.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Imagine/Filter/PostProcessor/CwebpPostProcessor.php
1
<?php
2

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

12
namespace Liip\ImagineBundle\Imagine\Filter\PostProcessor;
13

14
use Liip\ImagineBundle\Binary\BinaryInterface;
15
use Liip\ImagineBundle\Model\Binary;
16
use Symfony\Component\OptionsResolver\OptionsResolver;
17
use Symfony\Component\Process\Exception\ProcessFailedException;
18

19
class CwebpPostProcessor extends AbstractPostProcessor
20
{
21
    /**
22
     * Specify the compression factor for RGB channels between **0** and **100**. The default is **75**.
23
     *
24
     * In case of lossy compression , a small factor produces a smaller file with lower quality. Best quality is
25
     * achieved by using a value of **100**.
26
     *
27
     * In case of lossless compression (specified by the **-lossless** option), a small factor enables faster
28
     * compression speed, but produces a larger file. Maximum compression is achieved by using a value of **100**.
29
     *
30
     * @var int
31
     */
32
    protected $q;
33

34
    /**
35
     * Specify the compression factor for alpha compression between **0** and **100**. Lossless compression of alpha is
36
     * achieved using a value of **100**, while the lower values result in a lossy compression.
37
     *
38
     * @var int
39
     */
40
    protected $alphaQ;
41

42
    /**
43
     * Specify the compression method to use. This parameter controls the trade off between encoding speed and the
44
     * compressed file size and quality. Possible values range from **0** to **6**. When higher values are used, the
45
     * encoder will spend more time inspecting additional encoding possibilities and decide on the quality gain. Lower
46
     * value can result in faster processing time at the expense of larger file size and lower compression quality.
47
     *
48
     * @var int
49
     */
50
    protected $m;
51

52
    /**
53
     * Specify the predictive filtering method for the alpha plane. One of **none**, **fast** or **best**, in
54
     * increasing complexity and slowness order. Internally, alpha filtering is performed using four possible
55
     * predictions (none, horizontal, vertical, gradient). The **best** mode will try each mode in turn and pick the
56
     * one which gives the smaller size. The **fast** mode will just try to form an a priori guess without testing all
57
     * modes.
58
     *
59
     * @var string
60
     */
61
    protected $alphaFilter;
62

63
    /**
64
     * Specify the algorithm used for alpha compression: **0** or **1**. Algorithm **0** denotes no compression, **1**
65
     * uses WebP lossless format for compression.
66
     *
67
     * @var int
68
     */
69
    protected $alphaMethod;
70

71
    /**
72
     * Preserve RGB values in transparent area. The default is off, to help compressibility.
73
     *
74
     * @var bool
75
     */
76
    protected $exact;
77

78
    /**
79
     * An array of metadata to copy from the input to the output if present. Valid values: **all**, **none**, **exif**,
80
     * **icc**, **xmp**.
81
     *
82
     * Note that each input format may not support all combinations.
83
     *
84
     * @var string[]
85
     */
86
    protected $metadata;
87

88
    /**
89
     * @var OptionsResolver
90
     */
91
    private $resolver;
92

93
    /**
94
     * @param string[] $metadata
95
     */
96
    public function __construct(
97
        string $executablePath = '/usr/bin/cwebp',
98
        string $temporaryRootPath = null,
99
        int $q = null,
100
        int $alphaQ = null,
101
        int $m = null,
102
        string $alphaFilter = null,
103
        int $alphaMethod = null,
104
        bool $exact = null,
105
        array $metadata = []
106
    ) {
107
        parent::__construct($executablePath, $temporaryRootPath);
×
108

109
        $this->q = $q;
×
110
        $this->alphaQ = $alphaQ;
×
111
        $this->m = $m;
×
112
        $this->alphaFilter = $alphaFilter;
×
113
        $this->alphaMethod = $alphaMethod;
×
114
        $this->exact = $exact;
×
115
        $this->metadata = $metadata;
×
116
        $this->resolver = new OptionsResolver();
×
117

118
        $this->configureOptions($this->resolver);
×
119
    }
120

121
    public function process(BinaryInterface $binary, array $options = []): BinaryInterface
122
    {
123
        if (!$this->isBinaryTypeWebpImage($binary)) {
×
124
            return $binary;
×
125
        }
126

127
        $file = $this->writeTemporaryFile($binary, $options, 'imagine-post-processor-cwebp');
×
128
        $arguments = $this->getProcessArguments($options);
×
129
        $arguments[] = $file;
×
130
        $arguments[] = '-o';
×
131
        $arguments[] = '-';
×
132
        $process = $this->createProcess($arguments, $options);
×
133

134
        $process->run();
×
135

136
        if (!$this->isSuccessfulProcess($process)) {
×
137
            unlink($file);
×
138

139
            throw new ProcessFailedException($process);
×
140
        }
141

142
        $result = new Binary($process->getOutput(), $binary->getMimeType(), $binary->getFormat());
×
143

144
        unlink($file);
×
145

146
        return $result;
×
147
    }
148

149
    protected function isBinaryTypeWebpImage(BinaryInterface $binary): bool
150
    {
151
        return $this->isBinaryTypeMatch($binary, ['image/webp']);
×
152
    }
153

154
    protected function configureOptions(OptionsResolver $resolver): void
155
    {
UNCOV
156
        $resolver
×
157
            ->setDefault('q', $this->q)
×
158
            ->setAllowedTypes('q', ['null', 'int'])
×
159
            ->setAllowedValues('q', static function ($value) {
×
160
                if (null === $value) {
×
161
                    return true;
×
162
                }
163

164
                return $value >= 0 && $value <= 100;
×
UNCOV
165
            });
×
166

UNCOV
167
        $resolver
×
168
            ->setDefault('alphaQ', $this->alphaQ)
×
169
            ->setAllowedTypes('alphaQ', ['null', 'int'])
×
170
            ->setAllowedValues('alphaQ', static function ($value) {
×
171
                if (null === $value) {
×
172
                    return true;
×
173
                }
174

175
                return $value >= 0 && $value <= 100;
×
UNCOV
176
            });
×
177

UNCOV
178
        $resolver
×
179
            ->setDefault('m', $this->m)
×
180
            ->setAllowedTypes('m', ['null', 'int'])
×
181
            ->setAllowedValues('m', static function ($value) {
×
182
                if (null === $value) {
×
183
                    return true;
×
184
                }
185

186
                return $value >= 0 && $value <= 6;
×
UNCOV
187
            });
×
188

UNCOV
189
        $resolver
×
190
            ->setDefault('alphaFilter', $this->alphaFilter)
×
191
            ->setAllowedTypes('alphaFilter', ['null', 'string'])
×
192
            ->setAllowedValues('alphaFilter', [null, 'none', 'fast', 'best']);
×
193

UNCOV
194
        $resolver
×
195
            ->setDefault('alphaMethod', $this->alphaMethod)
×
196
            ->setAllowedTypes('alphaMethod', ['null', 'int'])
×
197
            ->setAllowedValues('alphaMethod', [null, 0, 1]);
×
198

UNCOV
199
        $resolver
×
200
            ->setDefault('exact', $this->exact)
×
201
            ->setAllowedTypes('exact', ['null', 'bool']);
×
202

UNCOV
203
        $resolver
×
204
            ->setDefault('metadata', $this->metadata)
×
205
            ->setAllowedTypes('metadata', ['null', 'array'])
×
206
            ->setAllowedValues('metadata', static function ($value) {
×
207
                if (null === $value) {
×
208
                    return true;
×
209
                }
210

211
                foreach ($value as $metadata) {
×
212
                    if (!\in_array($metadata, ['all', 'none', 'exif', 'icc', 'xmp'], true)) {
×
213
                        return false;
×
214
                    }
215
                }
216

217
                return true;
×
UNCOV
218
            });
×
219
    }
220

221
    /**
222
     * @param array<mixed> $options
223
     *
224
     * @return string[]
225
     */
226
    protected function getProcessArguments(array $options = []): array
227
    {
228
        $options = $this->resolver->resolve($options);
×
229
        $arguments = [$this->executablePath];
×
230

231
        if ($q = $options['q']) {
×
232
            $arguments[] = '-q';
×
233
            $arguments[] = $q;
×
234
        }
235

236
        if ($alphaQ = $options['alphaQ']) {
×
237
            $arguments[] = '-alpha_q';
×
238
            $arguments[] = $alphaQ;
×
239
        }
240

241
        if ($m = $options['m']) {
×
242
            $arguments[] = '-m';
×
243
            $arguments[] = $m;
×
244
        }
245

246
        if ($alphaFilter = $options['alphaFilter']) {
×
247
            $arguments[] = '-alpha_filter';
×
248
            $arguments[] = $alphaFilter;
×
249
        }
250

251
        $alphaMethod = $options['alphaMethod'];
×
252
        if (null !== $alphaMethod) {
×
253
            $arguments[] = '-alpha_method';
×
254
            $arguments[] = $alphaMethod;
×
255
        }
256

257
        if ($options['exact']) {
×
258
            $arguments[] = '-exact';
×
259
        }
260

261
        if ($metadata = $options['metadata']) {
×
262
            $arguments[] = '-metadata';
×
263
            $arguments[] = implode(',', $metadata);
×
264
        }
265

266
        return $arguments;
×
267
    }
268
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc