46 if ( !$dstPath && $checkDstPath ) {
47 # No output path available, client side scaling only
55 } elseif ( function_exists(
'imagecreatetruecolor' ) ) {
57 } elseif ( class_exists(
'Imagick' ) ) {
71 $res = parent::makeParamString( $params );
72 if ( isset( $params[
'interlace'] ) && $params[
'interlace'] ) {
73 return "interlaced-{$res}";
84 $remainder = preg_replace(
'/^interlaced-/',
'', $str );
85 $params = parent::parseParamString( $remainder );
86 if ( $params ===
false ) {
89 $params[
'interlace'] = $str !== $remainder;
98 if ( $name ===
'interlace' ) {
99 return $value ===
false || $value ===
true;
101 return parent::validateParam( $name, $value );
113 if ( !parent::normaliseParams( $image, $params ) ) {
116 $mimeType = $image->getMimeType();
117 $interlace = isset( $params[
'interlace'] ) && $params[
'interlace']
120 $params[
'interlace'] = $interlace;
131 switch ( $pixelFormat ) {
133 return [
'1x1',
'1x1',
'1x1' ];
135 return [
'2x1',
'1x1',
'1x1' ];
137 return [
'2x2',
'1x1',
'1x1' ];
139 throw new MWException(
'Invalid pixel format for JPEG output' );
162 $animation_post = [];
166 if ( $params[
'mimeType'] ==
'image/jpeg' ) {
167 $qualityVal = isset( $params[
'quality'] ) ? (string)$params[
'quality'] :
null;
169 if ( $params[
'interlace'] ) {
170 $animation_post = [
'-interlace',
'JPEG' ];
172 # Sharpening, see T8193
173 if ( ( $params[
'physicalWidth'] + $params[
'physicalHeight'] )
174 / ( $params[
'srcWidth'] + $params[
'srcHeight'] )
181 $decoderHint = [
'-define',
"jpeg:size={$params['physicalDimensions']}" ];
185 $subsampling = [
'-sampling-factor', implode(
',', $factors ) ];
187 } elseif ( $params[
'mimeType'] ==
'image/png' ) {
188 $quality = [
'-quality',
'95' ];
189 if ( $params[
'interlace'] ) {
190 $animation_post = [
'-interlace',
'PNG' ];
192 } elseif ( $params[
'mimeType'] ==
'image/webp' ) {
193 $quality = [
'-quality',
'95' ];
194 } elseif ( $params[
'mimeType'] ==
'image/gif' ) {
201 $animation_pre = [
'-coalesce' ];
205 $animation_post = [
'-fuzz',
'5%',
'-layers',
'optimizeTransparency' ];
210 $animation_post[] =
'-interlace';
211 $animation_post[] =
'GIF';
213 } elseif ( $params[
'mimeType'] ==
'image/x-xcf' ) {
221 '-background',
'transparent',
223 '-background',
'white',
228 $env = [
'OMP_NUM_THREADS' => 1 ];
233 $rotation = isset( $params[
'disableRotation'] ) ? 0 : $this->
getRotation( $image );
236 $cmd = Shell::escape( ...array_merge(
241 [
'-background',
'white' ],
248 [
'-thumbnail',
"{$width}x{$height}!" ],
250 ( $params[
'comment'] !==
''
254 [
'+set',
'Thumb::URI' ],
257 [
'-rotate',
"-$rotation" ],
262 wfDebug( __METHOD__ .
": running ImageMagick: $cmd" );
266 if ( $retval !== 0 ) {
272 return false; # No error
289 $im->readImage( $params[
'srcPath'] );
291 if ( $params[
'mimeType'] ==
'image/jpeg' ) {
293 if ( ( $params[
'physicalWidth'] + $params[
'physicalHeight'] )
294 / ( $params[
'srcWidth'] + $params[
'srcHeight'] )
299 $im->sharpenImage( $radius, $sigma );
301 $qualityVal = isset( $params[
'quality'] ) ? (string)$params[
'quality'] :
null;
303 if ( $params[
'interlace'] ) {
304 $im->setInterlaceScheme( Imagick::INTERLACE_JPEG );
308 $im->setSamplingFactors( $factors );
310 } elseif ( $params[
'mimeType'] ==
'image/png' ) {
311 $im->setCompressionQuality( 95 );
312 if ( $params[
'interlace'] ) {
313 $im->setInterlaceScheme( Imagick::INTERLACE_PNG );
315 } elseif ( $params[
'mimeType'] ==
'image/gif' ) {
319 $im->setImageScene( 0 );
322 $im = $im->coalesceImages();
325 if ( $params[
'interlace'] ) {
326 $im->setInterlaceScheme( Imagick::INTERLACE_GIF );
330 $rotation = isset( $params[
'disableRotation'] ) ? 0 : $this->
getRotation( $image );
333 $im->setImageBackgroundColor(
new ImagickPixel(
'white' ) );
336 foreach ( $im as $i => $frame ) {
337 if ( !$frame->thumbnailImage( $width, $height,
false ) ) {
341 $im->setImageDepth( 8 );
343 if ( $rotation && !$im->rotateImage(
new ImagickPixel(
'white' ), 360 - $rotation ) ) {
348 wfDebug( __METHOD__ .
": Writing animated thumbnail" );
350 $result = $im->writeImages( $params[
'dstPath'],
true );
352 $result = $im->writeImage( $params[
'dstPath'] );
356 "Unable to write thumbnail to {$params['dstPath']}" );
358 }
catch ( ImagickException $e ) {
374 # Use a custom convert command
377 # Variables: %s %d %w %h
378 $src = Shell::escape( $params[
'srcPath'] );
379 $dst = Shell::escape( $params[
'dstPath'] );
381 $cmd = str_replace(
'%s', $src, str_replace(
'%d', $dst, $cmd ) ); # Filenames
382 $cmd = str_replace(
'%h', Shell::escape( $params[
'physicalHeight'] ),
383 str_replace(
'%w', Shell::escape( $params[
'physicalWidth'] ), $cmd ) ); # Size
384 wfDebug( __METHOD__ .
": Running custom convert command $cmd" );
388 if ( $retval !== 0 ) {
394 return false; # No error
406 # Use PHP's builtin GD library functions.
407 # First find out what kind of file this is, and select the correct
408 # input routine for this.
411 'image/gif' => [
'imagecreatefromgif',
'palette',
false,
'imagegif' ],
412 'image/jpeg' => [
'imagecreatefromjpeg',
'truecolor',
true,
413 [ __CLASS__,
'imageJpegWrapper' ] ],
414 'image/png' => [
'imagecreatefrompng',
'bits',
false,
'imagepng' ],
415 'image/vnd.wap.wbmp' => [
'imagecreatefromwbmp',
'palette',
false,
'imagewbmp' ],
416 'image/xbm' => [
'imagecreatefromxbm',
'palette',
false,
'imagexbm' ],
419 if ( !isset( $typemap[$params[
'mimeType']] ) ) {
420 $err =
'Image type not supported';
422 $errMsg =
wfMessage(
'thumbnail_image-type' )->text();
426 list( $loader, $colorStyle, $useQuality, $saveType ) = $typemap[$params[
'mimeType']];
428 if ( !function_exists( $loader ) ) {
429 $err =
"Incomplete GD library configuration: missing function $loader";
431 $errMsg =
wfMessage(
'thumbnail_gd-library', $loader )->text();
436 if ( !file_exists( $params[
'srcPath'] ) ) {
437 $err =
"File seems to be missing: {$params['srcPath']}";
439 $errMsg =
wfMessage(
'thumbnail_image-missing', $params[
'srcPath'] )->text();
444 if ( filesize( $params[
'srcPath'] ) === 0 ) {
445 $err =
"Image file size seems to be zero.";
447 $errMsg =
wfMessage(
'thumbnail_image-size-zero', $params[
'srcPath'] )->text();
452 $src_image = $loader( $params[
'srcPath'] );
454 $rotation = function_exists(
'imagerotate' ) && !isset( $params[
'disableRotation'] ) ?
458 $dst_image = imagecreatetruecolor( $width, $height );
462 $background = imagecolorallocate( $dst_image, 0, 0, 0 );
463 imagecolortransparent( $dst_image, $background );
464 imagealphablending( $dst_image,
false );
466 if ( $colorStyle ==
'palette' ) {
469 imagecopyresized( $dst_image, $src_image,
472 imagesx( $src_image ), imagesy( $src_image ) );
474 imagecopyresampled( $dst_image, $src_image,
477 imagesx( $src_image ), imagesy( $src_image ) );
480 if ( $rotation % 360 != 0 && $rotation % 90 == 0 ) {
481 $rot_image = imagerotate( $dst_image, $rotation, 0 );
482 imagedestroy( $dst_image );
483 $dst_image = $rot_image;
486 imagesavealpha( $dst_image,
true );
488 $funcParams = [ $dst_image, $params[
'dstPath'] ];
489 if ( $useQuality && isset( $params[
'quality'] ) ) {
490 $funcParams[] = $params[
'quality'];
492 $saveType( ...$funcParams );
494 imagedestroy( $dst_image );
495 imagedestroy( $src_image );
497 return false; # No error
511 if ( $quality ===
null ) {
515 imageinterlace( $dst_image );
516 imagejpeg( $dst_image, $thumbPath, $quality );
529 # ImageMagick supports autorotation
532 # Imagick::rotateImage
535 # GD's imagerotate function is used to rotate images, but not
536 # all precompiled PHP versions have that function
537 return function_exists(
'imagerotate' );
539 # Other scalers don't support rotation
579 " -rotate " . Shell::escape(
"-$rotation" ) .
" " .
581 wfDebug( __METHOD__ .
": running ImageMagick: $cmd" );
584 if ( $retval !== 0 ) {
593 $im->readImage( $params[
'srcPath'] );
594 if ( !$im->rotateImage(
new ImagickPixel(
'white' ), 360 - $rotation ) ) {
596 "Error rotating $rotation degrees" );
598 $result = $im->writeImage( $params[
'dstPath'] );
601 "Unable to write image to {$params['dstPath']}" );
607 "$scaler rotation not implemented" );
$wgCustomConvertCommand
Use another resizing converter, e.g.
$wgMaxInterlacingAreas
Array of max pixel areas for interlacing per MIME type.
$wgUseImageResize
Whether to enable server-side image thumbnailing.
$wgJpegQuality
When scaling a JPEG thumbnail, this is the quality we request from the backend.
$wgEnableAutoRotation
If set to true, images that contain certain the exif orientation tag will be rotated accordingly.
$wgImageMagickTempDir
Temporary directory used for ImageMagick.
$wgSharpenReductionThreshold
Reduction in linear dimensions below which sharpening will be enabled.
$wgJpegPixelFormat
At default setting of 'yuv420', JPEG thumbnails will use 4:2:0 chroma subsampling to reduce file size...
$wgSharpenParameter
Sharpening parameter to ImageMagick.
$wgMaxAnimatedGifArea
Force thumbnailing of animated GIFs above this size to a single frame instead of an animated thumbnai...
$wgUseImageMagick
Resizing can be done using PHP's internal image libraries or using ImageMagick or another third-party...
$wgImageMagickConvertCommand
The convert command shipped with ImageMagick.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfShellExecWithStderr( $cmd, &$retval=null, $environ=[], $limits=[])
Execute a shell command, returning both stdout and stderr.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Generic handler for bitmap images.
canRotate()
Returns whether the current scaler supports rotation (im and gd do) Stable to override.
rotate( $file, $params)
Stable to override.
static imageJpegWrapper( $dst_image, $thumbPath, $quality=null)
Callback for transformGd when transforming jpeg images.
transformImageMagick( $image, $params)
Transform an image using ImageMagick Stable to override.
getScalerType( $dstPath, $checkDstPath=true)
Returns which scaler type should be used.
imageMagickSubsampling( $pixelFormat)
Get ImageMagick subsampling factors for the target JPEG pixel format.
transformCustom( $image, $params)
Transform an image using a custom command.
makeParamString( $params)
Merge a parameter array into a string appropriate for inclusion in filenames.string Stable to overrid...
transformGd( $image, $params)
Transform an image using the built in GD library.
parseParamString( $str)
Parse a param string made with makeParamString back into an array.array|bool Array of parameters or f...
normaliseParams( $image, &$params)
Stable to override.
transformImageMagickExt( $image, $params)
Transform an image using the Imagick PHP extension.
validateParam( $name, $value)
Validate a thumbnail parameter at parse time.Return true to accept the parameter, and false to reject...
getImageArea( $image)
Function that returns the number of pixels to be thumbnailed.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.