r92246 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r92245‎ | r92246 | r92247 >
Date:15:13, 15 July 2011
Author:btongminh
Status:resolved (Comments)
Tags:
Comment:
Follow-up r79845: Fix rotation. Turns out that we need to pass the pre-rotation dimensions to convert.exe. Also added tests.
Modified paths:
  • /trunk/phase3/includes/media/Bitmap.php (modified) (history)
  • /trunk/phase3/tests/phpunit/includes/media/ExifRotationTest.php (modified) (history)

Diff [purge]

Index: trunk/phase3/tests/phpunit/includes/media/ExifRotationTest.php
@@ -1,11 +1,12 @@
22 <?php
33
44 /**
5 - * @group Broken
 5+ * Tests related to auto rotation
66 */
77 class ExifRotationTest extends MediaWikiTestCase {
88
99 function setUp() {
 10+ parent::setUp();
1011 }
1112
1213 /**
@@ -14,10 +15,32 @@
1516 */
1617 function testMetadata( $name, $type, $info ) {
1718 $handler = new BitmapHandler();
18 -
 19+ # Force client side resizing
 20+ $params = array( 'width' => 10000, 'height' => 10000 );
1921 $file = UnregisteredLocalFile::newFromPath( dirname( __FILE__ ) . '/' . $name, $type );
20 - $this->assertEquals( $file->getWidth(), $info['width'], "$name: width check" );
21 - $this->assertEquals( $file->getHeight(), $info['height'], "$name: height check" );
 22+
 23+ # Normalize parameters
 24+ $this->assertTrue( $handler->normaliseParams( $file, $params ) );
 25+ $rotation = $handler->getRotation( $file );
 26+
 27+ # Check if pre-rotation dimensions are still good
 28+ list( $width, $height ) = $handler->extractPreRotationDimensions( $params, $rotation );
 29+ $this->assertEquals( $file->getWidth(), $width,
 30+ "$name: pre-rotation width check, $rotation:$width" );
 31+ $this->assertEquals( $file->getHeight(), $height,
 32+ "$name: pre-rotation height check, $rotation" );
 33+
 34+ # Any further test require a scaler that can rotate
 35+ if ( !BitmapHandler::canRotate() ) {
 36+ $this->markTestIncomplete( 'Scaler does not support rotation' );
 37+ return;
 38+ }
 39+
 40+ # Check post-rotation width
 41+ $this->assertEquals( $params['physicalWidth'], $info['width'],
 42+ "$name: post-rotation width check" );
 43+ $this->assertEquals( $params['physicalHeight'], $info['height'],
 44+ "$name: post-rotation height check" );
2245 }
2346
2447 function providerFiles() {
@@ -40,5 +63,42 @@
4164 )
4265 );
4366 }
 67+
 68+
 69+ const TEST_WIDTH = 100;
 70+ const TEST_HEIGHT = 200;
 71+
 72+ /**
 73+ * @dataProvider provideBitmapExtractPreRotationDimensions
 74+ */
 75+ function testBitmapExtractPreRotationDimensions( $rotation, $expected ) {
 76+ $handler = new BitmapHandler;
 77+ $result = $handler->extractPreRotationDimensions( array(
 78+ 'physicalWidth' => self::TEST_WIDTH,
 79+ 'physicalHeight' => self::TEST_HEIGHT,
 80+ ), $rotation );
 81+ $this->assertEquals( $expected, $result );
 82+ }
 83+
 84+ function provideBitmapExtractPreRotationDimensions() {
 85+ return array(
 86+ array(
 87+ 0,
 88+ array( self::TEST_WIDTH, self::TEST_HEIGHT )
 89+ ),
 90+ array(
 91+ 90,
 92+ array( self::TEST_HEIGHT, self::TEST_WIDTH )
 93+ ),
 94+ array(
 95+ 180,
 96+ array( self::TEST_WIDTH, self::TEST_HEIGHT )
 97+ ),
 98+ array(
 99+ 270,
 100+ array( self::TEST_HEIGHT, self::TEST_WIDTH )
 101+ ),
 102+ );
 103+ }
44104 }
45105
Index: trunk/phase3/includes/media/Bitmap.php
@@ -28,11 +28,13 @@
2929 $srcWidth = $image->getWidth( $params['page'] );
3030 $srcHeight = $image->getHeight( $params['page'] );
3131
 32+ $swapDimensions = false;
