From: Bryan Tong Minh Date: Sat, 12 Mar 2011 19:32:39 +0000 (+0000) Subject: (bug 14706) Added support for the Imagick PHP extension. Based on patch by Leslie... X-Git-Tag: 1.31.0-rc.0~31501 X-Git-Url: http://git.cyclocoop.org/%28?a=commitdiff_plain;h=634594c0398e6587e9c6ba49be29bf7ddfbe6832;p=lhc%2Fweb%2Fwiklou.git (bug 14706) Added support for the Imagick PHP extension. Based on patch by Leslie Hoare. Scaler type is "imext". Rotation is supported. Logic mostly copied from transformImagemagick() and ported to Imagick calls. Resizing animated gifs is broken; it only shows the first frame and I can't find out why it does not work, but otherwise it is fully working. --- diff --git a/CREDITS b/CREDITS index a13c0f4570..463b744a75 100644 --- a/CREDITS +++ b/CREDITS @@ -34,6 +34,7 @@ following names for their contribution to the product. * Jon Harald Søby * Juliano F. Ravasi * Leon Weber +* Leslie Hoare * Marco Schuster * Matěj Grabovský * Matt Johnston diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 15c2083b51..7cd82ef34a 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -102,6 +102,7 @@ PHP if you have not done so prior to upgrading MediaWiki. several wikis. * When $wgAllowMicrodataAttributes is true, all itemtypes are allowed, not just the three that were defined in the original specification. +* (bug 14706) Added support for the Imagick PHP extension. === Bug fixes in 1.18 === * (bug 23119) WikiError class and subclasses are now marked as deprecated diff --git a/includes/media/Bitmap.php b/includes/media/Bitmap.php index cc7b052030..74be0ba05c 100644 --- a/includes/media/Bitmap.php +++ b/includes/media/Bitmap.php @@ -143,6 +143,8 @@ class BitmapHandler extends ImageHandler { case 'custom': $err = $this->transformCustom( $image, $scalerParams ); break; + case 'imext': + $err = $this->transformImageMagickExt( $image, $scalerParams ); case 'gd': default: $err = $this->transformGd( $image, $scalerParams ); @@ -184,6 +186,8 @@ class BitmapHandler extends ImageHandler { $scaler = 'custom'; } elseif ( function_exists( 'imagecreatetruecolor' ) ) { $scaler = 'gd'; + } elseif ( class_exists( 'Imagick' ) ) { + $scaler = 'imext'; } else { $scaler = 'client'; } @@ -209,7 +213,7 @@ class BitmapHandler extends ImageHandler { return new ThumbnailImage( $image, $image->getURL(), $params['clientWidth'], $params['clientHeight'], $params['srcPath'] ); } - + /** * Transform an image using ImageMagick * @@ -301,6 +305,91 @@ class BitmapHandler extends ImageHandler { return false; # No error } + + /** + * Transform an image using the Imagick PHP extension + * + * @param $image File File associated with this thumbnail + * @param $params array Array with scaler params + * + * @return MediaTransformError Error object if error occured, false (=no error) otherwise + */ + protected function transformImageMagickExt( $image, $params ) { + global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea; + + try { + $im = new Imagick(); + $im->readImage( $params['srcPath'] ); + + if ( $params['mimeType'] == 'image/jpeg' ) { + // Sharpening, see bug 6193 + if ( ( $params['physicalWidth'] + $params['physicalHeight'] ) + / ( $params['srcWidth'] + $params['srcHeight'] ) + < $wgSharpenReductionThreshold ) { + // Hack, since $wgSharpenParamater is written specifically for the command line convert + list( $radius, $sigma ) = explode( 'x', $wgSharpenParameter ); + $im->sharpenImage( $radius, $sigma ); + } + $im->setCompressionQuality( 80 ); + } elseif( $params['mimeType'] == 'image/png' ) { + $im->setCompressionQuality( 95 ); + } elseif ( $params['mimeType'] == 'image/gif' ) { + if ( $this->getImageArea( $image, $params['srcWidth'], + $params['srcHeight'] ) > $wgMaxAnimatedGifArea ) { + // Extract initial frame only; we're so big it'll + // be a total drag. :P + $im->setImageScene( 0 ); + } elseif ( $this->isAnimatedImage( $image ) ) { + // Coalesce is needed to scale animated GIFs properly (bug 1017). + $im = $im->coalesceImages(); + } + } + + $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']; + } + + $im->setImageBackgroundColor( new ImagickPixel( 'white' ) ); + + // Call Imagick::thumbnailImage on each frame + foreach ( $im as $i => $frame ) { + if ( !$frame->thumbnailImage( $width, $height, /* fit */ false ) ) { + return $this->getMediaTransformError( $params, "Error scaling frame $i" ); + } + } + $im->setImageDepth( 8 ); + + if ( $rotation ) { + if ( !$im->rotateImage( new ImagickPixel( 'white' ), $rotation ) ) { + return $this->getMediaTransformError( $params, "Error rotating $rotation degrees" ); + } + } + + if ( $this->isAnimatedImage( $image ) ) { + wfDebug( __METHOD__ . ": Writing animated thumbnail\n" ); + // This is broken somehow... can't find out how to fix it + $result = $im->writeImages( $params['dstPath'], true ); + } else { + $result = $im->writeImage( $params['dstPath'] ); + } + if ( !$result ) { + return $this->getMediaTransformError( $params, + "Unable to write thumbnail to {$params['dstPath']}" ); + } + + } catch ( ImagickException $e ) { + return $this->getMediaTransformError( $params, $e->getMessage() ); + } + + return false; + + } /** * Transform an image using a custom command @@ -703,6 +792,9 @@ class BitmapHandler extends ImageHandler { case 'im': # ImageMagick supports autorotation return true; + case 'imext': + # Imagick::rotateImage + return true; case 'gd': # GD's imagerotate function is used to rotate images, but not # all precompiled PHP versions have that function