return $scaler;
}
+ function makeParamString( $params ) {
+ $res = parent::makeParamString( $params );
+ if ( isset( $params['interlace'] ) && $params['interlace'] ) {
+ return "interlaced-{$res}";
+ } else {
+ return $res;
+ }
+ }
+
+ function parseParamString( $str ) {
+ $remainder = preg_replace( '/^interlaced-/', '', $str );
+ $params = parent::parseParamString( $remainder );
+ if ( $params === false ) {
+ return false;
+ }
+ $params['interlace'] = $str !== $remainder;
+ return $params;
+ }
+
+ /**
+ * @param File $image
+ * @param array $params
+ * @return bool
+ */
+ function normaliseParams( $image, &$params ) {
+ global $wgMaxInterlacingAreas;
+ if ( !parent::normaliseParams( $image, $params ) ) {
+ return false;
+ }
+ $mimeType = $image->getMimeType();
+ $interlace = isset( $params['interlace'] ) && $params['interlace']
+ && isset( $wgMaxInterlacingAreas[$mimeType] )
+ && $this->getImageArea( $image ) <= $wgMaxInterlacingAreas[$mimeType];
+ $params['interlace'] = $interlace;
+ return true;
+ }
+
/**
* Transform an image using ImageMagick
*
protected function transformImageMagick( $image, $params ) {
# use ImageMagick
global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea,
- $wgImageMagickTempDir, $wgImageMagickConvertCommand;
+ $wgImageMagickTempDir, $wgImageMagickConvertCommand, $wgMaxInterlacingAreas;
$quality = array();
$sharpen = array();
$animation_pre = array();
$animation_post = array();
$decoderHint = array();
+
if ( $params['mimeType'] == 'image/jpeg' ) {
$qualityVal = isset( $params['quality'] ) ? (string)$params['quality'] : null;
$quality = array( '-quality', $qualityVal ?: '80' ); // 80%
+ if ( $params['interlace'] ) {
+ $animation_post = array( '-interlace', 'JPEG' );
+ }
# Sharpening, see bug 6193
if ( ( $params['physicalWidth'] + $params['physicalHeight'] )
/ ( $params['srcWidth'] + $params['srcHeight'] )
// JPEG decoder hint to reduce memory, available since IM 6.5.6-2
$decoderHint = array( '-define', "jpeg:size={$params['physicalDimensions']}" );
}
- } elseif ( $params['mimeType'] == 'image/png' || $params['mimeType'] == 'image/webp' ) {
+ } elseif ( $params['mimeType'] == 'image/png' ) {
+ $quality = array( '-quality', '95' ); // zlib 9, adaptive filtering
+ if ( $params['interlace'] ) {
+ $animation_post = array( '-interlace', 'PNG' );
+ }
+ } elseif ( $params['mimeType'] == 'image/webp' ) {
$quality = array( '-quality', '95' ); // zlib 9, adaptive filtering
} elseif ( $params['mimeType'] == 'image/gif' ) {
if ( $this->getImageArea( $image ) > $wgMaxAnimatedGifArea ) {
$animation_post = array( '-fuzz', '5%', '-layers', 'optimizeTransparency' );
}
}
+ if ( $params['interlace'] && version_compare( $this->getMagickVersion(), "6.3.4" ) >= 0
+ && !$this->isAnimatedImage( $image ) ) { // interlacing animated GIFs is a bad idea
+ $animation_post[] = '-interlace';
+ $animation_post[] = 'GIF';
+ }
} elseif ( $params['mimeType'] == 'image/x-xcf' ) {
// Before merging layers, we need to set the background
// to be transparent to preserve alpha, as -layers merge
( $params['comment'] !== ''
? array( '-set', 'comment', $this->escapeMagickProperty( $params['comment'] ) )
: array() ),
+ // T108616: Avoid exposure of local file path
+ array( '+set', 'Thumb::URI' ),
array( '-depth', 8 ),
$sharpen,
array( '-rotate', "-$rotation" ),
* @return MediaTransformError Error object if error occurred, false (=no error) otherwise
*/
protected function transformImageMagickExt( $image, $params ) {
- global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea;
+ global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea,
+ $wgMaxInterlacingAreas;
try {
$im = new Imagick();
}
$qualityVal = isset( $params['quality'] ) ? (string)$params['quality'] : null;
$im->setCompressionQuality( $qualityVal ?: 80 );
+ if ( $params['interlace'] ) {
+ $im->setInterlaceScheme( Imagick::INTERLACE_JPEG );
+ }
} elseif ( $params['mimeType'] == 'image/png' ) {
$im->setCompressionQuality( 95 );
+ if ( $params['interlace'] ) {
+ $im->setInterlaceScheme( Imagick::INTERLACE_PNG );
+ }
} elseif ( $params['mimeType'] == 'image/gif' ) {
if ( $this->getImageArea( $image ) > $wgMaxAnimatedGifArea ) {
// Extract initial frame only; we're so big it'll
// Coalesce is needed to scale animated GIFs properly (bug 1017).
$im = $im->coalesceImages();
}
+ // GIF interlacing is only available since 6.3.4
+ $v = Imagick::getVersion();
+ preg_match( '/ImageMagick ([0-9]+\.[0-9]+\.[0-9]+)/', $v['versionString'], $v );
+
+ if ( $params['interlace'] && version_compare( $v[1], '6.3.4' ) >= 0 ) {
+ $im->setInterlaceScheme( Imagick::INTERLACE_GIF );
+ }
}
$rotation = isset( $params['disableRotation'] ) ? 0 : $this->getRotation( $image );
*/
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.