3233 if ( self::canRotate() ) {
3334 $rotation = $this->getRotation( $image );
3435 if ( $rotation == 90 || $rotation == 270 ) {
3536 wfDebug( __METHOD__ . ": Swapping width and height because the file will be rotated $rotation degrees\n" );
3637
 38+ $swapDimensions = true;
3739 $width = $params['width'];
3840 $params['width'] = $params['height'];
3941 $params['height'] = $width;
@@ -44,8 +46,13 @@
4547 $params['physicalHeight'] = $params['height'];
4648
4749 if ( $params['physicalWidth'] >= $srcWidth ) {
48 - $params['physicalWidth'] = $srcWidth;
49 - $params['physicalHeight'] = $srcHeight;
 50+ if ( $swapDimensions ) {
 51+ $params['physicalWidth'] = $srcHeight;
 52+ $params['physicalHeight'] = $srcWidth;
 53+ } else {
 54+ $params['physicalWidth'] = $srcWidth;
 55+ $params['physicalHeight'] = $srcHeight;
 56+ }
5057 # Skip scaling limit checks if no scaling is required
5158 if ( !$image->mustRender() )
5259 return true;
@@ -63,6 +70,25 @@
6471
6572 return true;
6673 }
 74+
 75+ /**
 76+ * Extracts the width/height if the image will be scaled before rotating
 77+ *
 78+ * @param $params array Parameters as returned by normaliseParams
 79+ * @param $rotation int The rotation angle that will be applied
 80+ * @return array ($width, $height) array
 81+ */
 82+ public function extractPreRotationDimensions( $params, $rotation ) {
 83+ if ( $rotation == 90 || $rotation == 270 ) {
 84+ # We'll resize before rotation, so swap the dimensions again
 85+ $width = $params['physicalHeight'];
 86+ $height = $params['physicalWidth'];
 87+ } else {
 88+ $width = $params['physicalWidth'];
 89+ $height = $params['physicalHeight'];
 90+ }
 91+ return array( $width, $height );
 92+ }
6793
6894
6995 // Function that returns the number of pixels to be thumbnailed.
@@ -287,6 +313,9 @@
288314 if ( strval( $wgImageMagickTempDir ) !== '' ) {
289315 $env['MAGICK_TMPDIR'] = $wgImageMagickTempDir;
290316 }
 317+
 318+ $rotation = $this->getRotation( $image );
 319+ list( $width, $height ) = $this->extractPreRotationDimensions( $params, $rotation );
291320
292321 $cmd =
293322 wfEscapeShellArg( $wgImageMagickConvertCommand ) .
@@ -299,7 +328,7 @@
300329 // For the -thumbnail option a "!" is needed to force exact size,
301330 // or ImageMagick may decide your ratio is wrong and slice off
302331 // a pixel.
303 - " -thumbnail " . wfEscapeShellArg( "{$params['physicalDimensions']}!" ) .
 332+ " -thumbnail " . wfEscapeShellArg( "{$width}x{$height}!" ) .
304333 // Add the source url as a comment to the thumb, but don't add the flag if there's no comment
305334 ( $params['comment'] !== ''
306335 ? " -set comment " . wfEscapeShellArg( $this->escapeMagickProperty( $params['comment'] ) )
@@ -362,14 +391,7 @@
363392 }
364393
365394 $rotation = $this->getRotation( $image );
366 - if ( $rotation == 90 || $rotation == 270 ) {
367 - // We'll resize before rotation, so swap the dimensions again
368 - $width = $params['physicalHeight'];
369 - $height = $params['physicalWidth'];
370 - } else {
371 - $width = $params['physicalWidth'];
372 - $height = $params['physicalHeight'];
373 - }
 395+ list( $width, $height ) = $this->extractPreRotationDimensions( $params, $rotation );
374396
375397 $im->setImageBackgroundColor( new ImagickPixel( 'white' ) );
376398
@@ -509,14 +531,7 @@
510532 $src_image = call_user_func( $loader, $params['srcPath'] );
511533
512534 $rotation = function_exists( 'imagerotate' ) ? $this->getRotation( $image ) : 0;
513 - if ( $rotation == 90 || $rotation == 270 ) {
514 - # We'll resize before rotation, so swap the dimensions again
515 - $width = $params['physicalHeight'];
516 - $height = $params['physicalWidth'];
517 - } else {
518 - $width = $params['physicalWidth'];
519 - $height = $params['physicalHeight'];
520 - }
 535+ list( $width, $height ) = $this->extractPreRotationDimensions( $params, $rotation );
521536 $dst_image = imagecreatetruecolor( $width, $height );
522537
523538 // Initialise the destination image to transparent instead of

Follow-up revisions

RevisionCommit summaryAuthorDate
r97651Partial revert of broken test changes from r92246 -- for some reason it was t...brion19:13, 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
r79845$wgMaxUploadSize may now be set to an array to specify the upload size limit ...btongminh22:12, 7 January 2011

Comments

#Comment by Hashar (talk | contribs)   10:25, 2 September 2011

untagging 1.18. Revision got included by the 1.18 rebranching.

#Comment by Bawolff (talk | contribs)   19:34, 9 September 2011

Personally I find it slightly weird to have a function that switches the width and height if rotating, only to switch it right back when we actually do the rotation. Although I guess having physicalWidth mean the width before rotating, and width be post-rotation width would be even worse.

#Comment by Brion VIBBER (talk | contribs)   20:39, 9 September 2011

The thing to remember is that conceptually, the "real" size/orientation of the image is what you get after applying the EXIF orientation rotations or flips on the raw file -- from a user's perspective, you simply have (say) a portrait image, not a rotated landscape image.

So the only time we actually want to be dealing with raw pre-rotation width/height is when we need to pass that & the rotation information to something that does low-level image manipulation, because that's what it needs access to in order to produce correct output.

#Comment by Bawolff (talk | contribs)   21:10, 9 September 2011

However, as it stands, if portrait-rotated.jpg is an image needing rotation, [[File:portrait-rotated.jpg|200px]] results in a final image that has a width of 150px and a height of 200px, which is kind of unexpected.

#Comment by Brion VIBBER (talk | contribs)   18:27, 20 September 2011

We still have breakages -- many things are reporting original unrotated size, and a number of things are turning out images sized to the wrong bounding box. Bug 31024 lists a number of nasty bits, including an inconsistency between things resized internally and those done through thumb.php!

#Comment by Brion VIBBER (talk | contribs)   19:14, 20 September 2011

Test changes look wrong -- for some reason it's comparing $file->getWidth() and $file->getHeight() against "pre-rotation dimensions" -- it should compare them against logical dimensions (eg, post-rotation). So for the portrait image we should see 768x1024.

I've restored the testMetadata test to its original form, checking the returned getWidth/getHeight against the expected logical values, in r97651 -- which it clearly fails.

#Comment by Brion VIBBER (talk | contribs)   22:42, 20 September 2011

All happy as of r97671.

Status & tagging log