http://www.mediawiki.org/wiki/Special:Code/MediaWiki/97675

Revision: 97675
Author:   brion
Date:     2011-09-20 22:40:32 +0000 (Tue, 20 Sep 2011)
Log Message:
-----------
MFT r97651, r97656, r97659 updated test cases for bug 6672, 31024
MFT r97671 fix for bug 31024
MFT r97672 fix for bug 31048
these fixes resolve remaining issues on bug 6672.

Modified Paths:
--------------
    branches/REL1_18/phase3/includes/media/Bitmap.php
    branches/REL1_18/phase3/includes/media/ExifBitmap.php
    
branches/REL1_18/phase3/resources/mediawiki.special/mediawiki.special.upload.js
    branches/REL1_18/phase3/tests/phpunit/includes/media/ExifRotationTest.php

Modified: branches/REL1_18/phase3/includes/media/Bitmap.php
===================================================================
--- branches/REL1_18/phase3/includes/media/Bitmap.php   2011-09-20 22:38:24 UTC 
(rev 97674)
+++ branches/REL1_18/phase3/includes/media/Bitmap.php   2011-09-20 22:40:32 UTC 
(rev 97675)
@@ -42,20 +42,6 @@
                                return true;
                        }
                }
-
-
-               if ( self::canRotate() ) {
-                       $rotation = $this->getRotation( $image );
-                       if ( $rotation == 90 || $rotation == 270 ) {
-                               wfDebug( __METHOD__ . ": Swapping width and 
height because the file will be rotated $rotation degrees\n" );
-
-                               list( $params['width'], $params['height'] ) = 
-                                       array(  $params['height'], 
$params['width'] );
-                               list( $params['physicalWidth'], 
$params['physicalHeight'] ) = 
-                                       array( $params['physicalHeight'], 
$params['physicalWidth'] );
-                       }
-               }
-
                
                # Don't thumbnail an image so big that it will fill hard drives 
and send servers into swap
                # JPEG has the handy property of allowing thumbnailing without 
full decompression, so we make
@@ -73,6 +59,11 @@
        /**
         * Extracts the width/height if the image will be scaled before rotating
         * 
+        * This will match the physical size/aspect ratio of the original image
+        * prior to application of the rotation -- so for a portrait image 
that's
+        * stored as raw landscape with 90-degress rotation, the resulting size
+        * will be wider than it is tall.
+        *
         * @param $params array Parameters as returned by normaliseParams
         * @param $rotation int The rotation angle that will be applied
         * @return array ($width, $height) array
@@ -249,6 +240,8 @@
         * @param $image File File associated with this thumbnail
         * @param $params array Array with scaler params
         * @return ThumbnailImage
+        *
+        * @fixme no rotation support
         */
        protected function getClientScalingThumbnailImage( $image, $params ) {
                return new ThumbnailImage( $image, $image->getURL(),
@@ -685,33 +678,21 @@
        }
 
        /**
-        * Try to read out the orientation of the file and return the angle that
-        * the file needs to be rotated to be viewed
+        * On supporting image formats, try to read out the low-level 
orientation
+        * of the file and return the angle that the file needs to be rotated to
+        * be viewed.
         *
+        * This information is only useful when manipulating the original file;
+        * the width and height we normally work with is logical, and will match
+        * any produced output views.
+        *
+        * The base BitmapHandler doesn't understand any metadata formats, so 
this
+        * is left up to child classes to implement.
+        *
         * @param $file File
         * @return int 0, 90, 180 or 270
         */
        public function getRotation( $file ) {
-               $data = $file->getMetadata();
-               if ( !$data ) {
-                       return 0;
-               }
-               wfSuppressWarnings();
-               $data = unserialize( $data );
-               wfRestoreWarnings();
-               if ( isset( $data['Orientation'] ) ) {
-                       # See http://sylvana.net/jpegcrop/exif_orientation.html
-                       switch ( $data['Orientation'] ) {
-                               case 8:
-                                       return 90;
-                               case 3:
-                                       return 180;
-                               case 6:
-                                       return 270;
-                               default:
-                                       return 0;
-                       }
-               }
                return 0;
        }
 

Modified: branches/REL1_18/phase3/includes/media/ExifBitmap.php
===================================================================
--- branches/REL1_18/phase3/includes/media/ExifBitmap.php       2011-09-20 
22:38:24 UTC (rev 97674)
+++ branches/REL1_18/phase3/includes/media/ExifBitmap.php       2011-09-20 
22:40:32 UTC (rev 97675)
@@ -124,5 +124,77 @@
        function getMetadataType( $image ) {
                return 'exif';
        }
+
+       /**
+        * Wrapper for base classes ImageHandler::getImageSize() that checks for
+        * rotation reported from metadata and swaps the sizes to match.
+        *
+        * @param File $image
+        * @param string $path
+        * @return array
+        */
+       function getImageSize( $image, $path ) {
+               $gis = parent::getImageSize( $image, $path );
+               
+               // Don't just call $image->getMetadata(); 
File::getPropsFromPath() calls us with a bogus object.
+               // This may mean we read EXIF data twice on initial upload.
+               $meta = $this->getMetadata( $image, $path );
+               $rotation = $this->getRotationForExif( $meta );
+
+               if ($rotation == 90 || $rotation == 270) {
+                       $width = $gis[0];
+                       $gis[0] = $gis[1];
+                       $gis[1] = $width;
+               }
+               return $gis;
+       }
+
+       /**
+        * On supporting image formats, try to read out the low-level 
orientation
+        * of the file and return the angle that the file needs to be rotated to
+        * be viewed.
+        *
+        * This information is only useful when manipulating the original file;
+        * the width and height we normally work with is logical, and will match
+        * any produced output views.
+        *
+        * @param $file File
+        * @return int 0, 90, 180 or 270
+        */
+       public function getRotation( $file ) {
+               $data = $file->getMetadata();
+               return $this->getRotationForExif( $data );
+       }
+
+       /**
+        * Given a chunk of serialized Exif metadata, return the orientation as
+        * degrees of rotation.
+        *
+        * @param string $data
+        * @return int 0, 90, 180 or 270
+        * @fixme orientation can include flipping as well; see if this is an 
issue!
+        */
+       protected function getRotationForExif( $data ) {
+               if ( !$data ) {
+                       return 0;
+               }
+               wfSuppressWarnings();
+               $data = unserialize( $data );
+               wfRestoreWarnings();
+               if ( isset( $data['Orientation'] ) ) {
+                       # See http://sylvana.net/jpegcrop/exif_orientation.html
+                       switch ( $data['Orientation'] ) {
+                               case 8:
+                                       return 90;
+                               case 3:
+                                       return 180;
+                               case 6:
+                                       return 270;
+                               default:
+                                       return 0;
+                       }
+               }
+               return 0;
+       }
 }
 

Modified: 
branches/REL1_18/phase3/resources/mediawiki.special/mediawiki.special.upload.js
===================================================================
--- 
branches/REL1_18/phase3/resources/mediawiki.special/mediawiki.special.upload.js 
    2011-09-20 22:38:24 UTC (rev 97674)
+++ 
branches/REL1_18/phase3/resources/mediawiki.special/mediawiki.special.upload.js 
    2011-09-20 22:40:32 UTC (rev 97675)
@@ -83,7 +83,7 @@
                        }
                        
                        img.onload = function() {
-                               var width, height, x, y, dx, dy;
+                               var width, height, x, y, dx, dy, logicalWidth, 
logicalHeight;
                                // Fit the image within the 
previewSizexpreviewSize box
                                if ( img.width > img.height ) {
                                        width = previewSize;
@@ -103,19 +103,27 @@
                                        case 0:
                                                x = dx;
                                                y = dy;
+                                               logicalWidth = img.width;
+                                               logicalHeight = img.height;
                                                break;
                                        case 90:
                                                
                                                x = dx;
                                                y = dy - previewSize;
+                                               logicalWidth = img.height;
+                                               logicalHeight = img.width;
                                                break;
                                        case 180:
                                                x = dx - previewSize;
                                                y = dy - previewSize;
+                                               logicalWidth = img.width;
+                                               logicalHeight = img.height;
                                                break;
                                        case 270:
                                                x = dx - previewSize;
                                                y = dy;
+                                               logicalWidth = img.height;
+                                               logicalHeight = img.width;
                                                break;
                                }
                                
@@ -124,7 +132,7 @@
                                ctx.drawImage( img, x, y, width, height );
                                
                                // Image size
-                               var info = mw.msg( 'widthheight', img.width, 
img.height ) +
+                               var info = mw.msg( 'widthheight', logicalWidth, 
logicalHeight ) +
                                        ', ' + prettySize( file.size );
                                $( '#mw-upload-thumbnail .fileinfo' ).text( 
info );
                        };

