r84281 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r84280‎ | r84281 | r84282 >
Date:22:46, 18 March 2011
Author:btongminh
Status:deferred (Comments)
Tags:
Comment:
(bug 25990) Add VIPS scaling. VIPS is a set of image manipulation tools specially designed for speed and low memory usage. This is useful for resizing large PNGS.
The extension shells out to the vips binary. It be configured to scale only certain files (for example: big PNGs) by configuring $wgVipsConditions.

Currently not very useable on WMF though because vips has a bug with palette based images, which I reported upstream but has not yet been fixed.
Modified paths:
  • /trunk/extensions/VipsScaler/VipsScaler.i18n.php (added) (history)
  • /trunk/extensions/VipsScaler/VipsScaler.php (added) (history)
  • /trunk/extensions/VipsScaler/VipsScaler_body.php (added) (history)

Diff [purge]

Index: trunk/extensions/VipsScaler/VipsScaler.i18n.php
@@ -0,0 +1,5 @@
 2+<?php
 3+$messages = array();
 4+$messages['en'] = array(
 5+ 'vipsscaler-desc' => 'Create thumbnails using VIPS.'
 6+);
\ No newline at end of file
Property changes on: trunk/extensions/VipsScaler/VipsScaler.i18n.php
___________________________________________________________________
Added: svn:eol-style
17 + native
Index: trunk/extensions/VipsScaler/VipsScaler.php
@@ -0,0 +1,38 @@
 2+<?php
 3+/**
 4+ * Copyright © Bryan Tong Minh, 2011
 5+ *
 6+ * This program is free software; you can redistribute it and/or modify
 7+ * it under the terms of the GNU General Public License as published by
 8+ * the Free Software Foundation; either version 2 of the License, or
 9+ * (at your option) any later version.
 10+ *
 11+ * This program is distributed in the hope that it will be useful,
 12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 14+ * GNU General Public License for more details.
 15+ *
 16+ * You should have received a copy of the GNU General Public License along
 17+ * with this program; if not, write to the Free Software Foundation, Inc.,
 18+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 19+ * http://www.gnu.org/copyleft/gpl.html
 20+ */
 21+
 22+$wgExtensionCredits['media'][] = array(
 23+ 'path' => __FILE__,
 24+ 'name' => 'VipsScaler',
 25+ 'author' => array( 'Bryan Tong Minh' ),
 26+ 'descriptionmsg' => 'vipsscaler-desc',
 27+ 'url' => 'http://www.mediawiki.org/wiki/VipsScaler',
 28+);
 29+
 30+$dir = dirname( __FILE__ );
 31+
 32+$wgAutoloadClasses['VipsScaler'] = "$dir/VipsScaler_body.php";
 33+$wgExtensionMessagesFiles['VipsScaler'] = "$dir/VipsScaler.i18n.php";
 34+
 35+$wgHooks['BitmapHandlerTransform'][] = 'VipsScaler::onTransform';
 36+
 37+# Download vips from http://www.vips.ecs.soton.ac.uk/
 38+$wgVipsCommand = 'vips';
 39+$wgVipsConditions = array();
