5ae1763596dbff7a33ccd489f32836459a1e03d9
[lhc/web/wiklou.git] / tests / phpunit / includes / media / ExifRotationTest.php
1 <?php
2 /**
3 * Tests related to auto rotation.
4 *
5 * @group Media
6 * @group medium
7 *
8 * @todo covers tags
9 */
10 class ExifRotationTest extends MediaWikiMediaTestCase {
11
12 protected function setUp() {
13 parent::setUp();
14 $this->checkPHPExtension( 'exif' );
15
16 $this->handler = new BitmapHandler();
17
18 $this->setMwGlobals( [
19 'wgShowEXIF' => true,
20 'wgEnableAutoRotation' => true,
21 ] );
22 }
23
24 /**
25 * Mark this test as creating thumbnail files.
26 */
27 protected function createsThumbnails() {
28 return true;
29 }
30
31 /**
32 * @dataProvider provideFiles
33 */
34 public function testMetadata( $name, $type, $info ) {
35 if ( !$this->handler->canRotate() ) {
36 $this->markTestSkipped( "This test needs a rasterizer that can auto-rotate." );
37 }
38 $file = $this->dataFile( $name, $type );
39 $this->assertEquals( $info['width'], $file->getWidth(), "$name: width check" );
40 $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
41 }
42
43 /**
44 * Same as before, but with auto-rotation set to auto.
45 *
46 * This sets scaler to image magick, which we should detect as
47 * supporting rotation.
48 * @dataProvider provideFiles
49 */
50 public function testMetadataAutoRotate( $name, $type, $info ) {
51 $this->setMwGlobals( 'wgEnableAutoRotation', null );
52 $this->setMwGlobals( 'wgUseImageMagick', true );
53 $this->setMwGlobals( 'wgUseImageResize', true );
54
55 $file = $this->dataFile( $name, $type );
56 $this->assertEquals( $info['width'], $file->getWidth(), "$name: width check" );
57 $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
58 }
59
60 /**
61 *
62 * @dataProvider provideFiles
63 */
64 public function testRotationRendering( $name, $type, $info, $thumbs ) {
65 if ( !$this->handler->canRotate() ) {
66 $this->markTestSkipped( "This test needs a rasterizer that can auto-rotate." );
67 }
68 foreach ( $thumbs as $size => $out ) {
69 if ( preg_match( '/^(\d+)px$/', $size, $matches ) ) {
70 $params = [
71 'width' => $matches[1],
72 ];
73 } elseif ( preg_match( '/^(\d+)x(\d+)px$/', $size, $matches ) ) {
74 $params = [
75 'width' => $matches[1],
76 'height' => $matches[2]
77 ];
78 } else {
79 throw new MWException( 'bogus test data format ' . $size );
80 }
81
82 $file = $this->dataFile( $name, $type );
83 $thumb = $file->transform( $params, File::RENDER_NOW | File::RENDER_FORCE );
84
85 $this->assertEquals(
86 $out[0],
87 $thumb->getWidth(),
88 "$name: thumb reported width check for $size"
89 );
90 $this->assertEquals(
91 $out[1],
92 $thumb->getHeight(),
93 "$name: thumb reported height check for $size"
94 );
95
96 $gis = getimagesize( $thumb->getLocalCopyPath() );
97 if ( $out[0] > $info['width'] ) {
98 // Physical image won't be scaled bigger than the original.
99 $this->assertEquals( $info['width'], $gis[0], "$name: thumb actual width check for $size" );
100 $this->assertEquals( $info['height'], $gis[1], "$name: thumb actual height check for $size" );
101 } else {
102 $this->assertEquals( $out[0], $gis[0], "$name: thumb actual width check for $size" );
103 $this->assertEquals( $out[1], $gis[1], "$name: thumb actual height check for $size" );
104 }
105 }
106 }
107
108 public static function provideFiles() {
109 return [
110 [
111 'landscape-plain.jpg',
112 'image/jpeg',
113 [
114 'width' => 1024,
115 'height' => 768,
116 ],
117 [
118 '800x600px' => [ 800, 600 ],
119 '9999x800px' => [ 1067, 800 ],
120 '800px' => [ 800, 600 ],
121 '600px' => [ 600, 450 ],
122 ]
123 ],
124 [
125 'portrait-rotated.jpg',
126 'image/jpeg',
127 [
128 'width' => 768, // as rotated
129 'height' => 1024, // as rotated
130 ],
131 [
132 '800x600px' => [ 450, 600 ],
133 '9999x800px' => [ 600, 800 ],
134 '800px' => [ 800, 1067 ],
135 '600px' => [ 600, 800 ],
136 ]
137 ]
138 ];
139 }
140
141 /**
142 * Same as before, but with auto-rotation disabled.
143 * @dataProvider provideFilesNoAutoRotate
144 */
145 public function testMetadataNoAutoRotate( $name, $type, $info ) {
146 $this->setMwGlobals( 'wgEnableAutoRotation', false );
147
148 $file = $this->dataFile( $name, $type );
149 $this->assertEquals( $info['width'], $file->getWidth(), "$name: width check" );
150 $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
151 }
152
153 /**
154 * Same as before, but with auto-rotation set to auto and an image scaler that doesn't support it.
155 * @dataProvider provideFilesNoAutoRotate
156 */
157 public function testMetadataAutoRotateUnsupported( $name, $type, $info ) {
158 $this->setMwGlobals( 'wgEnableAutoRotation', null );
159 $this->setMwGlobals( 'wgUseImageResize', false );
160
161 $file = $this->dataFile( $name, $type );
162 $this->assertEquals( $info['width'], $file->getWidth(), "$name: width check" );
163 $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
164 }
165
166 /**
167 *
168 * @dataProvider provideFilesNoAutoRotate
169 */
170 public function testRotationRenderingNoAutoRotate( $name, $type, $info, $thumbs ) {
171 $this->setMwGlobals( 'wgEnableAutoRotation', false );
172
173 foreach ( $thumbs as $size => $out ) {
174 if ( preg_match( '/^(\d+)px$/', $size, $matches ) ) {
175 $params = [
176 'width' => $matches[1],
177 ];
178 } elseif ( preg_match( '/^(\d+)x(\d+)px$/', $size, $matches ) ) {
179 $params = [
180 'width' => $matches[1],
181 'height' => $matches[2]
182 ];
183 } else {
184 throw new MWException( 'bogus test data format ' . $size );
185 }
186
187 $file = $this->dataFile( $name, $type );
188 $thumb = $file->transform( $params, File::RENDER_NOW | File::RENDER_FORCE );
189
190 $this->assertEquals(
191 $out[0],
192 $thumb->getWidth(),
193 "$name: thumb reported width check for $size"
194 );
195 $this->assertEquals(
196 $out[1],
197 $thumb->getHeight(),
198 "$name: thumb reported height check for $size"
199 );
200
201 $gis = getimagesize( $thumb->getLocalCopyPath() );
202 if ( $out[0] > $info['width'] ) {
203 // Physical image won't be scaled bigger than the original.
204 $this->assertEquals( $info['width'], $gis[0], "$name: thumb actual width check for $size" );
205 $this->assertEquals( $info['height'], $gis[1], "$name: thumb actual height check for $size" );
206 } else {
207 $this->assertEquals( $out[0], $gis[0], "$name: thumb actual width check for $size" );
208 $this->assertEquals( $out[1], $gis[1], "$name: thumb actual height check for $size" );
209 }
210 }
211 }
212
213 public static function provideFilesNoAutoRotate() {
214 return [
215 [
216 'landscape-plain.jpg',
217 'image/jpeg',
218 [
219 'width' => 1024,
220 'height' => 768,
221 ],
222 [
223 '800x600px' => [ 800, 600 ],
224 '9999x800px' => [ 1067, 800 ],
225 '800px' => [ 800, 600 ],
226 '600px' => [ 600, 450 ],
227 ]
228 ],
229 [
230 'portrait-rotated.jpg',
231 'image/jpeg',
232 [
233 'width' => 1024, // since not rotated
234 'height' => 768, // since not rotated
235 ],
236 [
237 '800x600px' => [ 800, 600 ],
238 '9999x800px' => [ 1067, 800 ],
239 '800px' => [ 800, 600 ],
240 '600px' => [ 600, 450 ],
241 ]
242 ]
243 ];
244 }
245
246 const TEST_WIDTH = 100;
247 const TEST_HEIGHT = 200;
248
249 /**
250 * @dataProvider provideBitmapExtractPreRotationDimensions
251 */
252 public function testBitmapExtractPreRotationDimensions( $rotation, $expected ) {
253 $result = $this->handler->extractPreRotationDimensions( [
254 'physicalWidth' => self::TEST_WIDTH,
255 'physicalHeight' => self::TEST_HEIGHT,
256 ], $rotation );
257 $this->assertEquals( $expected, $result );
258 }
259
260 public static function provideBitmapExtractPreRotationDimensions() {
261 return [
262 [
263 0,
264 [ self::TEST_WIDTH, self::TEST_HEIGHT ]
265 ],
266 [
267 90,
268 [ self::TEST_HEIGHT, self::TEST_WIDTH ]
269 ],
270 [
271 180,
272 [ self::TEST_WIDTH, self::TEST_HEIGHT ]
273 ],
274 [
275 270,
276 [ self::TEST_HEIGHT, self::TEST_WIDTH ]
277 ],
278 ];
279 }
280 }