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