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

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

170 lines 6.3 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\Helpers;
4
5 use ExecWithFallback\ExecWithFallback;
6
7 /**
8 * Try to detect quality of a jpeg image using various tools.
9 *
10 * @package WebPConvert
11 * @author Bjørn Rosell <[email protected]>
12 * @since Class available since Release 2.0.0
13 */
14 class JpegQualityDetector
15 {
16
17 /**
18 * Try to detect quality of jpeg using imagick extension.
19 *
20 * Note that the detection might fail for two different reasons:
21 * 1) Imagick is not installed
22 * 2) Imagick for some reason fails to detect quality for some images
23 *
24 * In both cases, null is returned.
25 *
26 * @param string $filename A complete file path to file to be examined
27 * @return int|null Quality, or null if it was not possible to detect quality
28 */
29 private static function detectQualityOfJpgUsingImagick($filename)
30 {
31 if (extension_loaded('imagick') && class_exists('\\Imagick')) {
32 try {
33 $img = new \Imagick($filename);
34
35 // The required function is available as from PECL imagick v2.2.2
36 if (method_exists($img, 'getImageCompressionQuality')) {
37 $quality = $img->getImageCompressionQuality();
38 if ($quality === 0) {
39 // We have experienced that this Imagick method returns 0 for some images,
40 // (even though the imagemagick binary is able to detect the quality)
41 // ie "/test/images/quality-undetectable-with-imagick.jpg". See #208
42 $quality = null;
43 }
44 return $quality;
45 }
46 } catch (\Exception $e) {
47 // Well well, it just didn't work out.
48 // - But perhaps next method will work...
49 } catch (\Throwable $e) {
50 }
51 }
52 return null;
53 }
54
55
56 /**
57 * Try to detect quality of jpeg using imagick binary.
58 *
59 * Note that the detection might fail for three different reasons:
60 * 1) exec function is not available
61 * 2) the 'identify' command is not available on the system
62 * 3) imagemagick for some reason fails to detect quality for some images
63 *
64 * In the first two cases, null is returned.
65 * In the third case, 92 is returned. This is what imagemagick returns when it cannot detect the quality.
66 * and unfortunately we cannot distinguish between the situation where the quality is undetectable
67 * and the situation where the quality is actually 92 (at least, I have not found a way to do so)
68 *
69 * @param string $filename A complete file path to file to be examined
70 * @return int|null Quality, or null if it was not possible to detect quality
71 */
72 private static function detectQualityOfJpgUsingImageMagick($filename)
73 {
74 if (ExecWithFallback::anyAvailable()) {
75 // Try Imagick using exec, and routing stderr to stdout (the "2>$1" magic)
76
77 try {
78 ExecWithFallback::exec(
79 "identify -format '%Q' " . escapeshellarg($filename) . " 2>&1",
80 $output,
81 $returnCode
82 );
83 //echo 'out:' . print_r($output, true);
84 if ((intval($returnCode) == 0) && (is_array($output)) && (count($output) == 1)) {
85 return intval($output[0]);
86 }
87 } catch (\Exception $e) {
88 // its ok, there are other fish in the sea
89 } catch (\Throwable $e) {
90 }
91 }
92 return null;
93 }
94
95
96 /**
97 * Try to detect quality of jpeg using graphicsmagick binary.
98 *
99 * It seems that graphicsmagick is never able to detect the quality! - and always returns
100 * the default quality, which is 75.
101 * However, as this might be solved in future versions, the method might be useful one day.
102 * But we treat "75" as a failure to detect and shall return null in that case.
103 *
104 * @param string $filename A complete file path to file to be examined
105 * @return int|null Quality, or null if it was not possible to detect quality
106 */
107 private static function detectQualityOfJpgUsingGraphicsMagick($filename)
108 {
109 if (ExecWithFallback::anyAvailable()) {
110 // Try GraphicsMagick
111 try {
112 ExecWithFallback::exec(
113 "gm identify -format '%Q' " . escapeshellarg($filename) . " 2>&1",
114 $output,
115 $returnCode
116 );
117 if ((intval($returnCode) == 0) && (is_array($output)) && (count($output) == 1)) {
118 $quality = intval($output[0]);
119
120 // It seems that graphicsmagick is (currently) never able to detect the quality!
121 // - and always returns 75 as a fallback
122 // We shall therefore treat 75 as a failure to detect. (#209)
123 if ($quality == 75) {
124 return null;
125 }
126 return $quality;
127 }
128 } catch (\Exception $e) {
129 } catch (\Throwable $e) {
130 }
131 }
132 return null;
133 }
134
135
136 /**
137 * Try to detect quality of jpeg.
138 *
139 * Note: This method does not throw errors, but might dispatch warnings.
140 * You can use the WarningsIntoExceptions class if it is critical to you that nothing gets "printed"
141 *
142 * @param string $filename A complete file path to file to be examined
143 * @return int|null Quality, or null if it was not possible to detect quality
144 */
145 public static function detectQualityOfJpg($filename)
146 {
147
148 //trigger_error('warning test', E_USER_WARNING);
149
150 // Test that file exists in order not to break things.
151 if (!file_exists($filename)) {
152 // One could argue that it would be better to throw an Exception...?
153 return null;
154 }
155
156 // Try Imagick extension, if available
157 $quality = self::detectQualityOfJpgUsingImagick($filename);
158
159 if (is_null($quality)) {
160 $quality = self::detectQualityOfJpgUsingImageMagick($filename);
161 }
162
163 if (is_null($quality)) {
164 $quality = self::detectQualityOfJpgUsingGraphicsMagick($filename);
165 }
166
167 return $quality;
168 }
169 }
170