Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
62.00% covered (warning)
62.00%
31 / 50
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
Gmagick
62.00% covered (warning)
62.00%
31 / 50
0.00% covered (danger)
0.00%
0 / 4
52.03
0.00% covered (danger)
0.00%
0 / 1
 getUnsupportedDefaultOptions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 checkOperationality
57.14% covered (warning)
57.14%
4 / 7
0.00% covered (danger)
0.00%
0 / 1
5.26
 checkConvertability
81.82% covered (warning)
81.82%
9 / 11
0.00% covered (danger)
0.00%
0 / 1
5.15
 doActualConvert
58.06% covered (warning)
58.06%
18 / 31
0.00% covered (danger)
0.00%
0 / 1
25.46
1<?php
2
3namespace WebPConvert\Convert\Converters;
4
5use WebPConvert\Convert\Converters\AbstractConverter;
6use WebPConvert\Convert\Exceptions\ConversionFailedException;
7use WebPConvert\Convert\Exceptions\ConversionFailed\ConverterNotOperational\SystemRequirementsNotMetException;
8use WebPConvert\Convert\Converters\ConverterTraits\EncodingAutoTrait;
9
10//use WebPConvert\Convert\Exceptions\ConversionFailed\InvalidInput\TargetNotFoundException;
11
12/**
13 * Convert images to webp using Gmagick extension.
14 *
15 * @package    WebPConvert
16 * @author     Bjørn Rosell <it@rosell.dk>
17 * @since      Class available since Release 2.0.0
18 */
19class Gmagick extends AbstractConverter
20{
21    use EncodingAutoTrait;
22
23    protected function getUnsupportedDefaultOptions()
24    {
25        return [
26            'near-lossless',
27            'size-in-percentage',
28        ];
29    }
30
31    /**
32     * Check (general) operationality of Gmagick 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     */
40    public function checkOperationality()
41    {
42        if (!extension_loaded('Gmagick')) {
43            throw new SystemRequirementsNotMetException('Required Gmagick extension is not available.');
44        }
45
46        if (!class_exists('Gmagick')) {
47            throw new SystemRequirementsNotMetException(
48                'Gmagick is installed, but not correctly. The class Gmagick is not available'
49            );
50        }
51
52        $im = new \Gmagick($this->source);
53
54        if (!in_array('WEBP', $im->queryformats())) {
55            throw new SystemRequirementsNotMetException('Gmagick 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 Gmagick does not support image type
63     */
64    public function checkConvertability()
65    {
66        $im = new \Gmagick();
67        $mimeType = $this->getMimeTypeOfSource();
68        switch ($mimeType) {
69            case 'image/png':
70                if (!in_array('PNG', $im->queryFormats())) {
71                    throw new SystemRequirementsNotMetException(
72                        'Gmagick 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())) {
78                    throw new SystemRequirementsNotMetException(
79                        'Gmagick has been compiled without Jpeg support and can therefore not convert this Jpeg image.'
80                    );
81                }
82                break;
83        }
84    }
85
86    // Although this method is public, do not call directly.
87    // You should rather call the static convert() function, defined in AbstractConverter, which
88    // takes care of preparing stuff before calling doConvert, and validating after.
89    protected function doActualConvert()
90    {
91
92        // PS: graphicsmagick options are documented here: (search for "webp:")
93        // http://www.graphicsmagick.org/GraphicsMagick.html
94
95        $options = $this->options;
96
97        try {
98            $im = new \Gmagick($this->source);
99        } catch (\Exception $e) {
100            throw new ConversionFailedException(
101                'Failed creating Gmagick object of file',
102                'Failed creating Gmagick object of file: "' . $this->source . '" - Gmagick threw an exception.',
103                $e
104            );
105        }
106
107        $im->setimageformat('WEBP');
108
109        // setimageoption() has not always been there, so check first. #169
110        if (method_exists($im, 'setimageoption')) {
111            // Finally cracked setting webp options.
112            // See #167
113            // - and https://stackoverflow.com/questions/47294962/how-to-write-lossless-webp-files-with-perlmagick
114
115            if (!is_null($options['preset'])) {
116                if ($options['preset'] != 'none') {
117                    $imageHint = $options['preset'];
118                    switch ($imageHint) {
119                        case 'drawing':
120                        case 'icon':
121                        case 'text':
122                            $imageHint = 'graph';
123                            $this->logLn(
124                                'The "preset" value was mapped to "graph" because gmagick does not support "drawing",' .
125                                ' "icon" and "text", but grouped these into one option: "graph".'
126                            );
127                    }
128                    $im->setimageoption('webp', 'image-hint', $imageHint);
129                }
130            }
131            $im->setimageoption('webp', 'method', $options['method']);
132            $im->setimageoption('webp', 'lossless', $options['encoding'] == 'lossless' ? 'true' : 'false');
133            $im->setimageoption('webp', 'alpha-quality', $options['alpha-quality']);
134
135            if ($options['auto-filter'] === true) {
136                $im->setimageoption('webp', 'auto-filter', 'true');
137            }
138
139            if ($options['sharp-yuv'] === true) {
140                $im->setimageoption('webp', 'use-sharp-yuv', 'true');
141            }
142        }
143
144        /*
145        low-memory seems not to be supported:
146        $im->setimageoption('webp', 'low-memory', $options['low-memory'] ? true : false);
147        */
148
149        if ($options['metadata'] == 'none') {
150            // Strip metadata and profiles
151            $im->stripImage();
152        }
153
154        // Ps: Imagick automatically uses same quality as source, when no quality is set
155        // This feature is however not present in Gmagick
156        // TODO: However, it might be possible after all - see #91
157        $im->setcompressionquality($this->getCalculatedQuality());
158
159        // We call getImageBlob().
160        // That method is undocumented, but it is there!
161        // - just like it is in imagick, as pointed out here:
162        //   https://www.php.net/manual/ru/gmagick.readimageblob.php
163
164        /** @scrutinizer ignore-call */
165        $imageBlob = $im->getImageBlob();
166
167        $success = @file_put_contents($this->destination, $imageBlob);
168
169        if (!$success) {
170            throw new ConversionFailedException('Failed writing file');
171        }
172    }
173}