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 / GraphicsMagick.php

GraphicsMagick.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/GraphicsMagick.php

221 lines 7.4 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\Converters\ConverterTraits\ExecTrait;
8 use WebPConvert\Convert\Exceptions\ConversionFailed\ConverterNotOperational\SystemRequirementsNotMetException;
9 use WebPConvert\Convert\Exceptions\ConversionFailedException;
10 use WebPConvert\Options\OptionFactory;
11 use ExecWithFallback\ExecWithFallback;
12
13 //use WebPConvert\Convert\Exceptions\ConversionFailed\InvalidInput\TargetNotFoundException;
14
15 /**
16 * Convert images to webp by calling gmagick binary (gm).
17 *
18 * @package WebPConvert
19 * @author Bjørn Rosell <[email protected]>
20 * @since Class available since Release 2.0.0
21 */
22 class GraphicsMagick extends AbstractConverter
23 {
24 use ExecTrait;
25 use EncodingAutoTrait;
26
27 protected function getUnsupportedDefaultOptions()
28 {
29 return [
30 'near-lossless',
31 'size-in-percentage',
32 ];
33 }
34
35 /**
36 * Get the options unique for this converter
37 *
38 * @return array Array of options
39 */
40 public function getUniqueOptions($imageType)
41 {
42 return OptionFactory::createOptions([
43 self::niceOption()
44 ]);
45 }
46
47 private function getPath()
48 {
49 if (defined('WEBPCONVERT_GRAPHICSMAGICK_PATH')) {
50 return constant('WEBPCONVERT_GRAPHICSMAGICK_PATH');
51 }
52 if (!empty(getenv('WEBPCONVERT_GRAPHICSMAGICK_PATH'))) {
53 return getenv('WEBPCONVERT_GRAPHICSMAGICK_PATH');
54 }
55 return 'gm';
56 }
57
58 public function isInstalled()
59 {
60 ExecWithFallback::exec($this->getPath() . ' -version 2>&1', $output, $returnCode);
61 return ($returnCode == 0);
62 }
63
64 public function getVersion()
65 {
66 ExecWithFallback::exec($this->getPath() . ' -version 2>&1', $output, $returnCode);
67 if (($returnCode == 0) && isset($output[0])) {
68 return preg_replace('#http.*#', '', $output[0]);
69 }
70 return 'unknown';
71 }
72
73 // Check if webp delegate is installed
74 public function isWebPDelegateInstalled()
75 {
76 ExecWithFallback::exec($this->getPath() . ' -version 2>&1', $output, $returnCode);
77 foreach ($output as $line) {
78 if (preg_match('#WebP.*yes#i', $line)) {
79 return true;
80 }
81 }
82 return false;
83 }
84
85 /**
86 * Check (general) operationality of imagack converter executable
87 *
88 * @throws SystemRequirementsNotMetException if system requirements are not met
89 */
90 public function checkOperationality()
91 {
92 $this->checkOperationalityExecTrait();
93
94 if (!$this->isInstalled()) {
95 throw new SystemRequirementsNotMetException('gmagick is not installed');
96 }
97 if (!$this->isWebPDelegateInstalled()) {
98 throw new SystemRequirementsNotMetException('webp delegate missing');
99 }
100 }
101
102 /**
103 * Build command line options
104 *
105 * @return string
106 */
107 private function createCommandLineOptions()
108 {
109 // For available webp options, check out:
110 // https://github.com/kstep/graphicsmagick/blob/master/coders/webp.c
111
112 $commandArguments = [];
113
114 /*
115 if ($this->isQualityDetectionRequiredButFailing()) {
116 // Unlike imagick binary, it seems gmagick binary uses a fixed
117 // quality (75) when quality is omitted
118 // So we cannot simply omit in order to get same quality as source.
119 // But perhaps there is another way?
120 // Check out #91 - it is perhaps as easy as this: "-define jpeg:preserve-settings"
121 }
122 */
123 $commandArguments[] = '-quality ' . escapeshellarg($this->getCalculatedQuality());
124
125 $options = $this->options;
126
127 // preset
128 if (!is_null($options['preset'])) {
129 if ($options['preset'] != 'none') {
130 $imageHint = $options['preset'];
131 switch ($imageHint) {
132 case 'drawing':
133 case 'icon':
134 case 'text':
135 $imageHint = 'graph';
136 $this->logLn(
137 'Note: the preset was mapped to "graph" because graphicsmagick does not support ' .
138 '"drawing", "icon" and "text", but grouped these into one option: "graph".'
139 );
140 }
141 $commandArguments[] = '-define webp:image-hint=' . escapeshellarg($imageHint);
142 }
143 }
144
145 // encoding
146 if ($options['encoding'] == 'lossless') {
147 // Btw:
148 // I am not sure if we should set "quality" for lossless.
149 // Quality should not apply to lossless, but my tests shows that it does in some way for gmagick
150 // setting it low, you get bad visual quality and small filesize. Setting it high, you get the opposite
151 // Some claim it is a bad idea to set quality, but I'm not so sure.
152 // https://stackoverflow.com/questions/4228027/
153 // First, I do not just get bigger images when setting quality, as toc777 does.
154 // Secondly, the answer is very old and that bad behaviour is probably fixed by now.
155 $commandArguments[] = '-define webp:lossless=true';
156 } else {
157 $commandArguments[] = '-define webp:lossless=false';
158 }
159
160 if ($options['auto-filter'] === true) {
161 $commandArguments[] = '-define webp:auto-filter=true';
162 }
163
164 if ($options['alpha-quality'] !== 100) {
165 $commandArguments[] = '-define webp:alpha-quality=' . strval($options['alpha-quality']);
166 }
167
168 if ($options['low-memory']) {
169 $commandArguments[] = '-define webp:low-memory=true';
170 }
171
172 if ($options['sharp-yuv'] === true) {
173 $commandArguments[] = '-define webp:use-sharp-yuv=true';
174 }
175
176 if ($options['metadata'] == 'none') {
177 $commandArguments[] = '-strip';
178 }
179
180 $commandArguments[] = '-define webp:method=' . $options['method'];
181
182 $commandArguments[] = escapeshellarg($this->source);
183 $commandArguments[] = escapeshellarg('webp:' . $this->destination);
184
185 return implode(' ', $commandArguments);
186 }
187
188 protected function doActualConvert()
189 {
190 //$this->logLn('Using quality:' . $this->getCalculatedQuality());
191
192 $this->logLn('Version: ' . $this->getVersion());
193
194 $command = $this->getPath() . ' convert ' . $this->createCommandLineOptions() . ' 2>&1';
195
196 $useNice = ($this->options['use-nice'] && $this->checkNiceSupport());
197 if ($useNice) {
198 $command = 'nice ' . $command;
199 }
200 $this->logLn('Executing command: ' . $command);
201 ExecWithFallback::exec($command, $output, $returnCode);
202
203 $this->logExecOutput($output);
204 if ($returnCode == 0) {
205 $this->logLn('success');
206 } else {
207 $this->logLn('return code: ' . $returnCode);
208 }
209
210 if ($returnCode == 127) {
211 throw new SystemRequirementsNotMetException('gmagick is not installed');
212 }
213 if ($returnCode != 0) {
214 $this->logLn('command:' . $command);
215 $this->logLn('return code:' . $returnCode);
216 $this->logLn('output:' . print_r(implode("\n", $output), true));
217 throw new SystemRequirementsNotMetException('The exec() call failed');
218 }
219 }
220 }
221