Modified: 
branches/REL1_18/phase3/tests/phpunit/includes/media/ExifRotationTest.php
===================================================================
--- branches/REL1_18/phase3/tests/phpunit/includes/media/ExifRotationTest.php   
2011-09-20 22:38:24 UTC (rev 97674)
+++ branches/REL1_18/phase3/tests/phpunit/includes/media/ExifRotationTest.php   
2011-09-20 22:40:32 UTC (rev 97675)
@@ -9,41 +9,74 @@
                parent::setUp();
                $this->filePath = dirname( __FILE__ ) . '/../../data/media/';
                $this->handler = new BitmapHandler();
+               $this->repo = new FSRepo(array(
+                       'name' => 'temp',
+                       'directory' => wfTempDir() . '/exif-test-' . time(),
+                       'url' => 'http://localhost/thumbtest'
+               ));
+               if ( !wfDl( 'exif' ) ) {
+                       $this->markTestSkipped( "This test needs the exif 
extension." );
+               }
+               global $wgShowEXIF;
+               $this->show = $wgShowEXIF;
+               $wgShowEXIF = true;
        }
+       public function tearDown() {
+               global $wgShowEXIF;
+               $wgShowEXIF = $this->show;
+       }
 
        /**
         *
         * @dataProvider providerFiles
         */
        function testMetadata( $name, $type, $info ) {
-               # Force client side resizing
-               $params = array( 'width' => 10000, 'height' => 10000 );
                $file = UnregisteredLocalFile::newFromPath( $this->filePath . 
$name, $type );
-               
-               # Normalize parameters
-               $this->assertTrue( $this->handler->normaliseParams( $file, 
$params ) );
-               $rotation = $this->handler->getRotation( $file );
-               
-               # Check if pre-rotation dimensions are still good
-               list( $width, $height ) = 
$this->handler->extractPreRotationDimensions( $params, $rotation );
-               $this->assertEquals( $file->getWidth(), $width, 
-                       "$name: pre-rotation width check, $rotation:$width" );
-               $this->assertEquals( $file->getHeight(), $height, 
-                       "$name: pre-rotation height check, $rotation" );
-               
-               # Any further test require a scaler that can rotate
-               if ( !BitmapHandler::canRotate() ) {
-                       $this->markTestIncomplete( 'Scaler does not support 
rotation' );
-                       return;
+               $this->assertEquals( $info['width'], $file->getWidth(), "$name: 
width check" );
+               $this->assertEquals( $info['height'], $file->getHeight(), 
"$name: height check" );
+       }
+
+       /**
+        *
+        * @dataProvider providerFiles
+        */
+       function testRotationRendering( $name, $type, $info, $thumbs ) {
+               foreach( $thumbs as $size => $out ) {
+                       if( preg_match('/^(\d+)px$/', $size, $matches ) ) {
+                               $params = array(
+                                       'width' => $matches[1],
+                               );
+                       } elseif ( preg_match( '/^(\d+)x(\d+)px$/', $size, 
$matches ) ) {
+                               $params = array(
+                                       'width' => $matches[1],
+                                       'height' => $matches[2]
+                               );
+                       } else {
+                               throw new MWException('bogus test data format ' 
. $size);
+                       }
+
+                       $file = $this->localFile( $name, $type );
+                       $thumb = $file->transform( $params, File::RENDER_NOW );
+
+                       $this->assertEquals( $out[0], $thumb->getWidth(), 
"$name: thumb reported width check for $size" );
+                       $this->assertEquals( $out[1], $thumb->getHeight(), 
"$name: thumb reported height check for $size" );
+
+                       $gis = getimagesize( $thumb->getPath() );
+                       if ($out[0] > $info['width']) {
+                               // Physical image won't be scaled bigger than 
the original.
+                               $this->assertEquals( $info['width'], $gis[0], 
"$name: thumb actual width check for $size");
+                               $this->assertEquals( $info['height'], $gis[1], 
"$name: thumb actual height check for $size");
+                       } else {
+                               $this->assertEquals( $out[0], $gis[0], "$name: 
thumb actual width check for $size");
+                               $this->assertEquals( $out[1], $gis[1], "$name: 
thumb actual height check for $size");
+                       }
                }
-               
-               # Check post-rotation width
-               $this->assertEquals( $params['physicalWidth'], $info['width'], 
-                       "$name: post-rotation width check" );
-               $this->assertEquals( $params['physicalHeight'], 
$info['height'], 
-                       "$name: post-rotation height check" );
        }
 
+       private function localFile( $name, $type ) {
+               return new UnregisteredLocalFile( false, $this->repo, 
$this->filePath . $name, $type );
+       }
+
        function providerFiles() {
                return array(
                        array(
@@ -52,6 +85,12 @@
                                array(
                                        'width' => 1024,
                                        'height' => 768,
+                               ),
+                               array(
+                                       '800x600px' => array( 800, 600 ),
+                                       '9999x800px' => array( 1067, 800 ),
+                                       '800px' => array( 800, 600 ),
+                                       '600px' => array( 600, 450 ),
                                )
                        ),
                        array(
@@ -60,6 +99,12 @@
                                array(
                                        'width' => 768, // as rotated
                                        'height' => 1024, // as rotated
+                               ),
+                               array(
+                                       '800x600px' => array( 450, 600 ),
+                                       '9999x800px' => array( 600, 800 ),
+                                       '800px' => array( 800, 1067 ),
+                                       '600px' => array( 600, 800 ),
                                )
                        )
                );
@@ -100,22 +145,5 @@
                        ),                      
                );
        }
-
-       function testWidthFlipping() {
-               $file = UnregisteredLocalFile::newFromPath( $this->filePath . 
'portrait-rotated.jpg', 'image/jpeg' );
-               $params = array( 'width' => '50' );
-               $this->assertTrue( $this->handler->normaliseParams( $file, 
$params ) );
-
-               $this->assertEquals( 50, $params['height'] );
-               $this->assertEquals( round( (768/1024)*50 ), $params['width'], 
'', 0.1 );
-       }
-       function testWidthNotFlipping() {
-               $file = UnregisteredLocalFile::newFromPath( $this->filePath . 
'landscape-plain.jpg', 'image/jpeg' );
-               $params = array( 'width' => '50' );
-               $this->assertTrue( $this->handler->normaliseParams( $file, 
$params ) );
-
-               $this->assertEquals( 50, $params['width'] );
-               $this->assertEquals( round( (768/1024)*50 ), $params['height'], 
'', 0.1 );
-       }
 }
 


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to