PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.7
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.7
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 / Imagick.php

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

230 lines 9.1 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\Exceptions\ConversionFailedException;
7 use WebPConvert\Convert\Exceptions\ConversionFailed\FileSystemProblems\CreateDestinationFileException;
8 use WebPConvert\Convert\Exceptions\ConversionFailed\ConverterNotOperational\SystemRequirementsNotMetException;
9 use WebPConvert\Convert\Converters\ConverterTraits\EncodingAutoTrait;
10
11 //use WebPConvert\Convert\Exceptions\ConversionFailed\InvalidInput\TargetNotFoundException;
12
13 /**
14 * Convert images to webp using Imagick extension.
15 *
16 * @package WebPConvert
17 * @author Bjørn Rosell <[email protected]>
18 * @since Class available since Release 2.0.0
19 */
20 class Imagick extends AbstractConverter
21 {
22 use EncodingAutoTrait;
23
24 protected function getUnsupportedDefaultOptions()
25 {
26 return [
27 'size-in-percentage',
28 ];
29 }
30
31 /**
32 * Check operationality of Imagick converter.
33 *
34 * Note:
35 * It may be that Gd has been compiled without jpeg support or png support.
36 * We do not check for this here, as the converter could still be used for the other.
37 *
38 * @throws SystemRequirementsNotMetException if system requirements are not met
39 * @return void
40 */
41 public function checkOperationality()
42 {
43 if (!extension_loaded('imagick')) {
44 throw new SystemRequirementsNotMetException('Required iMagick extension is not available.');
45 }
46
47 if (!class_exists('\\Imagick')) {
48 throw new SystemRequirementsNotMetException(
49 'iMagick is installed, but not correctly. The class Imagick is not available'
50 );
51 }
52
53 $im = new \Imagick();
54 if (!in_array('WEBP', $im->queryFormats('WEBP'))) {
55 throw new SystemRequirementsNotMetException('iMagick was compiled without WebP support.');
56 }
57 }
58
59 /**
60 * Check if specific file is convertable with current converter / converter settings.
61 *
62 * @throws SystemRequirementsNotMetException if Imagick does not support image type
63 */
64 public function checkConvertability()
65 {
66 $im = new \Imagick();
67 $mimeType = $this->getMimeTypeOfSource();
68 switch ($mimeType) {
69 case 'image/png':
70 if (!in_array('PNG', $im->queryFormats('PNG'))) {
71 throw new SystemRequirementsNotMetException(
72 'Imagick has been compiled without PNG support and can therefore not convert this PNG image.'
73 );
74 }
75 break;
76 case 'image/jpeg':
77 if (!in_array('JPEG', $im->queryFormats('JPEG'))) {
78 throw new SystemRequirementsNotMetException(
79 'Imagick has been compiled without Jpeg support and can therefore not convert this Jpeg image.'
80 );
81 }
82 break;
83 }
84 }
85
86 /**
87 *
88 * It may also throw an ImagickException if imagick throws an exception
89 * @throws CreateDestinationFileException if imageblob could not be saved to file
90 */
91 protected function doActualConvert()
92 {
93 /*
94 * More about iMagick's WebP options:
95 * - Inspect source code: https://github.com/ImageMagick/ImageMagick/blob/master/coders/webp.c#L559
96 * (search for "webp:")
97 * - http://www.imagemagick.org/script/webp.php
98 * - https://developers.google.com/speed/webp/docs/cwebp
99 * - https://stackoverflow.com/questions/37711492/imagemagick-specific-webp-calls-in-php
100 */
101
102 $options = $this->options;
103
104 // This might throw - we let it!
105 $im = new \Imagick($this->source);
106 //$im = new \Imagick();
107 //$im->pingImage($this->source);
108 //$im->readImage($this->source);
109
110 $version = \Imagick::getVersion();
111 $this->logLn('ImageMagic API version (full): ' . $version['versionString']);
112
113 preg_match('#\d+\.\d+\.\d+[\d\.\-]+#', $version['versionString'], $matches);
114 $versionNumber = (isset($matches[0]) ? $matches[0] : 'unknown');
115 $this->logLn('ImageMagic API version (just the number): ' . $versionNumber);
116
117 // Note: good enough for info, but not entirely reliable - see #304
118 $extVersion = (defined('\Imagick::IMAGICK_EXTVER') ? \Imagick::IMAGICK_EXTVER : phpversion('imagick'));
119 $this->logLn('Imagic extension version: ' . $extVersion);
120
121 $im->setImageFormat('WEBP');
122
123 if (!is_null($options['preset'])) {
124 if ($options['preset'] != 'none') {
125 $imageHint = $options['preset'];
126 switch ($imageHint) {
127 case 'drawing':
128 case 'icon':
129 case 'text':
130 $imageHint = 'graph';
131 $this->logLn(
132 'The "preset" value was mapped to "graph" because imagick does not support "drawing",' .
133 ' "icon" and "text", but grouped these into one option: "graph".'
134 );
135 }
136 $im->setOption('webp:image-hint', $imageHint);
137 }
138 }
139
140 $im->setOption('webp:method', $options['method']);
141 $im->setOption('webp:lossless', $options['encoding'] == 'lossless' ? 'true' : 'false');
142 $im->setOption('webp:low-memory', $options['low-memory'] ? 'true' : 'false');
143 $im->setOption('webp:alpha-quality', $options['alpha-quality']);
144
145 if ($options['near-lossless'] != 100) {
146 if (version_compare($versionNumber, '7.0.10-54', '>=')) {
147 $im->setOption('webp:near-lossless', $options['near-lossless']);
148 } else {
149 $this->logLn(
150 'Note: near-lossless is not supported in your version of ImageMagick. ' .
151 'ImageMagic >= 7.0.10-54 is required',
152 'italic'
153 );
154 }
155 }
156
157 if ($options['auto-filter'] === true) {
158 $im->setOption('webp:auto-filter', 'true');
159 }
160
161 if ($options['sharp-yuv'] === true) {
162 if (version_compare($versionNumber, '7.0.8-26', '>=')) {
163 $im->setOption('webp:use-sharp-yuv', 'true');
164 } else {
165 $this->logLn(
166 'Note: "sharp-yuv" option is not supported in your version of ImageMagick. ' .
167 'ImageMagic >= 7.0.8-26 is required',
168 'italic'
169 );
170 }
171 }
172
173 if ($options['metadata'] == 'none') {
174 // To strip metadata, we need to use the stripImage() method. However, that method does not only remove
175 // metadata, but color profiles as well. We want to keep the color profiles, so we grab it now to be able
176 // to restore it. (Thanks, Max Eremin: https://www.php.net/manual/en/imagick.stripimage.php#120380)
177
178 // Grab color profile (to be able to restore them)
179 $profiles = $im->getImageProfiles("icc", true);
180
181 // Strip metadata (and color profiles)
182 $im->stripImage();
183
184 // Restore color profiles
185 if (!empty($profiles)) {
186 $im->profileImage("icc", $profiles['icc']);
187 }
188 }
189
190 if ($this->isQualityDetectionRequiredButFailing()) {
191 // Luckily imagick is a big boy, and automatically converts with same quality as
192 // source, when the quality isn't set.
193 // So we simply do not set quality.
194 // This actually kills the max-quality functionality. But I deem that this is more important
195 // because setting image quality to something higher than source generates bigger files,
196 // but gets you no extra quality. When failing to limit quality, you at least get something
197 // out of it
198 $this->logLn('Converting without setting quality in order to achieve auto quality');
199 } else {
200 $im->setImageCompressionQuality($this->getCalculatedQuality());
201 }
202
203 // https://stackoverflow.com/questions/29171248/php-imagick-jpeg-optimization
204 // setImageFormat
205
206 // TODO: Read up on
207 // https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/
208 // https://github.com/nwtn/php-respimg
209
210 // TODO:
211 // Should we set alpha channel for PNG's like suggested here:
212 // https://gauntface.com/blog/2014/09/02/webp-support-with-imagemagick-and-php ??
213 // It seems that alpha channel works without... (at least I see completely transparerent pixels)
214
215 // We used to use writeImageFile() method. But we now use getImageBlob(). See issue #43
216
217 // This might throw - we let it!
218 $imageBlob = $im->getImageBlob();
219
220 $success = file_put_contents($this->destination, $imageBlob);
221
222 if (!$success) {
223 throw new CreateDestinationFileException('Failed writing file');
224 }
225
226 // Btw: check out processWebp() method here:
227 // https://github.com/Intervention/image/blob/master/src/Intervention/Image/Imagick/Encoder.php
228 }
229 }
230