From 9a3b3dd0248590192174f57935ceb48298c9c555 Mon Sep 17 00:00:00 2001 From: Bryan Tong Minh Date: Sat, 12 Mar 2011 19:59:41 +0000 Subject: [PATCH] (bug 18691) Added support for SVG rasterization using the Imagick PHP extension. Based on patch by Yesid Carrillo. Set $wgSVGConverter = 'ImagickExt' to use it. Note that the results are extremely ugly, but I believe that happens with the command line scaler as well. Introduced new syntax for $wgSVGConverters, if the selected converter is an array, it is assumed to be a PHP callable. Imagick support is done by SvgHandler::rasterizeImagickExt. --- CREDITS | 1 + RELEASE-NOTES | 2 ++ includes/DefaultSettings.php | 3 ++ includes/media/SVG.php | 53 +++++++++++++++++++++++++++--------- 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/CREDITS b/CREDITS index 463b744a75..55448c867b 100644 --- a/CREDITS +++ b/CREDITS @@ -65,6 +65,7 @@ following names for their contribution to the product. * Tom Gries * Trevor Parscal * Victor Vasiliev +* Yesid Carrillo * Yuri Astrakhan == Patch Contributors == diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 7cd82ef34a..4671c9e043 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -103,6 +103,8 @@ PHP if you have not done so prior to upgrading MediaWiki. * When $wgAllowMicrodataAttributes is true, all itemtypes are allowed, not just the three that were defined in the original specification. * (bug 14706) Added support for the Imagick PHP extension. +* (bug 18691) Added support for SVG rasterization using the Imagick PHP + extension === Bug fixes in 1.18 === * (bug 23119) WikiError class and subclasses are now marked as deprecated diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index a4da8a4da7..7e9a3553bc 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -660,6 +660,8 @@ $wgCustomConvertCommand = false; * necessary to rasterize SVGs to PNG as a fallback format. * * An external program is required to perform this conversion. + * If set to an array, the first item is a PHP callable and any further items + * are passed as parameters after $srcPath, $dstPath, $width, $height */ $wgSVGConverters = array( 'ImageMagick' => '$path/convert -background white -thumbnail $widthx$height\! $input PNG:$output', @@ -668,6 +670,7 @@ $wgSVGConverters = array( 'batik' => 'java -Djava.awt.headless=true -jar $path/batik-rasterizer.jar -w $width -d $output $input', 'rsvg' => '$path/rsvg -w$width -h$height $input $output', 'imgserv' => '$path/imgserv-wrapper -i svg -o png -w$width $input $output', + 'ImagickExt' => array( 'SvgHandler::rasterizeImagickExt' ), ); /** Pick a converter defined in $wgSVGConverters */ $wgSVGConverter = 'ImageMagick'; diff --git a/includes/media/SVG.php b/includes/media/SVG.php index d425b9496d..57a96683c0 100644 --- a/includes/media/SVG.php +++ b/includes/media/SVG.php @@ -119,19 +119,32 @@ class SvgHandler extends ImageHandler { $err = false; $retval = ''; if ( isset( $wgSVGConverters[$wgSVGConverter] ) ) { - $cmd = str_replace( - array( '$path/', '$width', '$height', '$input', '$output' ), - array( $wgSVGConverterPath ? wfEscapeShellArg( "$wgSVGConverterPath/" ) : "", - intval( $width ), - intval( $height ), - wfEscapeShellArg( $srcPath ), - wfEscapeShellArg( $dstPath ) ), - $wgSVGConverters[$wgSVGConverter] - ) . " 2>&1"; - wfProfileIn( 'rsvg' ); - wfDebug( __METHOD__.": $cmd\n" ); - $err = wfShellExec( $cmd, $retval ); - wfProfileOut( 'rsvg' ); + if ( is_array( $wgSVGConverters[$wgSVGConverter] ) ) { + // This is a PHP callable + $func = $wgSVGConverters[$wgSVGConverter][0]; + $args = array_merge( array( $srcPath, $dstPath, $width, $height ), + array_slice( $wgSVGConverters[$wgSVGConverter], 1 ) ); + if ( !is_callable( $func ) ) { + throw new MWException( "$func is not callable" ); + } + $err = call_user_func_array( $func, $args ); + $retval = (bool)$err; + } else { + // External command + $cmd = str_replace( + array( '$path/', '$width', '$height', '$input', '$output' ), + array( $wgSVGConverterPath ? wfEscapeShellArg( "$wgSVGConverterPath/" ) : "", + intval( $width ), + intval( $height ), + wfEscapeShellArg( $srcPath ), + wfEscapeShellArg( $dstPath ) ), + $wgSVGConverters[$wgSVGConverter] + ) . " 2>&1"; + wfProfileIn( 'rsvg' ); + wfDebug( __METHOD__.": $cmd\n" ); + $err = wfShellExec( $cmd, $retval ); + wfProfileOut( 'rsvg' ); + } } $removed = $this->removeBadFile( $dstPath, $retval ); if ( $retval != 0 || $removed ) { @@ -141,6 +154,20 @@ class SvgHandler extends ImageHandler { } return true; } + + public static function rasterizeImagickExt( $srcPath, $dstPath, $width, $height ) { + $im = new Imagick( $srcPath ); + $im->setImageFormat( 'png' ); + $im->setBackgroundColor( 'transparent' ); + $im->setImageDepth( 8 ); + + if ( !$im->thumbnailImage( intval( $width ), intval( $height ), /* fit */ false ) ) { + return 'Could not resize image'; + } + if ( !$im->writeImage( $dstPath ) ) { + return "Could not write to $dstPath"; + } + } /** * @param $file File -- 2.20.1