Property changes on: trunk/extensions/VipsScaler/VipsScaler.php
___________________________________________________________________
Added: svn:eol-style
140 + native
Index: trunk/extensions/VipsScaler/VipsScaler_body.php
@@ -0,0 +1,154 @@
 2+<?php
 3+class VipsScaler {
 4+ /**
 5+ * Hook to BitmapHandlerTransform. Transforms the file using VIPS if it
 6+ * matches a condition in $wgVipsConditions
 7+ *
 8+ * @param BitmapHandler $handler
 9+ * @param File $file
 10+ * @param array $params
 11+ * @param MediaTransformOutput $mto
 12+ */
 13+ public static function onTransform( $handler, $file, &$params, &$mto ) {
 14+ # Check $wgVipsConditions
 15+ if ( !self::shouldHandle( $handler, $file, $params ) ) {
 16+ return true;
 17+ }
 18+
 19+ # Get the proper im_XXX2vips handler
 20+ $vipsHandler = self::getVipsHandler( $file );
 21+ if ( !$vipsHandler ) {
 22+ return true;
 23+ }
 24+
 25+ # Get a temporary file with .v extension
 26+ $tmp = self::makeTempV();
 27+ # Convert the source image to a .v file
 28+ list( $err, $retval ) = self::vips( $vipsHandler, $params['srcPath'], $tmp );
 29+ if ( $retval != 0 ) {
 30+ wfDebug( __METHOD__ . ": $vipsHandler failed!\n" );
 31+ unlink( $tmp );
 32+ $mto = $handler->getMediaTransformError( $params, $err );
 33+ return false;
 34+ }
 35+
 36+ # Rotate if necessary
 37+ $rotation = 360 - $handler->getRotation( $file );
 38+ if ( $rotation % 360 != 0 && $rotation % 90 == 0 ) {
 39+ $tmp2 = self::makeTempV();
 40+
 41+ list( $err, $retval ) = self::vips( "im_rot{$rotation}", $tmp, $tmp2 );
 42+ unlink( $tmp );
 43+ if ( $retval != 0 ) {
 44+ unlink( $tmp2 );
 45+ $mto = $handler->getMediaTransformError( $params, $err );
 46+ return false;
 47+ }
 48+
 49+ # Set the new rotated file
 50+ $tmp = $tmp2;
 51+ }
 52+
 53+ # Scale the image to the final output
 54+ list( $err, $retval ) = self::vips( 'im_resize_linear', $tmp,
 55+ $params['dstPath'], $params['physicalWidth'], $params['physicalHeight'] );
 56+ # Remove the temp file
 57+ unlink( $tmp );
 58+ if ( $retval != 0 ) {
 59+ $mto = $handler->getMediaTransformError( $params, $err );
 60+ return false;
 61+ }
 62+
 63+ # Set the output variable
 64+ $mto = new ThumbnailImage( $file, $params['dstUrl'],
 65+ $params['clientWidth'], $params['clientHeight'], $params['dstPath'] );
 66+
 67+ # Stop processing
 68+ return false;
 69+
 70+ }
 71+
 72+ /**
 73+ * Call the vips binary with varargs and returns the error output and
 74+ * return value.
 75+ *
 76+ * @param varargs
 77+ * @return array
 78+ */
 79+ protected static function vips( /* varargs */ ) {
 80+ global $wgVipsCommand;
 81+
 82+ $args = func_get_args();
 83+ $cmd = wfEscapeShellArg( $wgVipsCommand );
 84+ foreach ( $args as $arg ) {
 85+ $cmd .= ' ' . wfEscapeShellArg( $arg );
 86+ }
 87+
 88+ $retval = 0;
 89+ $err = wfShellExec( $cmd, $retval );
 90+ return array( $err, $retval );
 91+ }
 92+
 93+ /**
 94+ * Check the file and params against $wgVipsConditions
 95+ *
 96+ * @param BitmapHandler $handler
 97+ * @param File $file
 98+ * @param array $params
 99+ * @return bool
 100+ */
 101+ protected static function shouldHandle( $handler, $file, $params ) {
 102+ global $wgVipsConditions;
 103+ # Iterate over conditions
 104+ foreach ( $wgVipsConditions as $condition ) {
 105+ if ( isset( $condition['mimeType'] ) &&
 106+ $file->getMimeType() != $condition['mimeType'] ) {
 107+ continue;
 108+ }
 109+ $area = $handler->getImageArea( $file, $params['srcWidth'], $params['srcHeight'] );
 110+ if ( isset( $condition['minArea'] ) && $area < $condition['minArea'] ) {
 111+ continue;
 112+ }
 113+ if ( isset( $condition['maxArea'] ) && $area > $condition['maxArea'] ) {
 114+ continue;
 115+ }
 116+
 117+ # This condition passed
 118+ return true;
 119+ }
 120+ # All conditions failed
 121+ return false;
 122+ }
 123+
 124+ /**
 125+ * Return the appropriate im_XXX2vips handler for this file
 126+ * @param File $file
 127+ * @return mixed String or false
 128+ */
 129+ protected static function getVipsHandler( $file ) {
 130+ list( $major, $minor ) = File::splitMime( $file->getMimeType() );
 131+
 132+ if ( $major == 'image' && in_array( $minor, array( 'jpeg', 'png', 'tiff' ) ) ) {
 133+ return "im_{$minor}2vips";
 134+ } else {
 135+ return false;
 136+ }
 137+ }
 138+
 139+ /**
 140+ * Generate a random, non-existent temporary file with a .v extension.
 141+ *
 142+ * @return string
 143+ */
 144+ protected static function makeTempV() {
 145+ do {
 146+ # Generate a random file
 147+ $fileName = wfTempDir() . DIRECTORY_SEPARATOR .
 148+ dechex( mt_rand() ) . dechex( mt_rand() ) . '.v';
 149+ } while ( file_exists( $fileName ) );
 150+ # Create the file
 151+ touch( $fileName );
 152+
 153+ return $fileName;
 154+ }
 155+}
\ No newline at end of file
Property changes on: trunk/extensions/VipsScaler/VipsScaler_body.php
___________________________________________________________________
Added: svn:eol-style
1156 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r84635VipsHandler: Fix target width by offsetting the file dimensions per bug 25990#c7btongminh21:42, 23 March 2011

Comments

#Comment by P858snake (talk | contribs)   03:06, 22 April 2011

VipsScaler.php:

+	'url' => '[http://www.mediawiki.org/wiki/VipsScaler', http://www.mediawiki.org/wiki/VipsScaler',]

Really should point to http://www.mediawiki.org/wiki/Extension:VipsScaler, yes we can do mainspace redirects but that is just messy.

Also this should be documented and created on mw wiki.

Status & tagging log