Allow mobile to reduce image quality
http://www.mediawiki.org/wiki/Requests_for_comment/Reducing_image_quality_for_mobile Per above RFC, this patch implements the core changes required to specify quality reduction of JPEG via URL. To test, make sure your setup uses 404-based thumb generation. Vagrant supports it by adding "multimedia" role: $ vagrant add-role multimedia && vagrant provision * Pick any thumbnail jpeg URL that exists on the test wiki, e.g. http://.../images/thumb/4/49/Img.jpg/400px-Img.jpg * check that basic scaling works by altering 400 * add quality parameter qlow- right before px: http://.../images/thumb/4/49/Img.jpg/qlow-400px-Img.jpg Change-Id: I930ea06be6d302ffc8832d12b251422a9f1b3e75
This commit is contained in:
parent
a3983418d5
commit
a77032257f
3 changed files with 101 additions and 18 deletions
|
|
@ -530,7 +530,7 @@ class Linker {
|
|||
*
|
||||
* @param array $handlerParams Associative array of media handler parameters, to be passed
|
||||
* to transform(). Typical keys are "width" and "page".
|
||||
* @param string $time Timestamp of the file, set as false for current
|
||||
* @param string|bool $time Timestamp of the file, set as false for current
|
||||
* @param string $query Query params for desc url
|
||||
* @param int|null $widthOption Used by the parser to remember the user preference thumbnailsize
|
||||
* @since 1.20
|
||||
|
|
|
|||
|
|
@ -138,6 +138,10 @@ class BitmapHandler extends ImageHandler {
|
|||
'dstUrl' => $dstUrl,
|
||||
);
|
||||
|
||||
if ( isset( $params['quality'] ) && $params['quality'] === 'low' ) {
|
||||
$scalerParams['quality'] = 30;
|
||||
}
|
||||
|
||||
# Determine scaler type
|
||||
$scaler = self::getScalerType( $dstPath );
|
||||
|
||||
|
|
@ -147,6 +151,7 @@ class BitmapHandler extends ImageHandler {
|
|||
if ( !$image->mustRender() &&
|
||||
$scalerParams['physicalWidth'] == $scalerParams['srcWidth']
|
||||
&& $scalerParams['physicalHeight'] == $scalerParams['srcHeight']
|
||||
&& !isset( $scalerParams['quality'] )
|
||||
) {
|
||||
|
||||
# normaliseParams (or the user) wants us to return the unscaled image
|
||||
|
|
@ -163,12 +168,14 @@ class BitmapHandler extends ImageHandler {
|
|||
|
||||
if ( $flags & self::TRANSFORM_LATER ) {
|
||||
wfDebug( __METHOD__ . ": Transforming later per flags.\n" );
|
||||
$params = array(
|
||||
$newParams = array(
|
||||
'width' => $scalerParams['clientWidth'],
|
||||
'height' => $scalerParams['clientHeight']
|
||||
);
|
||||
|
||||
return new ThumbnailImage( $image, $dstUrl, false, $params );
|
||||
if ( isset( $params['quality'] ) ) {
|
||||
$newParams['quality'] = $params['quality'];
|
||||
}
|
||||
return new ThumbnailImage( $image, $dstUrl, false, $newParams );
|
||||
}
|
||||
|
||||
# Try to make a target path for the thumbnail
|
||||
|
|
@ -235,12 +242,14 @@ class BitmapHandler extends ImageHandler {
|
|||
} elseif ( $mto ) {
|
||||
return $mto;
|
||||
} else {
|
||||
$params = array(
|
||||
$newParams = array(
|
||||
'width' => $scalerParams['clientWidth'],
|
||||
'height' => $scalerParams['clientHeight']
|
||||
);
|
||||
|
||||
return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
|
||||
if ( isset( $params['quality'] ) ) {
|
||||
$newParams['quality'] = $params['quality'];
|
||||
}
|
||||
return new ThumbnailImage( $image, $dstUrl, $dstPath, $newParams );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -314,7 +323,8 @@ class BitmapHandler extends ImageHandler {
|
|||
$animation_post = array();
|
||||
$decoderHint = array();
|
||||
if ( $params['mimeType'] == 'image/jpeg' ) {
|
||||
$quality = array( '-quality', '80' ); // 80%
|
||||
$qualityVal = isset( $params['quality'] ) ? (string) $params['quality'] : null;
|
||||
$quality = array( '-quality', $qualityVal ?: '80' ); // 80%
|
||||
# Sharpening, see bug 6193
|
||||
if ( ( $params['physicalWidth'] + $params['physicalHeight'] )
|
||||
/ ( $params['srcWidth'] + $params['srcHeight'] )
|
||||
|
|
@ -419,7 +429,8 @@ class BitmapHandler extends ImageHandler {
|
|||
list( $radius, $sigma ) = explode( 'x', $wgSharpenParameter );
|
||||
$im->sharpenImage( $radius, $sigma );
|
||||
}
|
||||
$im->setCompressionQuality( 80 );
|
||||
$qualityVal = isset( $params['quality'] ) ? (string) $params['quality'] : null;
|
||||
$im->setCompressionQuality( $qualityVal ?: 80 );
|
||||
} elseif ( $params['mimeType'] == 'image/png' ) {
|
||||
$im->setCompressionQuality( 95 );
|
||||
} elseif ( $params['mimeType'] == 'image/gif' ) {
|
||||
|
|
@ -531,13 +542,14 @@ class BitmapHandler extends ImageHandler {
|
|||
# input routine for this.
|
||||
|
||||
$typemap = array(
|
||||
'image/gif' => array( 'imagecreatefromgif', 'palette', 'imagegif' ),
|
||||
'image/jpeg' => array( 'imagecreatefromjpeg', 'truecolor',
|
||||
'image/gif' => array( 'imagecreatefromgif', 'palette', false, 'imagegif' ),
|
||||
'image/jpeg' => array( 'imagecreatefromjpeg', 'truecolor', true,
|
||||
array( __CLASS__, 'imageJpegWrapper' ) ),
|
||||
'image/png' => array( 'imagecreatefrompng', 'bits', 'imagepng' ),
|
||||
'image/vnd.wap.wbmp' => array( 'imagecreatefromwbmp', 'palette', 'imagewbmp' ),
|
||||
'image/xbm' => array( 'imagecreatefromxbm', 'palette', 'imagexbm' ),
|
||||
'image/png' => array( 'imagecreatefrompng', 'bits', false, 'imagepng' ),
|
||||
'image/vnd.wap.wbmp' => array( 'imagecreatefromwbmp', 'palette', false, 'imagewbmp' ),
|
||||
'image/xbm' => array( 'imagecreatefromxbm', 'palette', false, 'imagexbm' ),
|
||||
);
|
||||
|
||||
if ( !isset( $typemap[$params['mimeType']] ) ) {
|
||||
$err = 'Image type not supported';
|
||||
wfDebug( "$err\n" );
|
||||
|
|
@ -545,7 +557,7 @@ class BitmapHandler extends ImageHandler {
|
|||
|
||||
return $this->getMediaTransformError( $params, $errMsg );
|
||||
}
|
||||
list( $loader, $colorStyle, $saveType ) = $typemap[$params['mimeType']];
|
||||
list( $loader, $colorStyle, $useQuality, $saveType ) = $typemap[$params['mimeType']];
|
||||
|
||||
if ( !function_exists( $loader ) ) {
|
||||
$err = "Incomplete GD library configuration: missing function $loader";
|
||||
|
|
@ -597,7 +609,12 @@ class BitmapHandler extends ImageHandler {
|
|||
|
||||
imagesavealpha( $dst_image, true );
|
||||
|
||||
call_user_func( $saveType, $dst_image, $params['dstPath'] );
|
||||
$funcParams = array( $dst_image, $params['dstPath'] );
|
||||
if ( $useQuality && isset( $params['quality'] ) ) {
|
||||
$funcParams[] = $params['quality'];
|
||||
}
|
||||
call_user_func_array( $saveType, $funcParams );
|
||||
|
||||
imagedestroy( $dst_image );
|
||||
imagedestroy( $src_image );
|
||||
|
||||
|
|
@ -730,9 +747,10 @@ class BitmapHandler extends ImageHandler {
|
|||
return $cache;
|
||||
}
|
||||
|
||||
static function imageJpegWrapper( $dst_image, $thumbPath ) {
|
||||
// FIXME: transformImageMagick() & transformImageMagickExt() uses JPEG quality 80, here it's 95?
|
||||
static function imageJpegWrapper( $dst_image, $thumbPath, $quality = 95 ) {
|
||||
imageinterlace( $dst_image );
|
||||
imagejpeg( $dst_image, $thumbPath, 95 );
|
||||
imagejpeg( $dst_image, $thumbPath, $quality );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -31,6 +31,71 @@
|
|||
* @ingroup Media
|
||||
*/
|
||||
class JpegHandler extends ExifBitmapHandler {
|
||||
|
||||
function normaliseParams( $image, &$params ) {
|
||||
if ( !parent::normaliseParams( $image, $params ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( isset( $params['quality'] ) && !self::validateQuality( $params['quality'] ) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function validateParam( $name, $value ) {
|
||||
if ( $name === 'quality' ) {
|
||||
return self::validateQuality( $value );
|
||||
} else {
|
||||
return parent::validateParam( $name, $value );
|
||||
}
|
||||
}
|
||||
|
||||
/** Validate and normalize quality value to be between 1 and 100 (inclusive).
|
||||
* @param int $value quality value, will be converted to integer or 0 if invalid
|
||||
* @return bool true if the value is valid
|
||||
*/
|
||||
private static function validateQuality( $value ) {
|
||||
return $value === 'low';
|
||||
}
|
||||
|
||||
function makeParamString( $params ) {
|
||||
// Prepend quality as "qValue-". This has to match parseParamString() below
|
||||
$res = parent::makeParamString( $params );
|
||||
if ( $res && isset( $params['quality'] ) ) {
|
||||
$res = "q{$params['quality']}-$res";
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
function parseParamString( $str ) {
|
||||
// $str contains "qlow-200px" or "200px" strings because thumb.php would strip the filename
|
||||
// first - check if the string begins with "qlow-", and if so, treat it as quality.
|
||||
// Pass the first portion, or the whole string if "qlow-" not found, to the parent
|
||||
// The parsing must match the makeParamString() above
|
||||
$res = false;
|
||||
$m = false;
|
||||
if ( preg_match( '/q([^-]+)-(.*)$/', $str, $m ) ) {
|
||||
$v = $m[1];
|
||||
if ( self::validateQuality( $v ) ) {
|
||||
$res = parent::parseParamString( $m[2] );
|
||||
if ( $res ) {
|
||||
$res['quality'] = $v;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$res = parent::parseParamString( $str );
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
function getScriptParams( $params ) {
|
||||
$res = parent::getScriptParams( $params );
|
||||
if ( isset( $params['quality'] ) ) {
|
||||
$res['quality'] = $params['quality'];
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
function getMetadata( $image, $filename ) {
|
||||
try {
|
||||
$meta = BitmapMetadataHandler::Jpeg( $filename );
|
||||
|
|
|
|||
Loading…
Reference in a new issue