r79845 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r79844‎ | r79845 | r79846 >
Date:22:12, 7 January 2011
Author:btongminh
Status:resolved (Comments)
Tags:
Comment:
$wgMaxUploadSize may now be set to an array to specify the upload size limit per upload type.

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.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/ImagePage.php (modified) (history)
  • /trunk/phase3/includes/media/Bitmap.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/ImagePage.php
@@ -368,10 +368,7 @@
369369 $thumbnail = $this->displayImg->transform( $params );
370370
371371 $showLink = true;
372 - $anchorclose = '';
373 - if ( !$this->displayImg->mustRender() ) {
374 - $anchorclose = "<br />" . $msgsmall;
375 - }
 372+ $anchorclose = "<br />" . $msgsmall;
376373
377374 $isMulti = $this->displayImg->isMultipage() && $this->displayImg->pageCount() > 1;
378375 if ( $isMulti ) {
Index: trunk/phase3/includes/media/Bitmap.php
@@ -21,6 +21,17 @@
2222 $mimeType = $image->getMimeType();
2323 $srcWidth = $image->getWidth( $params['page'] );
2424 $srcHeight = $image->getHeight( $params['page'] );
 25+
 26+ if ( $this->canRotate() ) {
 27+ $rotation = $this->getRotation( $image );
 28+ if ( $rotation == 90 || $rotation == 270 ) {
 29+ wfDebug( __METHOD__ . ": Swapping width and height because the file will be rotation $rotation degrees\n" );
 30+
 31+ $width = $params['width'];
 32+ $params['width'] = $params['height'];
 33+ $params['height'] = $width;
 34+ }
 35+ }
2536
2637 # Don't make an image bigger than the source
2738 $params['physicalWidth'] = $params['width'];
@@ -55,8 +66,7 @@
5667 }
5768
5869 function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
59 - global $wgUseImageMagick;
60 - global $wgCustomConvertCommand, $wgUseImageResize;
 70+ global $wgCustomConvertCommand;
6171
6272 if ( !$this->normaliseParams( $image, $params ) ) {
6373 return new TransformParameterError( $params );
@@ -93,20 +103,7 @@
94104 }
95105
96106 # Determine scaler type
97 - if ( !$dstPath ) {
98 - # No output path available, client side scaling only
99 - $scaler = 'client';
100 - } elseif ( !$wgUseImageResize ) {
101 - $scaler = 'client';
102 - } elseif ( $wgUseImageMagick ) {
103 - $scaler = 'im';
104 - } elseif ( $wgCustomConvertCommand ) {
105 - $scaler = 'custom';
106 - } elseif ( function_exists( 'imagecreatetruecolor' ) ) {
107 - $scaler = 'gd';
108 - } else {
109 - $scaler = 'client';
110 - }
 107+ $scaler = $this->getScalerType( $dstPath );
111108 wfDebug( __METHOD__ . ": scaler $scaler\n" );
112109
113110 if ( $scaler == 'client' ) {
@@ -154,6 +151,39 @@
155152 $scalerParams['clientHeight'], $dstPath );
156153 }
157154 }
 155+
 156+ /**
 157+ * Returns which scaler type should be used. Creates parent directories
 158+ * for $dstPath and returns 'client' on error
 159+ *
 160+ * @return string client,im,custom,gd
 161+ */
 162+ protected function getScalerType( $dstPath, $checkDstPath = true ) {
 163+ global $wgUseImageResize, $wgUseImageMagick, $wgCustomConvertCommand;
 164+
 165+ if ( !$dstPath && $checkDstPath ) {
 166+ # No output path available, client side scaling only
 167+ $scaler = 'client';
 168+ } elseif ( !$wgUseImageResize ) {
 169+ $scaler = 'client';
 170+ } elseif ( $wgUseImageMagick ) {
 171+ $scaler = 'im';
 172+ } elseif ( $wgCustomConvertCommand ) {
 173+ $scaler = 'custom';
 174+ } elseif ( function_exists( 'imagecreatetruecolor' ) ) {
 175+ $scaler = 'gd';
 176+ } else {
 177+ $scaler = 'client';
 178+ }
 179+
 180+ if ( $scaler != 'client' ) {
 181+ if ( !wfMkdirParents( dirname( $dstPath ) ) ) {
 182+ # Unable to create a path for the thumbnail
 183+ return 'client';
 184+ }
 185+ }
 186+ return $scaler;
 187+ }
