Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 62 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
VipsConvolution | |
0.00% |
0 / 62 |
|
0.00% |
0 / 2 |
182 | |
0.00% |
0 / 1 |
execute | |
0.00% |
0 / 48 |
|
0.00% |
0 / 1 |
42 | |||
getFormat | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
56 |
1 | <?php |
2 | /** |
3 | * PHP wrapper class for VIPS under MediaWiki |
4 | * |
5 | * Copyright © Bryan Tong Minh, 2011 |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | * |
12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU General Public License along |
18 | * with this program; if not, write to the Free Software Foundation, Inc., |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
20 | * http://www.gnu.org/copyleft/gpl.html |
21 | * @file |
22 | */ |
23 | |
24 | namespace MediaWiki\Extension\VipsScaler; |
25 | |
26 | use MediaWiki\Shell\Shell; |
27 | use RuntimeException; |
28 | |
29 | /** |
30 | * A wrapper class around im_conv because that command expects a convolution |
31 | * matrix file as its last argument |
32 | */ |
33 | class VipsConvolution extends VipsCommand { |
34 | |
35 | /** |
36 | * @return int |
37 | */ |
38 | public function execute() { |
39 | $format = $this->getFormat( $this->input ); |
40 | # Convert a 2D array into a space/newline separated matrix |
41 | $convolutionMatrix = array_pop( $this->args ); |
42 | $convolutionString = ''; |
43 | foreach ( $convolutionMatrix as $row ) { |
44 | $convolutionString .= implode( ' ', $row ) . "\n"; |
45 | } |
46 | # Save the matrix in a tempfile |
47 | $tmpFile = self::makeTemp( 'conv' ); |
48 | $tmpFile->bind( $this ); |
49 | $convolutionFile = $tmpFile->getPath(); |
50 | file_put_contents( $convolutionFile, $convolutionString ); |
51 | array_push( $this->args, $convolutionFile ); |
52 | |
53 | $tmpOutput = self::makeTemp( 'v' ); |
54 | $tmpOutput->bind( $this ); |
55 | $tmpOutputPath = $tmpOutput->getPath(); |
56 | |
57 | wfDebug( __METHOD__ . ": Convolving image [\n" . $convolutionString . "] \n" ); |
58 | |
59 | $limits = [ 'filesize' => 409600 ]; |
60 | $env = [ 'IM_CONCURRENCY' => '1' ]; |
61 | |
62 | $cmd = [ |
63 | $this->vips, |
64 | array_shift( $this->args ), |
65 | $this->input, |
66 | $tmpOutputPath |
67 | ]; |
68 | $cmd = array_merge( $cmd, $this->args ); |
69 | |
70 | // Execute |
71 | $result = Shell::command( $cmd ) |
72 | ->environment( $env ) |
73 | ->limits( $limits ) |
74 | ->includeStderr() |
75 | ->execute(); |
76 | $retval = $result->getExitCode(); |
77 | $this->err = $result->getStdout(); |
78 | |
79 | if ( $retval === 0 ) { |
80 | // vips seems to get confused about the bit depth after a convolution |
81 | // so reset it. Without this step, 16-bit tiff files seem to become all |
82 | // black when converted to pngs (https://github.com/jcupitt/libvips/issues/344) |
83 | $formatCmd = [ |
84 | $this->vips, 'im_clip2fmt', $tmpOutputPath, $this->output, (string)$format |
85 | ]; |
86 | $result = Shell::command( $formatCmd ) |
87 | ->environment( $env ) |
88 | ->limits( $limits ) |
89 | ->includeStderr() |
90 | ->execute(); |
91 | $retval = $result->getExitCode(); |
92 | $this->err .= $result->getStdout(); |
93 | } |
94 | |
95 | // Cleanup temp file |
96 | if ( $retval != 0 && file_exists( $this->output ) ) { |
97 | unlink( $this->output ); |
98 | } |
99 | if ( $this->removeInput ) { |
100 | unlink( $this->input ); |
101 | } |
102 | |
103 | // Remove the temporary matrix file |
104 | $tmpFile->purge(); |
105 | $tmpOutput->purge(); |
106 | |
107 | return $retval; |
108 | } |
109 | |
110 | /** |
111 | * Get the vips internal format (aka bit depth) |
112 | * |
113 | * @see https://github.com/jcupitt/libvips/issues/344 for why we do this |
114 | * @param string $input Path to file |
115 | * @return int Vips internal format number |
116 | * (common value 0 = VIPS_FORMAT_UCHAR, 2 = VIPS_FORMAT_USHORT) |
117 | */ |
118 | private function getFormat( $input ) { |
119 | $cmd = [ $this->vips, 'im_header_int', 'format', $input ]; |
120 | $result = Shell::command( $cmd ) |
121 | ->environment( [ 'IM_CONCURRENCY' => '1' ] ) |
122 | ->execute(); |
123 | |
124 | $res = trim( $result->getStdout() ); |
125 | |
126 | if ( $result->getExitCode() !== 0 || !is_numeric( $res ) ) { |
127 | throw new RuntimeException( "Cannot determine vips format of image" ); |
128 | } |
129 | |
130 | $format = (int)$res; |
131 | // Must be in range -1 to 10 |
132 | // We might want to be even stricter. Its assumed that the answer will usually be 0 or 2. |
133 | if ( $format < -1 || $format > 10 ) { |
134 | throw new RuntimeException( "vips format '$format' is invalid" ); |
135 | } |
136 | if ( $format === -1 || $format >= 6 ) { |
137 | // This will still work, but not something we expect to ever get. So log. |
138 | wfDebugLog( 'vips', __METHOD__ . ": Vips format value is outside the range expected " . |
139 | "(got: $format)\n" ); |
140 | } |
141 | |
142 | return $format; |
143 | } |
144 | } |