From: Bryan Tong Minh Date: Sat, 30 Oct 2010 19:11:30 +0000 (+0000) Subject: Follow-up r75702: stylize X-Git-Tag: 1.31.0-rc.0~34201 X-Git-Url: http://git.cyclocoop.org/%28?a=commitdiff_plain;h=46b5bdfa2cba4c82ddad8ffeb611c0b93497fdc4;p=lhc%2Fweb%2Fwiklou.git Follow-up r75702: stylize --- diff --git a/includes/media/Bitmap.php b/includes/media/Bitmap.php index fab5367156..51358d8d46 100644 --- a/includes/media/Bitmap.php +++ b/includes/media/Bitmap.php @@ -30,7 +30,7 @@ class BitmapHandler extends ImageHandler { $params['physicalWidth'] = $srcWidth; $params['physicalHeight'] = $srcHeight; # Skip scaling limit checks if no scaling is required - if( !$image->mustRender() ) + if ( !$image->mustRender() ) return true; } @@ -46,8 +46,8 @@ class BitmapHandler extends ImageHandler { return true; } - - + + // Function that returns the number of pixels to be thumbnailed. // Intended for animated GIFs to multiply by the number of frames. function getImageArea( $image, $width, $height ) { @@ -71,7 +71,7 @@ class BitmapHandler extends ImageHandler { 'clientWidth' => $params['width'], 'clientHeight' => $params['height'], # Comment as will be added to the EXIF of the thumbnail - 'comment' => isset( $params['descriptionUrl'] ) ? + 'comment' => isset( $params['descriptionUrl'] ) ? "File source: {$params['descriptionUrl']}" : '', # Properties of the original image 'srcWidth' => $image->getWidth(), @@ -83,10 +83,10 @@ class BitmapHandler extends ImageHandler { wfDebug( __METHOD__ . ": creating {$scalerParams['physicalSize']} thumbnail at $dstPath\n" ); - if ( !$image->mustRender() && + if ( !$image->mustRender() && $scalerParams['physicalWidth'] == $scalerParams['srcWidth'] && $scalerParams['physicalHeight'] == $scalerParams['srcHeight'] ) { - + # normaliseParams (or the user) wants us to return the unscaled image wfDebug( __METHOD__ . ": returning unscaled image\n" ); return $this->getClientScalingThumbnailImage( $image, $scalerParams ); @@ -96,7 +96,7 @@ class BitmapHandler extends ImageHandler { if ( !$dstPath ) { # No output path available, client side scaling only $scaler = 'client'; - } elseif( !$wgUseImageResize ) { + } elseif ( !$wgUseImageResize ) { $scaler = 'client'; } elseif ( $wgUseImageMagick ) { $scaler = 'im'; @@ -117,13 +117,13 @@ class BitmapHandler extends ImageHandler { if ( $flags & self::TRANSFORM_LATER ) { wfDebug( __METHOD__ . ": Transforming later per flags.\n" ); - return new ThumbnailImage( $image, $dstUrl, $scalerParams['clientWidth'], + return new ThumbnailImage( $image, $dstUrl, $scalerParams['clientWidth'], $scalerParams['clientHeight'], $dstPath ); } # Try to make a target path for the thumbnail if ( !wfMkdirParents( dirname( $dstPath ) ) ) { - wfDebug( __METHOD__.": Unable to create thumbnail destination directory, falling back to client scaling\n" ); + wfDebug( __METHOD__ . ": Unable to create thumbnail destination directory, falling back to client scaling\n" ); return $this->getClientScalingThumbnailImage( $image, $scalerParams ); } @@ -139,7 +139,7 @@ class BitmapHandler extends ImageHandler { $err = $this->transformGd( $image, $scalerParams ); break; } - + # Remove the file if a zero-byte thumbnail was created, or if there was an error $removed = $this->removeBadFile( $dstPath, (bool)$err ); if ( $err ) { @@ -147,152 +147,152 @@ class BitmapHandler extends ImageHandler { return $err; } elseif ( $removed ) { # Thumbnail was zero-byte and had to be removed - return new MediaTransformError( 'thumbnail_error', + return new MediaTransformError( 'thumbnail_error', $scalerParams['clientWidth'], $scalerParams['clientHeight'] ); } else { - return new ThumbnailImage( $image, $dstUrl, $scalerParams['clientWidth'], + return new ThumbnailImage( $image, $dstUrl, $scalerParams['clientWidth'], $scalerParams['clientHeight'], $dstPath ); } } - + /** * Get a ThumbnailImage that respresents an image that will be scaled * client side - * + * * @param $image File File associated with this thumbnail * @param $params array Array with scaler params * @return ThumbnailImage */ protected function getClientScalingThumbnailImage( $image, $params ) { - return new ThumbnailImage( $image, $image->getURL(), + return new ThumbnailImage( $image, $image->getURL(), $params['clientWidth'], $params['clientHeight'], $params['srcPath'] ); } /** * Transform an image using ImageMagick - * + * * @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 transformImageMagick( $image, $params ) { - # use ImageMagick - global $wgSharpenReductionThreshold, $wgSharpenParameter, - $wgMaxAnimatedGifArea, - $wgImageMagickTempDir, $wgImageMagickConvertCommand; - - $quality = ''; - $sharpen = ''; - $scene = false; - $animation_pre = ''; - $animation_post = ''; - $decoderHint = ''; - if ( $params['mimeType'] == 'image/jpeg' ) { - $quality = "-quality 80"; // 80% - # Sharpening, see bug 6193 - if ( ( $params['physicalWidth'] + $params['physicalHeight'] ) - / ( $params['srcWidth'] + $params['srcHeight'] ) - < $wgSharpenReductionThreshold ) { - $sharpen = "-sharpen " . wfEscapeShellArg( $wgSharpenParameter ); - } - // JPEG decoder hint to reduce memory, available since IM 6.5.6-2 - $decoderHint = "-define jpeg:size={$params['physicalSize']}"; - - } elseif ( $params['mimeType'] == 'image/png' ) { - $quality = "-quality 95"; // zlib 9, adaptive filtering - - } 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 - $scene = 0; - - } elseif( $this->isAnimatedImage( $image ) ) { - // Coalesce is needed to scale animated GIFs properly (bug 1017). - $animation_pre = '-coalesce'; - // We optimize the output, but -optimize is broken, - // use optimizeTransparency instead (bug 11822) - if( version_compare( $this->getMagickVersion(), "6.3.5" ) >= 0 ) { - $animation_post = '-fuzz 5% -layers optimizeTransparency +map'; - } + # use ImageMagick + global $wgSharpenReductionThreshold, $wgSharpenParameter, + $wgMaxAnimatedGifArea, + $wgImageMagickTempDir, $wgImageMagickConvertCommand; + + $quality = ''; + $sharpen = ''; + $scene = false; + $animation_pre = ''; + $animation_post = ''; + $decoderHint = ''; + if ( $params['mimeType'] == 'image/jpeg' ) { + $quality = "-quality 80"; // 80% + # Sharpening, see bug 6193 + if ( ( $params['physicalWidth'] + $params['physicalHeight'] ) + / ( $params['srcWidth'] + $params['srcHeight'] ) + < $wgSharpenReductionThreshold ) { + $sharpen = "-sharpen " . wfEscapeShellArg( $wgSharpenParameter ); + } + // JPEG decoder hint to reduce memory, available since IM 6.5.6-2 + $decoderHint = "-define jpeg:size={$params['physicalSize']}"; + + } elseif ( $params['mimeType'] == 'image/png' ) { + $quality = "-quality 95"; // zlib 9, adaptive filtering + + } 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 + $scene = 0; + + } elseif ( $this->isAnimatedImage( $image ) ) { + // Coalesce is needed to scale animated GIFs properly (bug 1017). + $animation_pre = '-coalesce'; + // We optimize the output, but -optimize is broken, + // use optimizeTransparency instead (bug 11822) + if ( version_compare( $this->getMagickVersion(), "6.3.5" ) >= 0 ) { + $animation_post = '-fuzz 5% -layers optimizeTransparency +map'; } } + } - // Use one thread only, to avoid deadlock bugs on OOM - $env = array( 'OMP_NUM_THREADS' => 1 ); - if ( strval( $wgImageMagickTempDir ) !== '' ) { - $env['MAGICK_TMPDIR'] = $wgImageMagickTempDir; - } + // Use one thread only, to avoid deadlock bugs on OOM + $env = array( 'OMP_NUM_THREADS' => 1 ); + if ( strval( $wgImageMagickTempDir ) !== '' ) { + $env['MAGICK_TMPDIR'] = $wgImageMagickTempDir; + } - $cmd = - wfEscapeShellArg( $wgImageMagickConvertCommand ) . - // Specify white background color, will be used for transparent images - // in Internet Explorer/Windows instead of default black. - " {$quality} -background white". - " {$decoderHint} " . - wfEscapeShellArg( $this->escapeMagickInput( $params['srcPath'], $scene ) ) . - " {$animation_pre}" . - // For the -thumbnail option a "!" is needed to force exact size, - // or ImageMagick may decide your ratio is wrong and slice off - // a pixel. - " -thumbnail " . wfEscapeShellArg( "{$params['physicalSize']}!" ) . - // Add the source url as a comment to the thumb. - " -set comment " . wfEscapeShellArg( $this->escapeMagickProperty( $params['comment'] ) ) . - " -depth 8 $sharpen" . - " {$animation_post} " . - wfEscapeShellArg( $this->escapeMagickOutput( $params['dstPath'] ) ) . " 2>&1"; - - wfDebug( __METHOD__.": running ImageMagick: $cmd\n" ); - wfProfileIn( 'convert' ); - $retval = 0; - $err = wfShellExec( $cmd, $retval, $env ); - wfProfileOut( 'convert' ); - - if ( $retval !== 0 ) { - $this->logErrorForExternalProcess( $retval, $err, $cmd ); - return $this->getMediaTransformError( $params, $err ); - } - - return false; # No error + $cmd = + wfEscapeShellArg( $wgImageMagickConvertCommand ) . + // Specify white background color, will be used for transparent images + // in Internet Explorer/Windows instead of default black. + " {$quality} -background white" . + " {$decoderHint} " . + wfEscapeShellArg( $this->escapeMagickInput( $params['srcPath'], $scene ) ) . + " {$animation_pre}" . + // For the -thumbnail option a "!" is needed to force exact size, + // or ImageMagick may decide your ratio is wrong and slice off + // a pixel. + " -thumbnail " . wfEscapeShellArg( "{$params['physicalSize']}!" ) . + // Add the source url as a comment to the thumb. + " -set comment " . wfEscapeShellArg( $this->escapeMagickProperty( $params['comment'] ) ) . + " -depth 8 $sharpen" . + " {$animation_post} " . + wfEscapeShellArg( $this->escapeMagickOutput( $params['dstPath'] ) ) . " 2>&1"; + + wfDebug( __METHOD__ . ": running ImageMagick: $cmd\n" ); + wfProfileIn( 'convert' ); + $retval = 0; + $err = wfShellExec( $cmd, $retval, $env ); + wfProfileOut( 'convert' ); + + if ( $retval !== 0 ) { + $this->logErrorForExternalProcess( $retval, $err, $cmd ); + return $this->getMediaTransformError( $params, $err ); + } + + return false; # No error } - + /** * Transform an image using a custom command - * + * * @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 transformCustom( $image, $params ) { - # Use a custom convert command - global $wgCustomConvertCommand; - - # Variables: %s %d %w %h - $src = wfEscapeShellArg( $params['srcPath'] ); - $dst = wfEscapeShellArg( $params['dstPath'] ); - $cmd = $wgCustomConvertCommand; - $cmd = str_replace( '%s', $src, str_replace( '%d', $dst, $cmd ) ); # Filenames - $cmd = str_replace( '%h', $params['physicalHeight'], - str_replace( '%w', $params['physicalWidth'], $cmd ) ); # Size - wfDebug( __METHOD__.": Running custom convert command $cmd\n" ); - wfProfileIn( 'convert' ); - $retval = 0; - $err = wfShellExec( $cmd, $retval ); - wfProfileOut( 'convert' ); - - if ( $retval !== 0 ) { - $this->logErrorForExternalProcess( $retval, $err, $cmd ); - return $this->getMediaTransformError( $params, $err ); - } - return false; # No error + # Use a custom convert command + global $wgCustomConvertCommand; + + # Variables: %s %d %w %h + $src = wfEscapeShellArg( $params['srcPath'] ); + $dst = wfEscapeShellArg( $params['dstPath'] ); + $cmd = $wgCustomConvertCommand; + $cmd = str_replace( '%s', $src, str_replace( '%d', $dst, $cmd ) ); # Filenames + $cmd = str_replace( '%h', $params['physicalHeight'], + str_replace( '%w', $params['physicalWidth'], $cmd ) ); # Size + wfDebug( __METHOD__ . ": Running custom convert command $cmd\n" ); + wfProfileIn( 'convert' ); + $retval = 0; + $err = wfShellExec( $cmd, $retval ); + wfProfileOut( 'convert' ); + + if ( $retval !== 0 ) { + $this->logErrorForExternalProcess( $retval, $err, $cmd ); + return $this->getMediaTransformError( $params, $err ); + } + return false; # No error } - + /** * Log an error that occured in an external process - * + * * @param $retval int * @param $err int * @param $cmd string @@ -303,87 +303,87 @@ class BitmapHandler extends ImageHandler { wfHostname(), $retval, trim( $err ), $cmd ) ); } /** - * + * */ protected function getMediaTransformError( $params, $errMsg ) { - return new MediaTransformError( 'thumbnail_error', $params['clientWidth'], + return new MediaTransformError( 'thumbnail_error', $params['clientWidth'], $params['clientHeight'], $errMsg ); } - + /** * Transform an image using the built in GD library - * + * * @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 transformGd( $image, $params ) { - # Use PHP's builtin GD library functions. - # - # First find out what kind of file this is, and select the correct - # input routine for this. - - $typemap = array( - 'image/gif' => array( 'imagecreatefromgif', 'palette', 'imagegif' ), - 'image/jpeg' => array( 'imagecreatefromjpeg', 'truecolor', array( __CLASS__, 'imageJpegWrapper' ) ), - 'image/png' => array( 'imagecreatefrompng', 'bits', 'imagepng' ), - 'image/vnd.wap.wbmp' => array( 'imagecreatefromwbmp', 'palette', 'imagewbmp' ), - 'image/xbm' => array( 'imagecreatefromxbm', 'palette', 'imagexbm' ), - ); - if( !isset( $typemap[$params['mimeType']] ) ) { - $err = 'Image type not supported'; - wfDebug( "$err\n" ); - $errMsg = wfMsg ( 'thumbnail_image-type' ); - return $this->getMediaTransformError( $params, $errMsg ); - } - list( $loader, $colorStyle, $saveType ) = $typemap[$params['mimeType']]; + # Use PHP's builtin GD library functions. + # + # First find out what kind of file this is, and select the correct + # input routine for this. + + $typemap = array( + 'image/gif' => array( 'imagecreatefromgif', 'palette', 'imagegif' ), + 'image/jpeg' => array( 'imagecreatefromjpeg', 'truecolor', array( __CLASS__, 'imageJpegWrapper' ) ), + 'image/png' => array( 'imagecreatefrompng', 'bits', 'imagepng' ), + 'image/vnd.wap.wbmp' => array( 'imagecreatefromwbmp', 'palette', 'imagewbmp' ), + 'image/xbm' => array( 'imagecreatefromxbm', 'palette', 'imagexbm' ), + ); + if ( !isset( $typemap[$params['mimeType']] ) ) { + $err = 'Image type not supported'; + wfDebug( "$err\n" ); + $errMsg = wfMsg ( 'thumbnail_image-type' ); + return $this->getMediaTransformError( $params, $errMsg ); + } + list( $loader, $colorStyle, $saveType ) = $typemap[$params['mimeType']]; - if( !function_exists( $loader ) ) { - $err = "Incomplete GD library configuration: missing function $loader"; - wfDebug( "$err\n" ); - $errMsg = wfMsg ( 'thumbnail_gd-library', $loader ); - return $this->getMediaTransformError( $params, $errMsg ); - } + if ( !function_exists( $loader ) ) { + $err = "Incomplete GD library configuration: missing function $loader"; + wfDebug( "$err\n" ); + $errMsg = wfMsg ( 'thumbnail_gd-library', $loader ); + return $this->getMediaTransformError( $params, $errMsg ); + } - if ( !file_exists( $params['srcPath'] ) ) { - $err = "File seems to be missing: {$params['srcPath']}"; - wfDebug( "$err\n" ); - $errMsg = wfMsg ( 'thumbnail_image-missing', $params['srcPath'] ); - return $this->getMediaTransformError( $params, $errMsg ); - } + if ( !file_exists( $params['srcPath'] ) ) { + $err = "File seems to be missing: {$params['srcPath']}"; + wfDebug( "$err\n" ); + $errMsg = wfMsg ( 'thumbnail_image-missing', $params['srcPath'] ); + return $this->getMediaTransformError( $params, $errMsg ); + } - $src_image = call_user_func( $loader, $params['srcPath'] ); - $dst_image = imagecreatetruecolor( $params['physicalWidth'], - $params['physicalHeight'] ); - - // Initialise the destination image to transparent instead of - // the default solid black, to support PNG and GIF transparency nicely - $background = imagecolorallocate( $dst_image, 0, 0, 0 ); - imagecolortransparent( $dst_image, $background ); - imagealphablending( $dst_image, false ); - - if ( $colorStyle == 'palette' ) { - // Don't resample for paletted GIF images. - // It may just uglify them, and completely breaks transparency. - imagecopyresized( $dst_image, $src_image, - 0,0,0,0, - $params['physicalWidth'], $params['physicalHeight'], - imagesx( $src_image ), imagesy( $src_image ) ); - } else { - imagecopyresampled( $dst_image, $src_image, - 0,0,0,0, - $params['physicalWidth'], $params['physicalHeight'], - imagesx( $src_image ), imagesy( $src_image ) ); - } + $src_image = call_user_func( $loader, $params['srcPath'] ); + $dst_image = imagecreatetruecolor( $params['physicalWidth'], + $params['physicalHeight'] ); + + // Initialise the destination image to transparent instead of + // the default solid black, to support PNG and GIF transparency nicely + $background = imagecolorallocate( $dst_image, 0, 0, 0 ); + imagecolortransparent( $dst_image, $background ); + imagealphablending( $dst_image, false ); + + if ( $colorStyle == 'palette' ) { + // Don't resample for paletted GIF images. + // It may just uglify them, and completely breaks transparency. + imagecopyresized( $dst_image, $src_image, + 0, 0, 0, 0, + $params['physicalWidth'], $params['physicalHeight'], + imagesx( $src_image ), imagesy( $src_image ) ); + } else { + imagecopyresampled( $dst_image, $src_image, + 0, 0, 0, 0, + $params['physicalWidth'], $params['physicalHeight'], + imagesx( $src_image ), imagesy( $src_image ) ); + } + + imagesavealpha( $dst_image, true ); - imagesavealpha( $dst_image, true ); + call_user_func( $saveType, $dst_image, $params['dstPath'] ); + imagedestroy( $dst_image ); + imagedestroy( $src_image ); - call_user_func( $saveType, $dst_image, $params['dstPath'] ); - imagedestroy( $dst_image ); - imagedestroy( $src_image ); - - return false; # No error + return false; # No error } /** @@ -403,14 +403,14 @@ class BitmapHandler extends ImageHandler { } /** - * Escape a string for ImageMagick's input filenames. See ExpandFilenames() + * Escape a string for ImageMagick's input filenames. See ExpandFilenames() * and GetPathComponent() in magick/utility.c. * * This won't work with an initial ~ or @, so input files should be prefixed - * with the directory name. + * with the directory name. * * Glob character unescaping is broken in ImageMagick before 6.6.1-5, but - * it's broken in a way that doesn't involve trying to convert every file + * it's broken in a way that doesn't involve trying to convert every file * in a directory, so we're better off escaping and waiting for the bugfix * to filter down to users. * @@ -421,7 +421,7 @@ class BitmapHandler extends ImageHandler { # Die on initial metacharacters (caller should prepend path) $firstChar = substr( $path, 0, 1 ); if ( $firstChar === '~' || $firstChar === '@' ) { - throw new MWException( __METHOD__.': cannot escape this path name' ); + throw new MWException( __METHOD__ . ': cannot escape this path name' ); } # Escape glob chars @@ -431,7 +431,7 @@ class BitmapHandler extends ImageHandler { } /** - * Escape a string for ImageMagick's output filename. See + * Escape a string for ImageMagick's output filename. See * InterpretImageFilename() in magick/image.c. */ function escapeMagickOutput( $path, $scene = false ) { @@ -440,7 +440,7 @@ class BitmapHandler extends ImageHandler { } /** - * Armour a string against ImageMagick's GetPathComponent(). This is a + * Armour a string against ImageMagick's GetPathComponent(). This is a * helper function for escapeMagickInput() and escapeMagickOutput(). * * @param $path string The file path @@ -454,11 +454,11 @@ class BitmapHandler extends ImageHandler { // OK, it's a drive letter // ImageMagick has a similar exception, see IsMagickConflict() } else { - throw new MWException( __METHOD__.': unexpected colon character in path name' ); + throw new MWException( __METHOD__ . ': unexpected colon character in path name' ); } } - # If there are square brackets, add a do-nothing scene specification + # If there are square brackets, add a do-nothing scene specification # to force a literal interpretation if ( $scene === false ) { if ( strpos( $path, '[' ) !== false ) { @@ -480,15 +480,15 @@ class BitmapHandler extends ImageHandler { global $wgMemc; $cache = $wgMemc->get( "imagemagick-version" ); - if( !$cache ) { + if ( !$cache ) { global $wgImageMagickConvertCommand; $cmd = wfEscapeShellArg( $wgImageMagickConvertCommand ) . ' -version'; - wfDebug( __METHOD__.": Running convert -version\n" ); + wfDebug( __METHOD__ . ": Running convert -version\n" ); $retval = ''; $return = wfShellExec( $cmd, $retval ); - $x = preg_match('/Version: ImageMagick ([0-9]*\.[0-9]*\.[0-9]*)/', $return, $matches); - if( $x != 1 ) { - wfDebug( __METHOD__.": ImageMagick version check failed\n" ); + $x = preg_match( '/Version: ImageMagick ([0-9]*\.[0-9]*\.[0-9]*)/', $return, $matches ); + if ( $x != 1 ) { + wfDebug( __METHOD__ . ": ImageMagick version check failed\n" ); return null; } $wgMemc->set( "imagemagick-version", $matches[1], 3600 ); @@ -505,7 +505,7 @@ class BitmapHandler extends ImageHandler { function getMetadata( $image, $filename ) { global $wgShowEXIF; - if( $wgShowEXIF && file_exists( $filename ) ) { + if ( $wgShowEXIF && file_exists( $filename ) ) { $exif = new Exif( $filename ); $data = $exif->getFilteredData(); if ( $data ) { @@ -540,7 +540,7 @@ class BitmapHandler extends ImageHandler { $exif['MEDIAWIKI_EXIF_VERSION'] != Exif::version() ) { # Wrong version - wfDebug( __METHOD__.": wrong version\n" ); + wfDebug( __METHOD__ . ": wrong version\n" ); return false; } return true; @@ -556,9 +556,9 @@ class BitmapHandler extends ImageHandler { function visibleMetadataFields() { $fields = array(); $lines = explode( "\n", wfMsgForContent( 'metadata-fields' ) ); - foreach( $lines as $line ) { + foreach ( $lines as $line ) { $matches = array(); - if( preg_match( '/^\\*\s*(.*?)\s*$/', $line, $matches ) ) { + if ( preg_match( '/^\\*\s*(.*?)\s*$/', $line, $matches ) ) { $fields[] = $matches[1]; } }