$wgMaxUploadSize may now be set to an array to specify the upload size limit per...
authorBryan Tong Minh <btongminh@users.mediawiki.org>
Fri, 7 Jan 2011 22:12:05 +0000 (22:12 +0000)
committerBryan Tong Minh <btongminh@users.mediawiki.org>
Fri, 7 Jan 2011 22:12:05 +0000 (22:12 +0000)
Backwards compatible, if not set to an array, applies to all uploads. If set to an array, per upload type maximums can be set, using the file and url keys. If the * key is set this value will be used as maximum for non-specified types.

RELEASE-NOTES
includes/ImagePage.php
includes/media/Bitmap.php

index 8fdc71a..46589e4 100644 (file)
@@ -41,6 +41,8 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * Search suggestions (other than in the Vector skin) will now use the HTML5
   datalist feature where supported, currently only Firefox 4.
 * Special:Contribs now redirects to Special:Contributions
+* (bug 6672) Images are now autorotated according to their EXIF orientation. 
+  This only affects thumbnails; the source remains unrotated.
 
 === Bug fixes in 1.18 ===
 * (bug 23119) WikiError class and subclasses are now marked as deprecated
index 686d3a8..3113818 100644 (file)
@@ -368,10 +368,7 @@ class ImagePage extends Article {
                                $thumbnail = $this->displayImg->transform( $params );
 
                                $showLink = true;
-                               $anchorclose = '';
-                               if ( !$this->displayImg->mustRender() ) {
-                                       $anchorclose = "<br />" . $msgsmall;
-                               }
+                               $anchorclose = "<br />" . $msgsmall;
 
                                $isMulti = $this->displayImg->isMultipage() && $this->displayImg->pageCount() > 1;
                                if ( $isMulti ) {
index f5f7ba6..c9ff9db 100644 (file)
@@ -21,6 +21,17 @@ class BitmapHandler extends ImageHandler {
                $mimeType = $image->getMimeType();
                $srcWidth = $image->getWidth( $params['page'] );
                $srcHeight = $image->getHeight( $params['page'] );
+               
+               if ( $this->canRotate() ) {
+                       $rotation = $this->getRotation( $image );
+                       if ( $rotation == 90 || $rotation == 270 ) {
+                               wfDebug( __METHOD__ . ": Swapping width and height because the file will be rotation $rotation degrees\n" );
+                               
+                               $width = $params['width'];
+                               $params['width'] = $params['height'];
+                               $params['height'] = $width;
+                       }
+               }
 
                # Don't make an image bigger than the source
                $params['physicalWidth'] = $params['width'];
@@ -55,8 +66,7 @@ class BitmapHandler extends ImageHandler {
        }
 
        function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
-               global $wgUseImageMagick;
-               global $wgCustomConvertCommand, $wgUseImageResize;
+               global $wgCustomConvertCommand;
 
                if ( !$this->normaliseParams( $image, $params ) ) {
                        return new TransformParameterError( $params );
@@ -93,20 +103,7 @@ class BitmapHandler extends ImageHandler {
                }
 
                # Determine scaler type
-               if ( !$dstPath ) {
-                       # No output path available, client side scaling only
-                       $scaler = 'client';
-               } elseif ( !$wgUseImageResize ) {
-                       $scaler = 'client';
-               } elseif ( $wgUseImageMagick ) {
-                       $scaler = 'im';
-               } elseif ( $wgCustomConvertCommand ) {
-                       $scaler = 'custom';
-               } elseif ( function_exists( 'imagecreatetruecolor' ) ) {
-                       $scaler = 'gd';
-               } else {
-                       $scaler = 'client';
-               }
+               $scaler = $this->getScalerType( $dstPath );
                wfDebug( __METHOD__ . ": scaler $scaler\n" );
 
                if ( $scaler == 'client' ) {
@@ -154,6 +151,39 @@ class BitmapHandler extends ImageHandler {
                                $scalerParams['clientHeight'], $dstPath );
                }
        }
+       
+       /**
+        * Returns which scaler type should be used. Creates parent directories 
+        * for $dstPath and returns 'client' on error
+        * 
+        * @return string client,im,custom,gd
+        */
+       protected function getScalerType( $dstPath, $checkDstPath = true ) {
+               global $wgUseImageResize, $wgUseImageMagick, $wgCustomConvertCommand;
+               
+               if ( !$dstPath && $checkDstPath ) {
+                       # No output path available, client side scaling only
+                       $scaler = 'client';
+               } elseif ( !$wgUseImageResize ) {
+                       $scaler = 'client';
+               } elseif ( $wgUseImageMagick ) {
+                       $scaler = 'im';
+               } elseif ( $wgCustomConvertCommand ) {
+                       $scaler = 'custom';
+               } elseif ( function_exists( 'imagecreatetruecolor' ) ) {
+                       $scaler = 'gd';
+               } else {
+                       $scaler = 'client';
+               }
+               
+               if ( $scaler != 'client' ) {
+                       if ( !wfMkdirParents( dirname( $dstPath ) ) ) {
+                               # Unable to create a path for the thumbnail
+                               return 'client';
+                       }
+               }
+               return $scaler;
+       }
 
        /**
         * Get a ThumbnailImage that respresents an image that will be scaled
@@ -242,7 +272,7 @@ class BitmapHandler extends ImageHandler {
                        ( $params['comment'] !== ''
                                ? " -set comment " . wfEscapeShellArg( $this->escapeMagickProperty( $params['comment'] ) )
                                : '' ) .
-                       " -depth 8 $sharpen" .
+                       " -depth 8 $sharpen -auto-orient" .
                        " {$animation_post} " .
                        wfEscapeShellArg( $this->escapeMagickOutput( $params['dstPath'] ) ) . " 2>&1";
 
@@ -360,8 +390,16 @@ class BitmapHandler extends ImageHandler {
                }
 
                $src_image = call_user_func( $loader, $params['srcPath'] );
-               $dst_image = imagecreatetruecolor( $params['physicalWidth'],
-                       $params['physicalHeight'] );
+               $rotation = $this->getRotation( $image );
+               if ( $rotation == 90 || $rotation == 270 ) {
+                       # We'll resize before rotation, so swap the dimensions again
+                       $width = $params['physicalHeight'];
+                       $height = $params['physicalWidth'];
+               } else {
+                       $width = $params['physicalWidth'];
+                       $height = $params['physicalHeight'];                    
+               }
+               $dst_image = imagecreatetruecolor( $width, $height );
 
                // Initialise the destination image to transparent instead of
                // the default solid black, to support PNG and GIF transparency nicely
@@ -374,15 +412,21 @@ class BitmapHandler extends ImageHandler {
                        // It may just uglify them, and completely breaks transparency.
                        imagecopyresized( $dst_image, $src_image,
                                0, 0, 0, 0,
-                               $params['physicalWidth'], $params['physicalHeight'],
+                               $width, $height,
                                imagesx( $src_image ), imagesy( $src_image ) );
                } else {
                        imagecopyresampled( $dst_image, $src_image,
                                0, 0, 0, 0,
-                               $params['physicalWidth'], $params['physicalHeight'],
+                               $width, $height,
                                imagesx( $src_image ), imagesy( $src_image ) );
                }
-
+               
+               if ( $rotation % 360 != 0 && $rotation % 90 == 0 ) {
+                       $rot_image = imagerotate( $dst_image, $rotation, 0 );
+                       imagedestroy( $dst_image );
+                       $dst_image = $rot_image;
+               }
+               
                imagesavealpha( $dst_image, true );
 
                call_user_func( $saveType, $dst_image, $params['dstPath'] );
@@ -602,4 +646,34 @@ class BitmapHandler extends ImageHandler {
                }
                return $result;
        }
+       
+       public function getRotation( $file ) {
+               $data = $file->getMetadata();
+               if ( !$data ) {
+                       return 0;
+               }
+               $data = unserialize( $data );
+               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;
+       }
+       public function canRotate() {
+               $scaler = $this->getScalerType( null, false );
+               return $scaler == 'im' || $scaler == 'gd';
+       }
+       
+       public function mustRender( $file ) {
+               return $this->canRotate() && $this->getRotation( $file ) != 0;
+       }
 }