Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.45% covered (success)
92.45%
49 / 53
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
AutoQualityTrait
92.45% covered (success)
92.45%
49 / 53
75.00% covered (warning)
75.00%
3 / 4
13.07
0.00% covered (danger)
0.00%
0 / 1
 logLn
n/a
0 / 0
n/a
0 / 0
0
 getMimeTypeOfSource
n/a
0 / 0
n/a
0 / 0
0
 isQualityDetectionRequiredButFailing
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getCalculatedQuality
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 processQualityOptionIfNotAlready
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 processQualityOption
91.30% covered (success)
91.30%
42 / 46
0.00% covered (danger)
0.00%
0 / 1
9.05
1<?php
2
3namespace WebPConvert\Convert\Converters\BaseTraits;
4
5use WebPConvert\Convert\Helpers\JpegQualityDetector;
6
7/**
8 * Trait for handling the "quality:auto" option.
9 *
10 * This trait is only used in the AbstractConverter class. It has been extracted into a
11 * trait in order to bundle the methods concerning auto quality.
12 *
13 * @package    WebPConvert
14 * @author     Bjørn Rosell <it@rosell.dk>
15 * @since      Class available since Release 2.0.0
16 */
17trait AutoQualityTrait
18{
19
20    abstract public function logLn($msg, $style = '');
21    abstract public function getMimeTypeOfSource();
22
23    /** @var boolean  Whether the quality option has been processed or not */
24    private $processed = false;
25
26    /** @var boolean  Whether the quality of the source could be detected or not (set upon processing) */
27    private $qualityCouldNotBeDetected = false;
28
29    /** @var integer  The calculated quality (set upon processing - on successful detection) */
30    private $calculatedQuality;
31
32
33    /**
34     *  Determine if quality detection is required but failing.
35     *
36     *  It is considered "required" when:
37     *  - Mime type is "image/jpeg"
38     *  - Quality is set to "auto"
39     *
40     *  If quality option hasn't been proccessed yet, it is triggered.
41     *
42     *  @return  boolean
43     */
44    public function isQualityDetectionRequiredButFailing()
45    {
46        $this->processQualityOptionIfNotAlready();
47        return $this->qualityCouldNotBeDetected;
48    }
49
50    /**
51     * Get calculated quality.
52     *
53     * If the "quality" option is a number, that number is returned.
54     * If mime type of source is something else than "image/jpeg", the "default-quality" option is returned
55     * If quality is "auto" and source is a jpeg image, it will be attempted to detect jpeg quality.
56     * In case of failure, the value of the "default-quality" option is returned.
57     * In case of success, the detected quality is returned, or the value of the "max-quality" if that is lower.
58     *
59     *  @return  int
60     */
61    public function getCalculatedQuality()
62    {
63        $this->processQualityOptionIfNotAlready();
64        return $this->calculatedQuality;
65    }
66
67    /**
68     * Process the quality option if it is not already processed.
69     *
70     * @return void
71     */
72    private function processQualityOptionIfNotAlready()
73    {
74        if (!$this->processed) {
75            $this->processed = true;
76            $this->processQualityOption();
77        }
78    }
79
80    /**
81     * Process the quality option.
82     *
83     * Sets the private property "calculatedQuality" according to the description for the getCalculatedQuality
84     * function.
85     * In case quality detection was attempted and failed, the private property "qualityCouldNotBeDetected" is set
86     * to true. This is used by the "isQualityDetectionRequiredButFailing" (and documented there too).
87     *
88     * @return void
89     */
90    private function processQualityOption()
91    {
92        $options = $this->options;
93        $source = $this->source;
94
95        /*
96        Mapping from old options to new options:
97        quality: "auto", max-quality: 85, default-quality: 75
98        becomes: quality: 85, auto-limit: true
99
100        quality: 80
101        becomes: quality: 80, auto-limit: false
102        */
103        $q = $options['quality'];
104        $useDeprecatedDefaultQuality = false;
105        if ($q == 'auto') {
106            $q = $options['quality'] = $options['max-quality'];
107            $this->logLn(
108                '*Setting "quality" to "auto" is deprecated. ' .
109                'Instead, set "quality" to a number (0-100) and "auto-limit" to true. '
110            );
111            $this->logLn(
112                '*"quality" has been set to: ' . $options['max-quality'] . ' (took the value of "max-quality").*'
113            );
114            if (!$this->options2->getOptionById('auto-limit')->isValueExplicitlySet()) {
115                $options['auto-limit'] = true;
116                $this->logLn(
117                    '*"auto-limit" has been set to: true."*'
118                );
119            } else {
120                $this->logLn(
121                    '*PS: "auto-limit" is set to false, as it was set explicitly to false in the options."*'
122                );
123            }
124            $useDeprecatedDefaultQuality = true;
125        }
126
127        if ($options['auto-limit']) {
128            if (($this->/** @scrutinizer ignore-call */getMimeTypeOfSource() == 'image/jpeg')) {
129                $this->logLn('Running auto-limit');
130                $this->logLn(
131                    'Quality setting: ' . $q . '. '
132                );
133                $q = JpegQualityDetector::detectQualityOfJpg($source);
134                if (is_null($q)) {
135                    $this->/** @scrutinizer ignore-call */logLn(
136                        'Quality of source image could not be established (Imagick or GraphicsMagick is required). ' .
137                        'Sorry, no auto-limit functionality for you. '
138                    );
139                    if ($useDeprecatedDefaultQuality) {
140                        $q = $options['default-quality'];
141                        $this->/** @scrutinizer ignore-call */logLn(
142                            'Using default-quality (' . $q . ').'
143                        );
144                    } else {
145                        $q = $options['quality'];
146                        $this->/** @scrutinizer ignore-call */logLn(
147                            'Using supplied quality (' . $q . ').'
148                        );
149                    }
150
151                    $this->qualityCouldNotBeDetected = true;
152                } else {
153                    $this->logLn(
154                        'Quality of jpeg: ' . $q . '. '
155                    );
156                    if ($q < $options['quality']) {
157                        $this->logLn(
158                            'Auto-limit result: ' . $q . ' ' .
159                            '(limiting applied).'
160                        );
161                    } else {
162                        $q = $options['quality'];
163                        $this->logLn(
164                            'Auto-limit result: ' . $q . ' ' .
165                            '(no limiting needed this time).'
166                        );
167                    }
168                }
169                $q = min($q, $options['max-quality']);
170            } else {
171                $this->logLn('Bypassing auto-limit (it is only active for jpegs)');
172                $this->logLn('Quality: ' . $q . '. ');
173            }
174        } else {
175            $this->logLn(
176                'Quality: ' . $q . '. '
177            );
178            if (($this->getMimeTypeOfSource() == 'image/jpeg')) {
179                $this->logLn(
180                    'Consider enabling "auto-limit" option. This will prevent unnecessary high quality'
181                );
182            }
183        }
184        $this->calculatedQuality = $q;
185    }
186}