PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.22
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.22
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / vendor / rosell-dk / webp-convert / src / Convert / Converters / Vips.php

Vips.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.2.22, at vendor/rosell-dk/webp-convert/src/Convert/Converters/Vips.php

307 lines 11.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WebPConvert\Convert\Converters;
4
5 use WebPConvert\Convert\Converters\AbstractConverter;
6 use WebPConvert\Convert\Converters\ConverterTraits\EncodingAutoTrait;
7 use WebPConvert\Convert\Exceptions\ConversionFailedException;
8 use WebPConvert\Convert\Exceptions\ConversionFailed\ConverterNotOperational\SystemRequirementsNotMetException;
9 use WebPConvert\Options\BooleanOption;
10 use WebPConvert\Options\IntegerOption;
11
12 //require '/home/rosell/.composer/vendor/autoload.php';
13
14 /**
15 * Convert images to webp using Vips extension.
16 *
17 * @package WebPConvert
18 * @author Bjørn Rosell <[email protected]>
19 * @since Class available since Release 2.0.0
20 */
21 class Vips extends AbstractConverter
22 {
23 use EncodingAutoTrait;
24
25 protected function getUnsupportedDefaultOptions()
26 {
27 return [
28 'auto-filter',
29 'size-in-percentage',
30 ];
31 }
32
33 /**
34 * Get the options unique for this converter
35 *
36 * @return array Array of options
37 */
38 public function getUniqueOptions($imageType)
39 {
40 $ssOption = new BooleanOption('smart-subsample', false);
41 $ssOption->markDeprecated();
42 return [
43 $ssOption
44 ];
45 }
46
47 /**
48 * Check operationality of Vips converter.
49 *
50 * @throws SystemRequirementsNotMetException if system requirements are not met
51 */
52 public function checkOperationality()
53 {
54 if (!extension_loaded('vips')) {
55 throw new SystemRequirementsNotMetException('Required Vips extension is not available.');
56 }
57
58 if (!function_exists('vips_image_new_from_file')) {
59 throw new SystemRequirementsNotMetException(
60 'Vips extension seems to be installed, however something is not right: ' .
61 'the function "vips_image_new_from_file" is not available.'
62 );
63 }
64
65 if (!function_exists('vips_call')) {
66 throw new SystemRequirementsNotMetException(
67 'Vips extension seems to be installed, however something is not right: ' .
68 'the function "vips_call" is not available.'
69 );
70 }
71
72 if (!function_exists('vips_error_buffer')) {
73 throw new SystemRequirementsNotMetException(
74 'Vips extension seems to be installed, however something is not right: ' .
75 'the function "vips_error_buffer" is not available.'
76 );
77 }
78
79
80 vips_error_buffer(); // clear error buffer
81 $result = vips_call('webpsave', null);
82 if ($result === -1) {
83 $message = vips_error_buffer();
84 if (strpos($message, 'VipsOperation: class "webpsave" not found') === 0) {
85 throw new SystemRequirementsNotMetException(
86 'Vips has not been compiled with webp support.'
87 );
88 }
89 }
90 }
91
92 /**
93 * Check if specific file is convertable with current converter / converter settings.
94 *
95 * @throws SystemRequirementsNotMetException if Vips does not support image type
96 */
97 public function checkConvertability()
98 {
99 // It seems that png and jpeg are always supported by Vips
100 // - so nothing needs to be done here
101
102 if (function_exists('vips_version')) {
103 $this->logLn('vipslib version: ' . vips_version());
104 }
105 $this->logLn('vips extension version: ' . phpversion('vips'));
106 }
107
108 /**
109 * Create vips image resource from source file
110 *
111 * @throws ConversionFailedException if image resource cannot be created
112 * @return resource vips image resource
113 */
114 private function createImageResource()
115 {
116 // We are currently using vips_image_new_from_file(), but we could consider
117 // calling vips_jpegload / vips_pngload instead
118 $result = /** @scrutinizer ignore-call */ vips_image_new_from_file($this->source, []);
119 if ($result === -1) {
120 /*throw new ConversionFailedException(
121 'Failed creating new vips image from file: ' . $this->source
122 );*/
123 $message = /** @scrutinizer ignore-call */ vips_error_buffer();
124 throw new ConversionFailedException($message);
125 }
126
127 if (!is_array($result)) {
128 throw new ConversionFailedException(
129 'vips_image_new_from_file did not return an array, which we expected'
130 );
131 }
132
133 if (count($result) != 1) {
134 throw new ConversionFailedException(
135 'vips_image_new_from_file did not return an array of length 1 as we expected ' .
136 '- length was: ' . count($result)
137 );
138 }
139
140 $im = array_shift($result);
141 return $im;
142 }
143
144 /**
145 * Create parameters for webpsave
146 *
147 * @return array the parameters as an array
148 */
149 private function createParamsForVipsWebPSave()
150 {
151 // webpsave options are described here:
152 // https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-webpsave
153 // near_lossless option is described here: https://github.com/libvips/libvips/pull/430
154
155 // NOTE: When a new option becomes available, we MUST remember to add
156 // it to the array of possibly unsupported options in webpsave() !
157 $options = [
158 "Q" => $this->getCalculatedQuality(),
159 'lossless' => ($this->options['encoding'] == 'lossless'),
160 'strip' => $this->options['metadata'] == 'none',
161 ];
162
163 // Only set the following options if they differ from the default of vipslib
164 // This ensures we do not get warning if that property isn't supported
165 if ($this->options['smart-subsample'] !== false) {
166 // PS: The smart-subsample option is now deprecated, as it turned out
167 // it was corresponding to the "sharp-yuv" option (see #280)
168 $options['smart_subsample'] = $this->options['smart-subsample'];
169 $this->logLn(
170 '*Note: the "smart-subsample" option is now deprecated. It turned out it corresponded to ' .
171 'the general option "sharp-yuv". You should use "sharp-yuv" instead.*'
172 );
173 }
174 if ($this->options['sharp-yuv'] !== false) {
175 $options['smart_subsample'] = $this->options['sharp-yuv'];
176 }
177
178 if ($this->options['alpha-quality'] !== 100) {
179 $options['alpha_q'] = $this->options['alpha-quality'];
180 }
181
182 if (!is_null($this->options['preset']) && ($this->options['preset'] != 'none')) {
183 // preset. 0:default, 1:picture, 2:photo, 3:drawing, 4:icon, 5:text, 6:last
184 $options['preset'] = array_search(
185 $this->options['preset'],
186 ['default', 'picture', 'photo', 'drawing', 'icon', 'text']
187 );
188 }
189 if ($this->options['near-lossless'] !== 100) {
190 if ($this->options['encoding'] == 'lossless') {
191 // We only let near_lossless have effect when encoding is set to lossless
192 // otherwise encoding=auto would not work as expected
193 // Available in https://github.com/libvips/libvips/pull/430, merged 1 may 2016
194 // seems it corresponds to release 8.4.2
195 $options['near_lossless'] = true;
196
197 // In Vips, the near-lossless value is controlled by Q.
198 // this differs from how it is done in cwebp, where it is an integer.
199 // We have chosen same option syntax as cwebp
200 $options['Q'] = $this->options['near-lossless'];
201 }
202 }
203 if ($this->options['method'] !== 4) {
204 $options['reduction_effort'] = $this->options['method'];
205 }
206
207 return $options;
208 }
209
210 /**
211 * Save as webp, using vips extension.
212 *
213 * Tries to save image resource as webp, using the supplied options.
214 * Vips fails when a parameter is not supported, but we detect this and unset that parameter and try again
215 * (recursively call itself until there is no more of these kind of errors).
216 *
217 * @param resource $im A vips image resource to save
218 * @throws ConversionFailedException if conversion fails.
219 */
220 private function webpsave($im, $options)
221 {
222 /** @scrutinizer ignore-call */ vips_error_buffer(); // clear error buffer
223 $result = /** @scrutinizer ignore-call */ vips_call('webpsave', $im, $this->destination, $options);
224
225 //trigger_error('test-warning', E_USER_WARNING);
226 if ($result === -1) {
227 $message = /** @scrutinizer ignore-call */ vips_error_buffer();
228
229 $nameOfPropertyNotFound = '';
230 if (preg_match("#no property named .(.*).#", $message, $matches)) {
231 $nameOfPropertyNotFound = $matches[1];
232 } elseif (preg_match("#(.*)\\sunsupported$#", $message, $matches)) {
233 // Actually, I am not quite sure if this ever happens.
234 // I got a "near_lossless unsupported" error message in a build, but perhaps it rather a warning
235 if (in_array($matches[1], [
236 'lossless',
237 'alpha_q',
238 'near_lossless',
239 'smart_subsample',
240 'reduction_effort',
241 'preset'
242 ])) {
243 $nameOfPropertyNotFound = $matches[1];
244 }
245 }
246
247 if ($nameOfPropertyNotFound != '') {
248 $msg = 'Note: Your version of vipslib does not support the "' .
249 $nameOfPropertyNotFound . '" property';
250
251 switch ($nameOfPropertyNotFound) {
252 case 'alpha_q':
253 $msg .= ' (It was introduced in vips 8.4)';
254 break;
255 case 'near_lossless':
256 $msg .= ' (It was introduced in vips 8.4)';
257 break;
258 case 'smart_subsample':
259 $msg .= ' (its the vips equalent to the "sharp-yuv" option. It was introduced in vips 8.4)';
260 break;
261 case 'reduction_effort':
262 $msg .= ' (its the vips equalent to the "method" option. It was introduced in vips 8.8.0)';
263 break;
264 case 'preset':
265 $msg .= ' (It was introduced in vips 8.4)';
266 break;
267 }
268 $msg .= '. The option is ignored.';
269
270
271 $this->logLn($msg, 'bold');
272
273 unset($options[$nameOfPropertyNotFound]);
274 $this->webpsave($im, $options);
275 } else {
276 throw new ConversionFailedException($message);
277 }
278 }
279 }
280
281 /**
282 * Convert, using vips extension.
283 *
284 * Tries to create image resource and save it as webp using the calculated options.
285 * PS: The Vips "webpsave" call fails when a parameter is not supported, but our webpsave() method
286 * detect this and unset that parameter and try again (repeat until success).
287 *
288 * @throws ConversionFailedException if conversion fails.
289 */
290 protected function doActualConvert()
291 {
292 /*
293 $im = \Jcupitt\Vips\Image::newFromFile($this->source);
294 //$im->writeToFile(__DIR__ . '/images/small-vips.webp', ["Q" => 10]);
295
296 $im->webpsave($this->destination, [
297 "Q" => 80,
298 //'near_lossless' => true
299 ]);
300 return;*/
301
302 $im = $this->createImageResource();
303 $options = $this->createParamsForVipsWebPSave();
304 $this->webpsave($im, $options);
305 }
306 }
307