158188
159189 /**
160190 * Get a ThumbnailImage that respresents an image that will be scaled
@@ -242,7 +272,7 @@
243273 ( $params['comment'] !== ''
244274 ? " -set comment " . wfEscapeShellArg( $this->escapeMagickProperty( $params['comment'] ) )
245275 : '' ) .
246 - " -depth 8 $sharpen" .
 276+ " -depth 8 $sharpen -auto-orient" .
247277 " {$animation_post} " .
248278 wfEscapeShellArg( $this->escapeMagickOutput( $params['dstPath'] ) ) . " 2>&1";
249279
@@ -360,8 +390,16 @@
361391 }
362392
363393 $src_image = call_user_func( $loader, $params['srcPath'] );
364 - $dst_image = imagecreatetruecolor( $params['physicalWidth'],
365 - $params['physicalHeight'] );
 394+ $rotation = $this->getRotation( $image );
 395+ if ( $rotation == 90 || $rotation == 270 ) {
 396+ # We'll resize before rotation, so swap the dimensions again
 397+ $width = $params['physicalHeight'];
 398+ $height = $params['physicalWidth'];
 399+ } else {
 400+ $width = $params['physicalWidth'];
 401+ $height = $params['physicalHeight'];
 402+ }
 403+ $dst_image = imagecreatetruecolor( $width, $height );
366404
367405 // Initialise the destination image to transparent instead of
368406 // the default solid black, to support PNG and GIF transparency nicely
@@ -374,15 +412,21 @@
375413 // It may just uglify them, and completely breaks transparency.
376414 imagecopyresized( $dst_image, $src_image,
377415 0, 0, 0, 0,
378 - $params['physicalWidth'], $params['physicalHeight'],
 416+ $width, $height,
379417 imagesx( $src_image ), imagesy( $src_image ) );
380418 } else {
381419 imagecopyresampled( $dst_image, $src_image,
382420 0, 0, 0, 0,
383 - $params['physicalWidth'], $params['physicalHeight'],
 421+ $width, $height,
384422 imagesx( $src_image ), imagesy( $src_image ) );
385423 }
386 -
 424+
 425+ if ( $rotation % 360 != 0 && $rotation % 90 == 0 ) {
 426+ $rot_image = imagerotate( $dst_image, $rotation, 0 );
 427+ imagedestroy( $dst_image );
 428+ $dst_image = $rot_image;
 429+ }
 430+
387431 imagesavealpha( $dst_image, true );
388432
389433 call_user_func( $saveType, $dst_image, $params['dstPath'] );
@@ -602,4 +646,34 @@
603647 }
604648 return $result;
605649 }
 650+
 651+ public function getRotation( $file ) {
 652+ $data = $file->getMetadata();
 653+ if ( !$data ) {
 654+ return 0;
 655+ }
 656+ $data = unserialize( $data );
 657+ if ( isset( $data['Orientation'] ) ) {
 658+ # See http://sylvana.net/jpegcrop/exif_orientation.html
 659+ switch ( $data['Orientation'] ) {
 660+ case 8:
 661+ return 90;
 662+ case 3:
 663+ return 180;
 664+ case 6:
 665+ return 270;
 666+ default:
 667+ return 0;
 668+ }
 669+ }
 670+ return 0;
 671+ }
 672+ public function canRotate() {
 673+ $scaler = $this->getScalerType( null, false );
 674+ return $scaler == 'im' || $scaler == 'gd';
 675+ }
 676+
 677+ public function mustRender( $file ) {
 678+ return $this->canRotate() && $this->getRotation( $file ) != 0;
 679+ }
606680 }
Index: trunk/phase3/RELEASE-NOTES
@@ -41,6 +41,8 @@
4242 * Search suggestions (other than in the Vector skin) will now use the HTML5
4343 datalist feature where supported, currently only Firefox 4.
4444 * Special:Contribs now redirects to Special:Contributions
 45+* (bug 6672) Images are now autorotated according to their EXIF orientation.
 46+ This only affects thumbnails; the source remains unrotated.
4547
4648 === Bug fixes in 1.18 ===
4749 * (bug 23119) WikiError class and subclasses are now marked as deprecated

Follow-up revisions

RevisionCommit summaryAuthorDate
r79859Follow-up r79845: add function documentation; only call wfMakeDirsParent if w...btongminh11:49, 8 January 2011
r79867Follow-up r79845: Add rotation support to the upload preview using the <canva...btongminh16:24, 8 January 2011
r80070Follow up r79845. No need to keep $wgCustomConvertCommand there.platonides00:30, 12 January 2011
r90016Start on test cases for bug 6672 (Exif orientation support), follow up to r79......brion22:13, 13 June 2011
r92246Follow-up r79845: Fix rotation. Turns out that we need to pass the pre-rotati...btongminh15:13, 15 July 2011
r97671* (bug 6672, 31024) Fixes for handling of images with an EXIF orientation...brion22:13, 20 September 2011
r97785Removed the redundant wfMkdirParents() call added to BitmapHandler::doTransfo...tstarling03:37, 22 September 2011

Comments

#Comment by Bryan (talk | contribs)   22:14, 7 January 2011

Accidentally clicked "use previous commit summary". The correct summary:

(bug 6672) Images are now autorotated according to their EXIF orientation. Following the Flickr example, this only affects thumbnails, with the source unrotated.

  • Introduced BitmapHandler::canRotate() and BitmapHandler::getRotation() to check if rotation is supported and what the amount of rotation is
  • Factored out scaler determination into BitmapHandler::getScalerType()
  • ImageMagick uses the -auto-orientation option
  • GD uses imagerotate()
  • Unconditionally show the thumb size on the image page, don't know why this wasn't shown for SVGs etc.
#Comment by Brion VIBBER (talk | contribs)   21:39, 13 June 2011

There's some borkage with ImageMagick, noted on bug 6672. Needs test cases.

#Comment by Bryan (talk | contribs)   16:30, 15 July 2011
#Comment by Brion VIBBER (talk | contribs)   18:56, 20 September 2011

Several things appear to be visibly wrong, and still exposed as of current trunk and bug 31024 etc:

  • width & height reported for an image from BitmapHandler are not being normalized to the post-rotation values, and thus get reported on through via $file->getWidth(), $file->getHeight() etc
  • lots and lots of stuff gets confused and sizes things to something other than what you asked for; for instance asking for a portrait image rendered to fit an 800x600 box may give you a 600x800 image instead of 450x600 (and per bug 31024 thumb.php will render the 450x600 after being *asked* for 600x800, when we should have asked for 450x600. aaaaaargh)
#Comment by Brion VIBBER (talk | contribs)   22:43, 20 September 2011

All happy as of r97671.

#Comment by Tim Starling (talk | contribs)   03:33, 22 September 2011

You can't run wfMkdirParents() on $dstPath if TRANSFORM_LATER has been given to doTransform(). The point of TRANSFORM_LATER is to avoid NFS access during page rendering.

Status & tagging log