X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fmedia%2FBitmap.php;h=c86eabdec0ba19fb001f6c5929cb45818e50aa9f;hb=a9007e8baf802f0f57d095e3bb4ad201c98c0cb3;hp=4da41c8de418958d1102d6abcbbfb342e4cb4997;hpb=6593f76927558202414e67d4ee1435c96baea658;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/media/Bitmap.php b/includes/media/Bitmap.php index 4da41c8de4..ac39e6f3d4 100644 --- a/includes/media/Bitmap.php +++ b/includes/media/Bitmap.php @@ -88,7 +88,7 @@ class BitmapHandler extends TransformationalImageHandler { /** * @param File $image - * @param array $params + * @param array &$params * @return bool */ function normaliseParams( $image, &$params ) { @@ -104,18 +104,37 @@ class BitmapHandler extends TransformationalImageHandler { return true; } + /** + * Get ImageMagick subsampling factors for the target JPEG pixel format. + * + * @param string $pixelFormat one of 'yuv444', 'yuv422', 'yuv420' + * @return array of string keys + */ + protected function imageMagickSubsampling( $pixelFormat ) { + switch ( $pixelFormat ) { + case 'yuv444': + return [ '1x1', '1x1', '1x1' ]; + case 'yuv422': + return [ '2x1', '1x1', '1x1' ]; + case 'yuv420': + return [ '2x2', '1x1', '1x1' ]; + default: + throw new MWException( 'Invalid pixel format for JPEG output' ); + } + } + /** * Transform an image using ImageMagick * * @param File $image File associated with this thumbnail * @param array $params Array with scaler params * - * @return MediaTransformError Error object if error occurred, false (=no error) otherwise + * @return MediaTransformError|bool Error object if error occurred, false (=no error) otherwise */ protected function transformImageMagick( $image, $params ) { # use ImageMagick global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea, - $wgImageMagickTempDir, $wgImageMagickConvertCommand; + $wgImageMagickTempDir, $wgImageMagickConvertCommand, $wgJpegPixelFormat; $quality = []; $sharpen = []; @@ -123,6 +142,7 @@ class BitmapHandler extends TransformationalImageHandler { $animation_pre = []; $animation_post = []; $decoderHint = []; + $subsampling = []; if ( $params['mimeType'] == 'image/jpeg' ) { $qualityVal = isset( $params['quality'] ) ? (string)$params['quality'] : null; @@ -130,7 +150,7 @@ class BitmapHandler extends TransformationalImageHandler { if ( $params['interlace'] ) { $animation_post = [ '-interlace', 'JPEG' ]; } - # Sharpening, see bug 6193 + # Sharpening, see T8193 if ( ( $params['physicalWidth'] + $params['physicalHeight'] ) / ( $params['srcWidth'] + $params['srcHeight'] ) < $wgSharpenReductionThreshold @@ -141,6 +161,10 @@ class BitmapHandler extends TransformationalImageHandler { // JPEG decoder hint to reduce memory, available since IM 6.5.6-2 $decoderHint = [ '-define', "jpeg:size={$params['physicalDimensions']}" ]; } + if ( $wgJpegPixelFormat ) { + $factors = $this->imageMagickSubsampling( $wgJpegPixelFormat ); + $subsampling = [ '-sampling-factor', implode( ',', $factors ) ]; + } } elseif ( $params['mimeType'] == 'image/png' ) { $quality = [ '-quality', '95' ]; // zlib 9, adaptive filtering if ( $params['interlace'] ) { @@ -154,10 +178,10 @@ class BitmapHandler extends TransformationalImageHandler { // be a total drag. :P $scene = 0; } elseif ( $this->isAnimatedImage( $image ) ) { - // Coalesce is needed to scale animated GIFs properly (bug 1017). + // Coalesce is needed to scale animated GIFs properly (T3017). $animation_pre = [ '-coalesce' ]; // We optimize the output, but -optimize is broken, - // use optimizeTransparency instead (bug 11822) + // use optimizeTransparency instead (T13822) if ( version_compare( $this->getMagickVersion(), "6.3.5" ) >= 0 ) { $animation_post = [ '-fuzz', '5%', '-layers', 'optimizeTransparency' ]; } @@ -187,7 +211,7 @@ class BitmapHandler extends TransformationalImageHandler { && $xcfMeta['colorType'] === 'greyscale-alpha' && version_compare( $this->getMagickVersion(), "6.8.9-3" ) < 0 ) { - // bug 66323 - Greyscale images not rendered properly. + // T68323 - Greyscale images not rendered properly. // So only take the "red" channel. $channelOnly = [ '-channel', 'R', '-separate' ]; $animation_pre = array_merge( $animation_pre, $channelOnly ); @@ -225,6 +249,7 @@ class BitmapHandler extends TransformationalImageHandler { [ '-depth', 8 ], $sharpen, [ '-rotate', "-$rotation" ], + $subsampling, $animation_post, [ $this->escapeMagickOutput( $params['dstPath'] ) ] ) ); @@ -247,18 +272,18 @@ class BitmapHandler extends TransformationalImageHandler { * @param File $image File associated with this thumbnail * @param array $params Array with scaler params * - * @return MediaTransformError Error object if error occurred, false (=no error) otherwise + * @return MediaTransformError Error|bool object if error occurred, false (=no error) otherwise */ protected function transformImageMagickExt( $image, $params ) { global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea, - $wgMaxInterlacingAreas; + $wgJpegPixelFormat; try { $im = new Imagick(); $im->readImage( $params['srcPath'] ); if ( $params['mimeType'] == 'image/jpeg' ) { - // Sharpening, see bug 6193 + // Sharpening, see T8193 if ( ( $params['physicalWidth'] + $params['physicalHeight'] ) / ( $params['srcWidth'] + $params['srcHeight'] ) < $wgSharpenReductionThreshold @@ -272,6 +297,10 @@ class BitmapHandler extends TransformationalImageHandler { if ( $params['interlace'] ) { $im->setInterlaceScheme( Imagick::INTERLACE_JPEG ); } + if ( $wgJpegPixelFormat ) { + $factors = $this->imageMagickSubsampling( $wgJpegPixelFormat ); + $im->setSamplingFactors( $factors ); + } } elseif ( $params['mimeType'] == 'image/png' ) { $im->setCompressionQuality( 95 ); if ( $params['interlace'] ) { @@ -283,7 +312,7 @@ class BitmapHandler extends TransformationalImageHandler { // be a total drag. :P $im->setImageScene( 0 ); } elseif ( $this->isAnimatedImage( $image ) ) { - // Coalesce is needed to scale animated GIFs properly (bug 1017). + // Coalesce is needed to scale animated GIFs properly (T3017). $im = $im->coalesceImages(); } // GIF interlacing is only available since 6.3.4 @@ -338,7 +367,7 @@ class BitmapHandler extends TransformationalImageHandler { * @param File $image File associated with this thumbnail * @param array $params Array with scaler params * - * @return MediaTransformError Error object if error occurred, false (=no error) otherwise + * @return MediaTransformError Error|bool object if error occurred, false (=no error) otherwise */ protected function transformCustom( $image, $params ) { # Use a custom convert command @@ -370,7 +399,7 @@ class BitmapHandler extends TransformationalImageHandler { * @param File $image File associated with this thumbnail * @param array $params Array with scaler params * - * @return MediaTransformError Error object if error occurred, false (=no error) otherwise + * @return MediaTransformError|bool Error object if error occurred, false (=no error) otherwise */ protected function transformGd( $image, $params ) { # Use PHP's builtin GD library functions. @@ -512,7 +541,7 @@ class BitmapHandler extends TransformationalImageHandler { * @param array $params Rotate parameters. * 'rotation' clockwise rotation in degrees, allowed are multiples of 90 * @since 1.21 - * @return bool + * @return bool|MediaTransformError */ public function rotate( $file, $params ) { global $wgImageMagickConvertCommand;