r96687 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r96686‎ | r96687 | r96688 >
Date:20:13, 9 September 2011
Author:bawolff
Status:ok (Comments)
Tags:
Comment:
(bug 30640; follow-up r92279) Rotating images was making skewed images

This is Bryan's patch from bug 30640 with a couple minor related changes, plus some unit tests.
This also addresses an issue with preventing too-big images from being scaled from r92279.

I also noticed that image magick's rotation support is broken in 6.3.7 (the version I had installed locally. I've since upgraded) I'm not sure if we should be doing something about that...

I did test this without both image magick, and gd (although only very briefly with gd) both seemed to work well. I didn't test any other image scalars.
Modified paths:
  • /trunk/phase3/includes/media/Bitmap.php (modified) (history)
  • /trunk/phase3/tests/phpunit/includes/media/BitmapScalingTest.php (modified) (history)
  • /trunk/phase3/tests/phpunit/includes/media/ExifRotationTest.php (modified) (history)

Diff [purge]

Index: trunk/phase3/tests/phpunit/includes/media/ExifRotationTest.php
@@ -8,6 +8,7 @@
99 function setUp() {
1010 parent::setUp();
1111 $this->filePath = dirname( __FILE__ ) . '/../../data/media/';
 12+ $this->handler = new BitmapHandler();
1213 }
1314
1415 /**
@@ -15,17 +16,16 @@
1617 * @dataProvider providerFiles
1718 */
1819 function testMetadata( $name, $type, $info ) {
19 - $handler = new BitmapHandler();
2020 # Force client side resizing
2121 $params = array( 'width' => 10000, 'height' => 10000 );
2222 $file = UnregisteredLocalFile::newFromPath( $this->filePath . $name, $type );
2323
2424 # 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 );
2727
2828 # 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 );
3030 $this->assertEquals( $file->getWidth(), $width,
3131 "$name: pre-rotation width check, $rotation:$width" );
3232 $this->assertEquals( $file->getHeight(), $height,
@@ -73,8 +73,7 @@
7474 * @dataProvider provideBitmapExtractPreRotationDimensions
7575 */
7676 function testBitmapExtractPreRotationDimensions( $rotation, $expected ) {
77 - $handler = new BitmapHandler;
78 - $result = $handler->extractPreRotationDimensions( array(
 77+ $result = $this->handler->extractPreRotationDimensions( array(
7978 'physicalWidth' => self::TEST_WIDTH,
8079 'physicalHeight' => self::TEST_HEIGHT,
8180 ), $rotation );
@@ -101,5 +100,22 @@
102101 ),
103102 );
104103 }
 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+ }
105121 }
106122
Index: trunk/phase3/tests/phpunit/includes/media/BitmapScalingTest.php
@@ -1,13 +1,24 @@
22 <?php
33
44 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+ }
515 /**
616 * @dataProvider provideNormaliseParams
717 */
818 function testNormaliseParams( $fileDimensions, $expectedParams, $params, $msg ) {
919 $file = new FakeDimensionFile( $fileDimensions );
1020 $handler = new BitmapHandler;
11 - $handler->normaliseParams( $file, $params );
 21+ $valid = $handler->normaliseParams( $file, $params );
 22+ $this->assertTrue( $valid );
1223 $this->assertEquals( $expectedParams, $params, $msg );
1324 }
1425
@@ -77,11 +88,37 @@
7889 array( 'width' => 10, 'height' => 5 ),
7990 'Very high image with height set',
8091 ),
 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+ ),
81103 );
82104 }
 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+ }
83118 }
84119
85120 class FakeDimensionFile extends File {
 121+ public $mustRender = false;
 122+
86123 public function __construct( $dimensions ) {
87124 parent::__construct( Title::makeTitle( NS_FILE, 'Test' ), null );
88125
@@ -93,4 +130,7 @@
94131 public function getHeight( $page = 1 ) {
95132 return $this->dimensions[1];
96133 }
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 @@
1616
1717 /**
1818 * @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.
2022 * @return bool
2123 */
2224 function normaliseParams( $image, &$params ) {
@@ -25,38 +27,36 @@
2628 }
2729
2830 $mimeType = $image->getMimeType();
 31+ # Obtain the source, pre-rotation dimensions
2932 $srcWidth = $image->getWidth( $params['page'] );
3033 $srcHeight = $image->getHeight( $params['page'] );
3134
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+
3348 if ( self::canRotate() ) {
3449 $rotation = $this->getRotation( $image );
3550 if ( $rotation == 90 || $rotation == 270 ) {
3651 wfDebug( __METHOD__ . ": Swapping width and height because the file will be rotated $rotation degrees\n" );
3752
38 - $swapDimensions = true;
3953 list( $params['width'], $params['height'] ) =
40 - array( $params['width'], $params['height'] );
 54+ array( $params['height'], $params['width'] );
4155 list( $params['physicalWidth'], $params['physicalHeight'] ) =
42 - array( $params['physicalWidth'], $params['physicalHeight'] );
 56+ array( $params['physicalHeight'], $params['physicalWidth'] );
4357 }
4458 }
4559
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 - }
5660
57 - # Skip scaling limit checks if no scaling is required
58 - if ( !$image->mustRender() )
59 - return true;
60 -
6161 # Don't thumbnail an image so big that it will fill hard drives and send servers into swap
6262 # JPEG has the handy property of allowing thumbnailing without full decompression, so we make
6363 # an exception for it.

Follow-up revisions

RevisionCommit summaryAuthorDate
r96849REL1_18: r96509, r96522, r96606, r96643, r96645, r96655, r96659, r96687, r967......reedy15:03, 12 September 2011
r97656Further tweaks to r96687, r90016, r97398 etc tests: actually produce a thumbn...brion19:39, 20 September 2011
r97659Further tweaks to r96687, r90016, r97398, r97656 etc tests: try several thumb...brion20:04, 20 September 2011
r97671* (bug 6672, 31024) Fixes for handling of images with an EXIF orientation...brion22:13, 20 September 2011

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r92279(bug 28762) Resizing to specified height broken for very thin images...btongminh19:03, 15 July 2011

Comments

#Comment by Aaron Schulz (talk | contribs)   21:18, 9 September 2011

The logic here is a lot easier to follow now.

Status & tagging log