Index: trunk/phase3/tests/phpunit/includes/media/ExifRotationTest.php |
— | — | @@ -8,6 +8,7 @@ |
9 | 9 | function setUp() { |
10 | 10 | parent::setUp(); |
11 | 11 | $this->filePath = dirname( __FILE__ ) . '/../../data/media/'; |
| 12 | + $this->handler = new BitmapHandler(); |
12 | 13 | } |
13 | 14 | |
14 | 15 | /** |
— | — | @@ -15,17 +16,16 @@ |
16 | 17 | * @dataProvider providerFiles |
17 | 18 | */ |
18 | 19 | function testMetadata( $name, $type, $info ) { |
19 | | - $handler = new BitmapHandler(); |
20 | 20 | # Force client side resizing |
21 | 21 | $params = array( 'width' => 10000, 'height' => 10000 ); |
22 | 22 | $file = UnregisteredLocalFile::newFromPath( $this->filePath . $name, $type ); |
23 | 23 | |
24 | 24 | # Normalize parameters |
25 | | - $this->assertTrue( $handler->normaliseParams( $file, $params ) ); |
26 | | - $rotation = $handler->getRotation( $file ); |
| 25 | + $this->assertTrue( $this->handler->normaliseParams( $file, $params ) ); |
| 26 | + $rotation = $this->handler->getRotation( $file ); |
27 | 27 | |
28 | 28 | # Check if pre-rotation dimensions are still good |
29 | | - list( $width, $height ) = $handler->extractPreRotationDimensions( $params, $rotation ); |
| 29 | + list( $width, $height ) = $this->handler->extractPreRotationDimensions( $params, $rotation ); |
30 | 30 | $this->assertEquals( $file->getWidth(), $width, |
31 | 31 | "$name: pre-rotation width check, $rotation:$width" ); |
32 | 32 | $this->assertEquals( $file->getHeight(), $height, |
— | — | @@ -73,8 +73,7 @@ |
74 | 74 | * @dataProvider provideBitmapExtractPreRotationDimensions |
75 | 75 | */ |
76 | 76 | function testBitmapExtractPreRotationDimensions( $rotation, $expected ) { |
77 | | - $handler = new BitmapHandler; |
78 | | - $result = $handler->extractPreRotationDimensions( array( |
| 77 | + $result = $this->handler->extractPreRotationDimensions( array( |
79 | 78 | 'physicalWidth' => self::TEST_WIDTH, |
80 | 79 | 'physicalHeight' => self::TEST_HEIGHT, |
81 | 80 | ), $rotation ); |
— | — | @@ -101,5 +100,22 @@ |
102 | 101 | ), |
103 | 102 | ); |
104 | 103 | } |
| 104 | + |
| 105 | + function testWidthFlipping() { |
| 106 | + $file = UnregisteredLocalFile::newFromPath( $this->filePath . 'portrait-rotated.jpg', 'image/jpeg' ); |
| 107 | + $params = array( 'width' => '50' ); |
| 108 | + $this->assertTrue( $this->handler->normaliseParams( $file, $params ) ); |
| 109 | + |
| 110 | + $this->assertEquals( 50, $params['height'] ); |
| 111 | + $this->assertEquals( round( (768/1024)*50 ), $params['width'], '', 0.1 ); |
| 112 | + } |
| 113 | + function testWidthNotFlipping() { |
| 114 | + $file = UnregisteredLocalFile::newFromPath( $this->filePath . 'landscape-plain.jpg', 'image/jpeg' ); |
| 115 | + $params = array( 'width' => '50' ); |
| 116 | + $this->assertTrue( $this->handler->normaliseParams( $file, $params ) ); |
| 117 | + |
| 118 | + $this->assertEquals( 50, $params['width'] ); |
| 119 | + $this->assertEquals( round( (768/1024)*50 ), $params['height'], '', 0.1 ); |
| 120 | + } |
105 | 121 | } |
106 | 122 | |
Index: trunk/phase3/tests/phpunit/includes/media/BitmapScalingTest.php |
— | — | @@ -1,13 +1,24 @@ |
2 | 2 | <?php |
3 | 3 | |
4 | 4 | class BitmapScalingTest extends MediaWikiTestCase { |
| 5 | + |
| 6 | + function setUp() { |
| 7 | + global $wgMaxImageArea; |
| 8 | + $this->oldMaxImageArea = $wgMaxImageArea; |
| 9 | + $wgMaxImageArea = 1.25e7; // 3500x3500 |
| 10 | + } |
| 11 | + function tearDown() { |
| 12 | + global $wgMaxImageArea; |
| 13 | + $wgMaxImageArea = $this->oldMaxImageArea; |
| 14 | + } |
5 | 15 | /** |
6 | 16 | * @dataProvider provideNormaliseParams |
7 | 17 | */ |
8 | 18 | function testNormaliseParams( $fileDimensions, $expectedParams, $params, $msg ) { |
9 | 19 | $file = new FakeDimensionFile( $fileDimensions ); |
10 | 20 | $handler = new BitmapHandler; |
11 | | - $handler->normaliseParams( $file, $params ); |
| 21 | + $valid = $handler->normaliseParams( $file, $params ); |
| 22 | + $this->assertTrue( $valid ); |
12 | 23 | $this->assertEquals( $expectedParams, $params, $msg ); |
13 | 24 | } |
14 | 25 | |
— | — | @@ -77,11 +88,37 @@ |
78 | 89 | array( 'width' => 10, 'height' => 5 ), |
79 | 90 | 'Very high image with height set', |
80 | 91 | ), |
| 92 | + /* Max image area */ |
| 93 | + array( |
| 94 | + array( 4000, 4000 ), |
| 95 | + array( |
| 96 | + 'width' => 5000, 'height' => 5000, |
| 97 | + 'physicalWidth' => 4000, 'physicalHeight' => 4000, |
| 98 | + 'page' => 1, |
| 99 | + ), |
| 100 | + array( 'width' => 5000 ), |
| 101 | + 'Bigger than max image size but doesn\'t need scaling', |
| 102 | + ), |
81 | 103 | ); |
82 | 104 | } |
| 105 | + function testTooBigImage() { |
| 106 | + $file = new FakeDimensionFile( array( 4000, 4000 ) ); |
| 107 | + $handler = new BitmapHandler; |
| 108 | + $params = array( 'width' => '3700' ); // Still bigger than max size. |
| 109 | + $this->assertFalse( $handler->normaliseParams( $file, $params ) ); |
| 110 | + } |
| 111 | + function testTooBigMustRenderImage() { |
| 112 | + $file = new FakeDimensionFile( array( 4000, 4000 ) ); |
| 113 | + $file->mustRender = true; |
| 114 | + $handler = new BitmapHandler; |
| 115 | + $params = array( 'width' => '5000' ); // Still bigger than max size. |
| 116 | + $this->assertFalse( $handler->normaliseParams( $file, $params ) ); |
| 117 | + } |
83 | 118 | } |
84 | 119 | |
85 | 120 | class FakeDimensionFile extends File { |
| 121 | + public $mustRender = false; |
| 122 | + |
86 | 123 | public function __construct( $dimensions ) { |
87 | 124 | parent::__construct( Title::makeTitle( NS_FILE, 'Test' ), null ); |
88 | 125 | |
— | — | @@ -93,4 +130,7 @@ |
94 | 131 | public function getHeight( $page = 1 ) { |
95 | 132 | return $this->dimensions[1]; |
96 | 133 | } |
97 | | -} |
\ No newline at end of file |
| 134 | + public function mustRender() { |
| 135 | + return $this->mustRender; |
| 136 | + } |
| 137 | +} |
Index: trunk/phase3/includes/media/Bitmap.php |
— | — | @@ -15,7 +15,9 @@ |
16 | 16 | |
17 | 17 | /** |
18 | 18 | * @param $image File |
19 | | - * @param $params |
| 19 | + * @param $params array Transform parameters. Entries with the keys 'width' |
| 20 | + * and 'height' are the respective screen width and height, while the keys |
| 21 | + * 'physicalWidth' and 'physicalHeight' indicate the thumbnail dimensions. |
20 | 22 | * @return bool |
21 | 23 | */ |
22 | 24 | function normaliseParams( $image, &$params ) { |
— | — | @@ -25,38 +27,36 @@ |
26 | 28 | } |
27 | 29 | |
28 | 30 | $mimeType = $image->getMimeType(); |
| 31 | + # Obtain the source, pre-rotation dimensions |
29 | 32 | $srcWidth = $image->getWidth( $params['page'] ); |
30 | 33 | $srcHeight = $image->getHeight( $params['page'] ); |
31 | 34 | |
32 | | - $swapDimensions = false; |
| 35 | + # Don't make an image bigger than the source |
| 36 | + if ( $params['physicalWidth'] >= $srcWidth ) { |
| 37 | + $params['physicalWidth'] = $srcWidth; |
| 38 | + $params['physicalHeight'] = $srcHeight; |
| 39 | + |
| 40 | + # Skip scaling limit checks if no scaling is required |
| 41 | + # due to requested size being bigger than source. |
| 42 | + if ( !$image->mustRender() ) { |
| 43 | + return true; |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + |
33 | 48 | if ( self::canRotate() ) { |
34 | 49 | $rotation = $this->getRotation( $image ); |
35 | 50 | if ( $rotation == 90 || $rotation == 270 ) { |
36 | 51 | wfDebug( __METHOD__ . ": Swapping width and height because the file will be rotated $rotation degrees\n" ); |
37 | 52 | |
38 | | - $swapDimensions = true; |
39 | 53 | list( $params['width'], $params['height'] ) = |
40 | | - array( $params['width'], $params['height'] ); |
| 54 | + array( $params['height'], $params['width'] ); |
41 | 55 | list( $params['physicalWidth'], $params['physicalHeight'] ) = |
42 | | - array( $params['physicalWidth'], $params['physicalHeight'] ); |
| 56 | + array( $params['physicalHeight'], $params['physicalWidth'] ); |
43 | 57 | } |
44 | 58 | } |
45 | 59 | |
46 | | - # Don't make an image bigger than the source |
47 | | - if ( $params['physicalWidth'] >= $srcWidth ) { |
48 | | - if ( $swapDimensions ) { |
49 | | - $params['physicalWidth'] = $srcHeight; |
50 | | - $params['physicalHeight'] = $srcWidth; |
51 | | - } else { |
52 | | - $params['physicalWidth'] = $srcWidth; |
53 | | - $params['physicalHeight'] = $srcHeight; |
54 | | - } |
55 | | - } |
56 | 60 | |
57 | | - # Skip scaling limit checks if no scaling is required |
58 | | - if ( !$image->mustRender() ) |
59 | | - return true; |
60 | | - |
61 | 61 | # Don't thumbnail an image so big that it will fill hard drives and send servers into swap |
62 | 62 | # JPEG has the handy property of allowing thumbnailing without full decompression, so we make |
63 | 63 | # an exception for it. |