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
* @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 );
array(
'width' => 512, 'height' => 384,
'physicalWidth' => 512, 'physicalHeight' => 384,
- 'page' => 1,
+ 'page' => 1, 'interlace' => false,
),
array( 'width' => 512 ),
'Resizing with width set',
array(
'width' => 512, 'height' => 384,
'physicalWidth' => 512, 'physicalHeight' => 384,
- 'page' => 1,
+ 'page' => 1, 'interlace' => false,
),
array( 'width' => 512, 'height' => 768 ),
'Resizing with height set too high',
array(
'width' => 512, 'height' => 384,
'physicalWidth' => 512, 'physicalHeight' => 384,
- 'page' => 1,
+ 'page' => 1, 'interlace' => false,
),
array( 'width' => 1024, 'height' => 384 ),
'Resizing with height set',
array(
'width' => 5, 'height' => 1,
'physicalWidth' => 5, 'physicalHeight' => 1,
- 'page' => 1,
+ 'page' => 1, 'interlace' => false,
),
array( 'width' => 5 ),
'Very wide image',
array(
'width' => 1, 'height' => 10,
'physicalWidth' => 1, 'physicalHeight' => 10,
- 'page' => 1,
+ 'page' => 1, 'interlace' => false,
),
array( 'width' => 1 ),
'Very high image',
array(
'width' => 1, 'height' => 5,
'physicalWidth' => 1, 'physicalHeight' => 10,
- 'page' => 1,
+ 'page' => 1, 'interlace' => false,
),
array( 'width' => 10, 'height' => 5 ),
'Very high image with height set',
array(
'width' => 5000, 'height' => 5000,
'physicalWidth' => 4000, 'physicalHeight' => 4000,
- 'page' => 1,
+ 'page' => 1, 'interlace' => false,
),
array( 'width' => 5000 ),
'Bigger than max image size but doesn\'t need scaling',
),
+ /* Max interlace image area */
+ array(
+ array( 4000, 4000 ),
+ array(
+ 'width' => 5000, 'height' => 5000,
+ 'physicalWidth' => 4000, 'physicalHeight' => 4000,
+ 'page' => 1, 'interlace' => false,
+ ),
+ array( 'width' => 5000, 'interlace' => true ),
+ 'Interlace bigger than max interlace area',
+ ),
);
}