Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1431387
BitmapHandler.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
BitmapHandler.php
View Options
<?php
/**
* Generic handler for bitmap images.
*
* @license GPL-2.0-or-later
* @file
* @ingroup Media
*/
use
MediaWiki\FileRepo\File\File
;
use
MediaWiki\MainConfigNames
;
use
MediaWiki\MediaWikiServices
;
use
MediaWiki\Shell\Shell
;
/**
* Generic handler for bitmap images
*
* @stable to extend
* @ingroup Media
*/
class
BitmapHandler
extends
TransformationalImageHandler
{
/**
* Returns which scaler type should be used. Creates parent directories
* for $dstPath and returns 'client' on error
* @stable to override
*
* @param string|null $dstPath
* @param bool $checkDstPath
* @return string|callable One of client, im, custom, gd, imext or an array( object, method )
*/
protected
function
getScalerType
(
$dstPath
,
$checkDstPath
=
true
)
{
$mainConfig
=
MediaWikiServices
::
getInstance
()->
getMainConfig
();
$useImageResize
=
$mainConfig
->
get
(
MainConfigNames
::
UseImageResize
);
$useImageMagick
=
$mainConfig
->
get
(
MainConfigNames
::
UseImageMagick
);
$customConvertCommand
=
$mainConfig
->
get
(
MainConfigNames
::
CustomConvertCommand
);
if
(
!
$dstPath
&&
$checkDstPath
)
{
# No output path available, client side scaling only
$scaler
=
'client'
;
}
elseif
(
!
$useImageResize
)
{
$scaler
=
'client'
;
}
elseif
(
$useImageMagick
)
{
$scaler
=
'im'
;
}
elseif
(
$customConvertCommand
)
{
$scaler
=
'custom'
;
}
elseif
(
$this
->
hasGDSupport
()
&&
function_exists
(
'imagecreatetruecolor'
)
)
{
$scaler
=
'gd'
;
}
elseif
(
class_exists
(
'Imagick'
)
)
{
$scaler
=
'imext'
;
}
else
{
$scaler
=
'client'
;
}
return
$scaler
;
}
/**
* Whether the php-gd extension supports this type of file.
*
* @stable to override
* @return bool
*/
protected
function
hasGDSupport
()
{
return
true
;
}
/**
* @inheritDoc
* @stable to override
*/
public
function
makeParamString
(
$params
)
{
$res
=
parent
::
makeParamString
(
$params
);
if
(
isset
(
$params
[
'interlace'
]
)
&&
$params
[
'interlace'
]
)
{
return
"interlaced-$res"
;
}
return
$res
;
}
/**
* @inheritDoc
* @stable to override
*/
public
function
parseParamString
(
$str
)
{
$remainder
=
preg_replace
(
'/^interlaced-/'
,
''
,
$str
);
$params
=
parent
::
parseParamString
(
$remainder
);
if
(
$params
===
false
)
{
return
false
;
}
$params
[
'interlace'
]
=
$str
!==
$remainder
;
return
$params
;
}
/**
* @inheritDoc
* @stable to override
*/
public
function
validateParam
(
$name
,
$value
)
{
if
(
$name
===
'interlace'
)
{
return
$value
===
false
||
$value
===
true
;
}
return
parent
::
validateParam
(
$name
,
$value
);
}
/**
* @stable to override
* @param File $image
* @param array &$params
* @return bool
*/
public
function
normaliseParams
(
$image
,
&
$params
)
{
$maxInterlacingAreas
=
MediaWikiServices
::
getInstance
()->
getMainConfig
()
->
get
(
MainConfigNames
::
MaxInterlacingAreas
);
if
(
!
parent
::
normaliseParams
(
$image
,
$params
)
)
{
return
false
;
}
$mimeType
=
$image
->
getMimeType
();
$interlace
=
isset
(
$params
[
'interlace'
]
)
&&
$params
[
'interlace'
]
&&
isset
(
$maxInterlacingAreas
[
$mimeType
]
)
&&
$this
->
getImageArea
(
$image
)
<=
$maxInterlacingAreas
[
$mimeType
];
$params
[
'interlace'
]
=
$interlace
;
return
true
;
}
/**
* Get ImageMagick subsampling factors for the target JPEG pixel format.
*
* @param string $pixelFormat one of 'yuv444', 'yuv422', 'yuv420'
* @return string[] List of sampling factors
*/
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
UnexpectedValueException
(
'Invalid pixel format for JPEG output'
);
}
}
/**
* Transform an image using ImageMagick
* @stable to override
*
* @param File $image File associated with this thumbnail
* @param array $params Array with scaler params
*
* @return MediaTransformError|false Error object if error occurred, false (=no error) otherwise
*/
protected
function
transformImageMagick
(
$image
,
$params
)
{
# use ImageMagick
$mainConfig
=
MediaWikiServices
::
getInstance
()->
getMainConfig
();
$sharpenReductionThreshold
=
$mainConfig
->
get
(
MainConfigNames
::
SharpenReductionThreshold
);
$sharpenParameter
=
$mainConfig
->
get
(
MainConfigNames
::
SharpenParameter
);
$maxAnimatedGifArea
=
$mainConfig
->
get
(
MainConfigNames
::
MaxAnimatedGifArea
);
$imageMagickTempDir
=
$mainConfig
->
get
(
MainConfigNames
::
ImageMagickTempDir
);
$imageMagickConvertCommand
=
$mainConfig
->
get
(
MainConfigNames
::
ImageMagickConvertCommand
);
$jpegPixelFormat
=
$mainConfig
->
get
(
MainConfigNames
::
JpegPixelFormat
);
$jpegQuality
=
$mainConfig
->
get
(
MainConfigNames
::
JpegQuality
);
$quality
=
[];
$sharpen
=
[];
$scene
=
false
;
$animation_pre
=
[];
$animation_post
=
[];
$decoderHint
=
[];
$subsampling
=
[];
if
(
$params
[
'mimeType'
]
===
'image/jpeg'
)
{
$qualityVal
=
isset
(
$params
[
'quality'
]
)
?
(
string
)
$params
[
'quality'
]
:
null
;
$quality
=
[
'-quality'
,
$qualityVal
?:
(
string
)
$jpegQuality
];
// 80% by default
if
(
$params
[
'interlace'
]
)
{
$animation_post
=
[
'-interlace'
,
'JPEG'
];
}
# Sharpening, see T8193
if
(
(
$params
[
'physicalWidth'
]
+
$params
[
'physicalHeight'
]
)
/
(
$params
[
'srcWidth'
]
+
$params
[
'srcHeight'
]
)
<
$sharpenReductionThreshold
)
{
$sharpen
=
[
'-sharpen'
,
$sharpenParameter
];
}
// JPEG decoder hint to reduce memory, available since IM 6.5.6-2
$decoderHint
=
[
'-define'
,
"jpeg:size={$params['physicalDimensions']}"
];
if
(
$jpegPixelFormat
)
{
$factors
=
$this
->
imageMagickSubsampling
(
$jpegPixelFormat
);
$subsampling
=
[
'-sampling-factor'
,
implode
(
','
,
$factors
)
];
}
}
elseif
(
$params
[
'mimeType'
]
===
'image/png'
)
{
$quality
=
[
'-quality'
,
'95'
];
// zlib 9, adaptive filtering
if
(
$params
[
'interlace'
]
)
{
$animation_post
=
[
'-interlace'
,
'PNG'
];
}
}
elseif
(
$params
[
'mimeType'
]
===
'image/webp'
)
{
$quality
=
[
'-quality'
,
'95'
];
// zlib 9, adaptive filtering
}
elseif
(
$params
[
'mimeType'
]
===
'image/gif'
)
{
if
(
$this
->
getImageArea
(
$image
)
>
$maxAnimatedGifArea
)
{
// 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 (T3017).
$animation_pre
=
[
'-coalesce'
];
// We optimize the output, but -optimize is broken,
// use optimizeTransparency instead (T13822). Version >= IM 6.3.5
$animation_post
=
[
'-fuzz'
,
'5%'
,
'-layers'
,
'optimizeTransparency'
];
}
if
(
$params
[
'interlace'
]
&&
!
$this
->
isAnimatedImage
(
$image
)
)
{
// Version >= IM 6.3.4
// 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
// merges all layers on to a canvas filled with the
// background colour. After merging we reset the background
// to be white for the default background colour setting
// in the PNG image (which is used in old IE)
$animation_pre
=
[
'-background'
,
'transparent'
,
'-layers'
,
'merge'
,
'-background'
,
'white'
,
];
}
// Use one thread only, to avoid deadlock bugs on OOM
$env
=
[
'OMP_NUM_THREADS'
=>
1
];
if
(
(
string
)
$imageMagickTempDir
!==
''
)
{
$env
[
'MAGICK_TMPDIR'
]
=
$imageMagickTempDir
;
}
$rotation
=
isset
(
$params
[
'disableRotation'
]
)
?
0
:
$this
->
getRotation
(
$image
);
[
$width
,
$height
]
=
$this
->
extractPreRotationDimensions
(
$params
,
$rotation
);
$cmd
=
Shell
::
escape
(
...
array_merge
(
[
$imageMagickConvertCommand
],
$quality
,
// Specify white background color, will be used for transparent images
// in Internet Explorer/Windows instead of default black.
[
'-background'
,
'white'
],
$decoderHint
,
[
$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'
,
"{$width}x{$height}!"
],
// Add the source url as a comment to the thumb, but don't add the flag if there's no comment
(
$params
[
'comment'
]
!==
''
?
[
'-set'
,
'comment'
,
$this
->
escapeMagickProperty
(
$params
[
'comment'
]
)
]
:
[]
),
// T108616: Avoid exposure of local file path
[
'+set'
,
'Thumb::URI'
],
[
'-depth'
,
8
],
$sharpen
,
[
'-rotate'
,
"-$rotation"
],
$subsampling
,
$animation_post
,
[
$this
->
escapeMagickOutput
(
$params
[
'dstPath'
]
)
]
)
);
wfDebug
(
__METHOD__
.
": running ImageMagick: $cmd"
);
$retval
=
0
;
$err
=
wfShellExecWithStderr
(
$cmd
,
$retval
,
$env
);
if
(
$retval
!==
0
)
{
$this
->
logErrorForExternalProcess
(
$retval
,
$err
,
$cmd
);
return
$this
->
getMediaTransformError
(
$params
,
"$err
\n
Error code: $retval"
);
}
return
false
;
# No error
}
/**
* Transform an image using the Imagick PHP extension
*
* @param File $image File associated with this thumbnail
* @param array $params Array with scaler params
*
* @return MediaTransformError|false Error object if error occurred, false (=no error) otherwise
*/
protected
function
transformImageMagickExt
(
$image
,
$params
)
{
$mainConfig
=
MediaWikiServices
::
getInstance
()->
getMainConfig
();
$sharpenReductionThreshold
=
$mainConfig
->
get
(
MainConfigNames
::
SharpenReductionThreshold
);
$sharpenParameter
=
$mainConfig
->
get
(
MainConfigNames
::
SharpenParameter
);
$maxAnimatedGifArea
=
$mainConfig
->
get
(
MainConfigNames
::
MaxAnimatedGifArea
);
$jpegPixelFormat
=
$mainConfig
->
get
(
MainConfigNames
::
JpegPixelFormat
);
$jpegQuality
=
$mainConfig
->
get
(
MainConfigNames
::
JpegQuality
);
try
{
$im
=
new
Imagick
();
$im
->
readImage
(
$params
[
'srcPath'
]
);
if
(
$params
[
'mimeType'
]
===
'image/jpeg'
)
{
// Sharpening, see T8193
if
(
(
$params
[
'physicalWidth'
]
+
$params
[
'physicalHeight'
]
)
/
(
$params
[
'srcWidth'
]
+
$params
[
'srcHeight'
]
)
<
$sharpenReductionThreshold
)
{
// Hack, since $wgSharpenParameter is written specifically for the command line convert
[
$radius
,
$sigma
]
=
explode
(
'x'
,
$sharpenParameter
,
2
);
$im
->
sharpenImage
(
(
float
)
$radius
,
(
float
)
$sigma
);
}
$qualityVal
=
isset
(
$params
[
'quality'
]
)
?
(
string
)
$params
[
'quality'
]
:
null
;
$im
->
setCompressionQuality
(
$qualityVal
?:
$jpegQuality
);
if
(
$params
[
'interlace'
]
)
{
$im
->
setInterlaceScheme
(
Imagick
::
INTERLACE_JPEG
);
}
if
(
$jpegPixelFormat
)
{
$factors
=
$this
->
imageMagickSubsampling
(
$jpegPixelFormat
);
$im
->
setSamplingFactors
(
$factors
);
}
}
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
)
>
$maxAnimatedGifArea
)
{
// Extract initial frame only; we're so big it'll
// be a total drag. :P
$im
->
setImageScene
(
0
);
}
elseif
(
$this
->
isAnimatedImage
(
$image
)
)
{
// Coalesce is needed to scale animated GIFs properly (T3017).
$im
=
$im
->
coalesceImages
();
}
// GIF interlacing is only available since 6.3.4
if
(
$params
[
'interlace'
]
)
{
$im
->
setInterlaceScheme
(
Imagick
::
INTERLACE_GIF
);
}
}
$rotation
=
isset
(
$params
[
'disableRotation'
]
)
?
0
:
$this
->
getRotation
(
$image
);
[
$width
,
$height
]
=
$this
->
extractPreRotationDimensions
(
$params
,
$rotation
);
$im
->
setImageBackgroundColor
(
new
ImagickPixel
(
'white'
)
);
// Call Imagick::thumbnailImage on each frame
foreach
(
$im
as
$i
=>
$frame
)
{
if
(
!
$frame
->
thumbnailImage
(
$width
,
$height
,
/* fit */
false
)
)
{
return
$this
->
getMediaTransformError
(
$params
,
"Error scaling frame $i"
);
}
}
$im
->
setImageDepth
(
8
);
if
(
$rotation
&&
!
$im
->
rotateImage
(
new
ImagickPixel
(
'white'
),
360
-
$rotation
)
)
{
return
$this
->
getMediaTransformError
(
$params
,
"Error rotating $rotation degrees"
);
}
if
(
$this
->
isAnimatedImage
(
$image
)
)
{
wfDebug
(
__METHOD__
.
": Writing animated thumbnail"
);
// This is broken somehow... can't find out how to fix it
$result
=
$im
->
writeImages
(
$params
[
'dstPath'
],
true
);
}
else
{
$result
=
$im
->
writeImage
(
$params
[
'dstPath'
]
);
}
if
(
!
$result
)
{
return
$this
->
getMediaTransformError
(
$params
,
"Unable to write thumbnail to {$params['dstPath']}"
);
}
}
catch
(
ImagickException
$e
)
{
return
$this
->
getMediaTransformError
(
$params
,
$e
->
getMessage
()
);
}
return
false
;
}
/**
* Transform an image using a custom command
*
* @param File $image File associated with this thumbnail
* @param array $params Array with scaler params
*
* @return MediaTransformError|false Error object if error occurred, false (=no error) otherwise
*/
protected
function
transformCustom
(
$image
,
$params
)
{
// Use a custom convert command
$customConvertCommand
=
MediaWikiServices
::
getInstance
()->
getMainConfig
()
->
get
(
MainConfigNames
::
CustomConvertCommand
);
// Find all variables in the original command at once,
// so that replacement values cannot inject variable placeholders
$cmd
=
strtr
(
$customConvertCommand
,
[
'%s'
=>
Shell
::
escape
(
$params
[
'srcPath'
]
),
'%d'
=>
Shell
::
escape
(
$params
[
'dstPath'
]
),
'%w'
=>
Shell
::
escape
(
$params
[
'physicalWidth'
]
),
'%h'
=>
Shell
::
escape
(
$params
[
'physicalHeight'
]
),
]
);
wfDebug
(
__METHOD__
.
": Running custom convert command $cmd"
);
$retval
=
0
;
$err
=
wfShellExecWithStderr
(
$cmd
,
$retval
);
if
(
$retval
!==
0
)
{
$this
->
logErrorForExternalProcess
(
$retval
,
$err
,
$cmd
);
return
$this
->
getMediaTransformError
(
$params
,
$err
);
}
return
false
;
# No error
}
/**
* Transform an image using the built in GD library
*
* @param File $image File associated with this thumbnail
* @param array $params Array with scaler params
*
* @return MediaTransformError|false Error object if error occurred, 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
=
[
'image/gif'
=>
[
'imagecreatefromgif'
,
'palette'
,
false
,
'imagegif'
],
'image/jpeg'
=>
[
'imagecreatefromjpeg'
,
'truecolor'
,
true
,
[
self
::
class
,
'imageJpegWrapper'
]
],
'image/png'
=>
[
'imagecreatefrompng'
,
'bits'
,
false
,
'imagepng'
],
'image/vnd.wap.wbmp'
=>
[
'imagecreatefromwbmp'
,
'palette'
,
false
,
'imagewbmp'
],
'image/xbm'
=>
[
'imagecreatefromxbm'
,
'palette'
,
false
,
'imagexbm'
],
];
if
(
!
isset
(
$typemap
[
$params
[
'mimeType'
]]
)
)
{
$err
=
'Image type not supported'
;
wfDebug
(
$err
);
$errMsg
=
wfMessage
(
'thumbnail_image-type'
)->
text
();
return
$this
->
getMediaTransformError
(
$params
,
$errMsg
);
}
[
$loader
,
$colorStyle
,
$useQuality
,
$saveType
]
=
$typemap
[
$params
[
'mimeType'
]];
if
(
!
function_exists
(
$loader
)
)
{
$err
=
"Incomplete GD library configuration: missing function $loader"
;
wfDebug
(
$err
);
$errMsg
=
wfMessage
(
'thumbnail_gd-library'
,
$loader
)->
text
();
return
$this
->
getMediaTransformError
(
$params
,
$errMsg
);
}
if
(
!
file_exists
(
$params
[
'srcPath'
]
)
)
{
$err
=
"File seems to be missing: {$params['srcPath']}"
;
wfDebug
(
$err
);
$errMsg
=
wfMessage
(
'thumbnail_image-missing'
,
$params
[
'srcPath'
]
)->
text
();
return
$this
->
getMediaTransformError
(
$params
,
$errMsg
);
}
if
(
filesize
(
$params
[
'srcPath'
]
)
===
0
)
{
$err
=
"Image file size seems to be zero."
;
wfDebug
(
$err
);
$errMsg
=
wfMessage
(
'thumbnail_image-size-zero'
,
$params
[
'srcPath'
]
)->
text
();
return
$this
->
getMediaTransformError
(
$params
,
$errMsg
);
}
$src_image
=
$loader
(
$params
[
'srcPath'
]
);
$rotation
=
function_exists
(
'imagerotate'
)
&&
!
isset
(
$params
[
'disableRotation'
]
)
?
$this
->
getRotation
(
$image
)
:
0
;
[
$width
,
$height
]
=
$this
->
extractPreRotationDimensions
(
$params
,
$rotation
);
$dst_image
=
imagecreatetruecolor
(
$width
,
$height
);
// 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
,
$width
,
$height
,
imagesx
(
$src_image
),
imagesy
(
$src_image
)
);
}
else
{
imagecopyresampled
(
$dst_image
,
$src_image
,
0
,
0
,
0
,
0
,
$width
,
$height
,
imagesx
(
$src_image
),
imagesy
(
$src_image
)
);
}
if
(
$rotation
%
360
!==
0
&&
$rotation
%
90
===
0
)
{
$rot_image
=
imagerotate
(
$dst_image
,
$rotation
,
0
);
imagedestroy
(
$dst_image
);
$dst_image
=
$rot_image
;
}
imagesavealpha
(
$dst_image
,
true
);
$funcParams
=
[
$dst_image
,
$params
[
'dstPath'
]
];
if
(
$useQuality
&&
isset
(
$params
[
'quality'
]
)
)
{
$funcParams
[]
=
$params
[
'quality'
];
}
// @phan-suppress-next-line PhanParamTooFewInternalUnpack,PhanParamTooFewUnpack There are at least 2 args
$saveType
(
...
$funcParams
);
imagedestroy
(
$dst_image
);
imagedestroy
(
$src_image
);
return
false
;
# No error
}
/**
* Callback for transformGd when transforming jpeg images.
*
* @phpcs:ignore MediaWiki.Commenting.FunctionComment.ObjectTypeHintParam
* @param resource|object $dst_image Image resource of the original image
* @param string $thumbPath File path to write the thumbnail image to
* @param int|null $quality Quality of the thumbnail from 1-100,
* or null to use default quality.
*/
public
static
function
imageJpegWrapper
(
$dst_image
,
$thumbPath
,
$quality
=
null
)
{
$jpegQuality
=
MediaWikiServices
::
getInstance
()->
getMainConfig
()->
get
(
MainConfigNames
::
JpegQuality
);
imageinterlace
(
$dst_image
);
imagejpeg
(
$dst_image
,
$thumbPath
,
$quality
??
$jpegQuality
);
}
/**
* Returns whether the current scaler supports rotation (im and gd do)
* @stable to override
*
* @return bool
*/
public
function
canRotate
()
{
$scaler
=
$this
->
getScalerType
(
null
,
false
);
switch
(
$scaler
)
{
case
'im'
:
# ImageMagick supports autorotation
return
true
;
case
'imext'
:
# Imagick::rotateImage
return
true
;
case
'gd'
:
# GD's imagerotate function is used to rotate images, but not
# all precompiled PHP versions have that function
return
function_exists
(
'imagerotate'
);
default
:
# Other scalers don't support rotation
return
false
;
}
}
/**
* @see $wgEnableAutoRotation
* @stable to override
* @return bool Whether auto rotation is enabled
*/
public
function
autoRotateEnabled
()
{
$enableAutoRotation
=
MediaWikiServices
::
getInstance
()->
getMainConfig
()
->
get
(
MainConfigNames
::
EnableAutoRotation
);
if
(
$enableAutoRotation
===
null
)
{
// Only enable auto-rotation when we actually can
return
$this
->
canRotate
();
}
return
$enableAutoRotation
;
}
/**
* @stable to override
* @param File $file
* @param array $params Rotate parameters.
* 'rotation' clockwise rotation in degrees, allowed are multiples of 90
* @since 1.21
* @return MediaTransformError|false
*/
public
function
rotate
(
$file
,
$params
)
{
$imageMagickConvertCommand
=
MediaWikiServices
::
getInstance
()
->
getMainConfig
()->
get
(
MainConfigNames
::
ImageMagickConvertCommand
);
$rotation
=
(
$params
[
'rotation'
]
+
$this
->
getRotation
(
$file
)
)
%
360
;
$scene
=
false
;
$scaler
=
$this
->
getScalerType
(
null
,
false
);
switch
(
$scaler
)
{
case
'im'
:
$cmd
=
Shell
::
escape
(
$imageMagickConvertCommand
)
.
" "
.
Shell
::
escape
(
$this
->
escapeMagickInput
(
$params
[
'srcPath'
],
$scene
)
)
.
" -rotate "
.
Shell
::
escape
(
"-$rotation"
)
.
" "
.
Shell
::
escape
(
$this
->
escapeMagickOutput
(
$params
[
'dstPath'
]
)
);
wfDebug
(
__METHOD__
.
": running ImageMagick: $cmd"
);
$retval
=
0
;
$err
=
wfShellExecWithStderr
(
$cmd
,
$retval
);
if
(
$retval
!==
0
)
{
$this
->
logErrorForExternalProcess
(
$retval
,
$err
,
$cmd
);
return
new
MediaTransformError
(
'thumbnail_error'
,
0
,
0
,
$err
);
}
return
false
;
case
'imext'
:
$im
=
new
Imagick
();
$im
->
readImage
(
$params
[
'srcPath'
]
);
if
(
!
$im
->
rotateImage
(
new
ImagickPixel
(
'white'
),
360
-
$rotation
)
)
{
return
new
MediaTransformError
(
'thumbnail_error'
,
0
,
0
,
"Error rotating $rotation degrees"
);
}
$result
=
$im
->
writeImage
(
$params
[
'dstPath'
]
);
if
(
!
$result
)
{
return
new
MediaTransformError
(
'thumbnail_error'
,
0
,
0
,
"Unable to write image to {$params['dstPath']}"
);
}
return
false
;
default
:
return
new
MediaTransformError
(
'thumbnail_error'
,
0
,
0
,
"$scaler rotation not implemented"
);
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 20:25 (1 d, 36 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
5f/a8/c6900048fb12a13773ae6e8ab7ac
Default Alt Text
BitmapHandler.php (20 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment