From 7f7e79022bfd421e49084b089e74c7a16b77bc03 Mon Sep 17 00:00:00 2001 From: Jens Frank Date: Sun, 13 Aug 2006 17:34:48 +0000 Subject: [PATCH] (bug 6420) Render thumbnails for djvu images, show multipage preview on image page --- RELEASE-NOTES | 3 + includes/DefaultSettings.php | 20 +++ includes/DjVuImage.php | 18 ++- includes/Image.php | 261 +++++++++++++++++++++++------------ includes/ImageGallery.php | 4 +- includes/ImagePage.php | 50 +++++++ includes/Linker.php | 14 +- includes/MimeMagic.php | 9 ++ includes/Parser.php | 8 +- languages/MessagesDe.php | 8 ++ skins/common/common.css | 24 +++- skins/monobook/main.css | 21 +++ thumb.php | 16 +++ 13 files changed, 355 insertions(+), 101 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index cbfc67f4c0..0cb4b87399 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -26,6 +26,9 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN == Major new features == * (bug 550) Allow blocks on anonymous users only. +* (bug 6420) Render thumbnails for DJVU images, support multipage DJVU display + on image pages. Added new 'page=' thumbnail option to select a page from a + multipage djvu for thumbnail generation. == Changes since 1.7 == diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 8cd5f7d01b..57bf270f1c 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -2186,4 +2186,24 @@ $wgContentNamespaces = array( NS_MAIN ); */ $wgMaxShellMemory = 102400; +/** + * DJVU settings + * Path of the djvutoxml executable + * Enable this and $wgDjvuRenderer to enable djvu rendering + */ +# $wgDjvuToXML = 'djvutoxml'; + +/** + * Path of the ddjvu DJVU renderer + * Enable this and $wgDjvuToXML to enable djvu rendering + */ +# $wgDjvuRenderer = 'ddjvu'; + +/** + * Path of the DJVU post processor + * May include command line options + * Default: ppmtojpeg, since ddjvu generates ppm output + */ +$wgDjvuPostProcessor = 'ppmtojpeg'; + ?> diff --git a/includes/DjVuImage.php b/includes/DjVuImage.php index b857fa66f5..871c563bf8 100644 --- a/includes/DjVuImage.php +++ b/includes/DjVuImage.php @@ -208,7 +208,23 @@ class DjVuImage { 'resolution' => $resolution, 'gamma' => $gamma / 10.0 ); } + + /** + * Return an XML string describing the DjVu image + * @return string + */ + function retrieveMetaData() { + global $wgDjvuToXML; + if ( isset( $wgDjvuToXML ) ) { + $cmd = $wgDjvuToXML . ' --without-anno --without-text ' . $this->mFilename; + $xml = wfShellExec( $cmd, $retval ); + } else { + $xml = null; + } + return $xml; + } + } -?> \ No newline at end of file +?> diff --git a/includes/Image.php b/includes/Image.php index c52411ee41..39268ab8f1 100644 --- a/includes/Image.php +++ b/includes/Image.php @@ -46,6 +46,7 @@ class Image $size, # Size in bytes (loadFromXxx) $metadata, # Metadata $dataLoaded, # Whether or not all this has been loaded from the database (loadFromXxx) + $page, # Page to render when creating thumbnails $lastError; # Error string associated with a thumbnail display error @@ -86,6 +87,7 @@ class Image $this->extension = Image::normalizeExtension( $n ? substr( $this->name, $n + 1 ) : '' ); $this->historyLine = 0; + $this->page = 1; $this->dataLoaded = false; } @@ -307,7 +309,11 @@ class Image $this->dataLoaded = true; - $this->metadata = serialize( $this->retrieveExifData( $this->imagePath ) ); + if ( $this->mime == 'image/vnd.djvu' ) { + $this->metadata = $deja->retrieveMetaData(); + } else { + $this->metadata = serialize( $this->retrieveExifData( $this->imagePath ) ); + } if ( isset( $gis['bits'] ) ) $this->bits = $gis['bits']; else $this->bits = 0; @@ -323,7 +329,6 @@ class Image wfProfileIn( __METHOD__ ); $dbr =& wfGetDB( DB_SLAVE ); - $this->checkDBSchema($dbr); $row = $dbr->selectRow( 'image', @@ -605,7 +610,7 @@ class Image * @todo remember the result of this check. */ function canRender() { - global $wgUseImageMagick; + global $wgUseImageMagick, $wgDjvuRenderer; if( $this->getWidth()<=0 || $this->getHeight()<=0 ) return false; @@ -651,6 +656,7 @@ class Image if ( $mime === 'image/vnd.wap.wbmp' || $mime === 'image/x-xbitmap' ) return true; } + if ( $mime === 'image/vnd.djvu' && isset( $wgDjvuRenderer ) && $wgDjvuRenderer ) return true; return false; } @@ -738,9 +744,16 @@ class Image * Return the escapeLocalURL of this image * @public */ - function getEscapeLocalURL() { + function getEscapeLocalURL( $query=false) { $this->getTitle(); - return $this->title->escapeLocalURL(); + if ( $query === false ) { + if ( $this->page != 1 ) { + $query = 'page=' . $this->page; + } else { + $query = ''; + } + } + return $this->title->escapeLocalURL( $query ); } /** @@ -840,6 +853,9 @@ class Image */ function thumbName( $width ) { $thumb = $width."px-".$this->name; + if ( $this->page != 1 ) { + $thumb = "page{$this->page}-$thumb"; + } if( $this->mustRender() ) { if( $this->canRender() ) { @@ -1127,6 +1143,7 @@ class Image global $wgSVGConverters, $wgSVGConverter; global $wgUseImageMagick, $wgImageMagickConvertCommand; global $wgCustomConvertCommand; + global $wgDjvuRenderer, $wgDjvuPostProcessor; $this->load(); @@ -1153,96 +1170,112 @@ class Image $err = wfShellExec( $cmd, $retval ); wfProfileOut( 'rsvg' ); } - } elseif ( $wgUseImageMagick ) { - # use ImageMagick - - if ( $this->mime == 'image/jpeg' ) { - $quality = "-quality 80"; // 80% - } elseif ( $this->mime == 'image/png' ) { - $quality = "-quality 95"; // zlib 9, adaptive filtering - } else { - $quality = ''; // default - } - - # Specify white background color, will be used for transparent images - # in Internet Explorer/Windows instead of default black. - - # Note, we specify "-size {$width}" and NOT "-size {$width}x{$height}". - # It seems that ImageMagick has a bug wherein it produces thumbnails of - # the wrong size in the second case. - - $cmd = wfEscapeShellArg($wgImageMagickConvertCommand) . - " {$quality} -background white -size {$width} ". - wfEscapeShellArg($this->imagePath) . - // Coalesce is needed to scale animated GIFs properly (bug 1017). - ' -coalesce ' . - // For the -resize option a "!" is needed to force exact size, - // or ImageMagick may decide your ratio is wrong and slice off - // a pixel. - " -resize " . wfEscapeShellArg( "{$width}x{$height}!" ) . - " -depth 8 " . - wfEscapeShellArg($thumbPath) . " 2>&1"; - wfDebug("reallyRenderThumb: running ImageMagick: $cmd\n"); - wfProfileIn( 'convert' ); - $err = wfShellExec( $cmd, $retval ); - wfProfileOut( 'convert' ); - } elseif( $wgCustomConvertCommand ) { - # Use a custom convert command - # Variables: %s %d %w %h - $src = wfEscapeShellArg( $this->imagePath ); - $dst = wfEscapeShellArg( $thumbPath ); - $cmd = $wgCustomConvertCommand; - $cmd = str_replace( '%s', $src, str_replace( '%d', $dst, $cmd ) ); # Filenames - $cmd = str_replace( '%h', $height, str_replace( '%w', $width, $cmd ) ); # Size - wfDebug( "reallyRenderThumb: Running custom convert command $cmd\n" ); - wfProfileIn( 'convert' ); - $err = wfShellExec( $cmd, $retval ); - wfProfileOut( 'convert' ); } else { - # 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 = array( - 'image/gif' => array( 'imagecreatefromgif', 'palette', 'imagegif' ), - 'image/jpeg' => array( 'imagecreatefromjpeg', 'truecolor', array( &$this, 'imageJpegWrapper' ) ), - 'image/png' => array( 'imagecreatefrompng', 'bits', 'imagepng' ), - 'image/vnd.wap.wmbp' => array( 'imagecreatefromwbmp', 'palette', 'imagewbmp' ), - 'image/xbm' => array( 'imagecreatefromxbm', 'palette', 'imagexbm' ), - ); - if( !isset( $typemap[$this->mime] ) ) { - $err = 'Image type not supported'; - wfDebug( "$err\n" ); - return $err; - } - list( $loader, $colorStyle, $saveType ) = $typemap[$this->mime]; + if ( $this->mime === "image/vnd.djvu" && $wgDjvuRenderer ) { + // DJVU image + // The file contains several images. First, extract the + // page in hi-res, if it doesn't yet exist. Then, thumbnail + // it. + + $cmd = "{$wgDjvuRenderer} -page={$this->page} -size=${width}x${height} " . + wfEscapeShellArg( $this->imagePath ) . + " | {$wgDjvuPostProcessor} > " . wfEscapeShellArg($thumbPath); + wfProfileIn( 'ddjvu' ); + wfDebug( "reallyRenderThumb DJVU: $cmd\n" ); + $err = wfShellExec( $cmd, $retval ); + wfProfileOut( 'ddjvu' ); - if( !function_exists( $loader ) ) { - $err = "Incomplete GD library configuration: missing function $loader"; - wfDebug( "$err\n" ); - return $err; - } - if( $colorStyle == 'palette' ) { - $truecolor = false; - } elseif( $colorStyle == 'truecolor' ) { - $truecolor = true; - } elseif( $colorStyle == 'bits' ) { - $truecolor = ( $this->bits > 8 ); - } + } elseif ( $wgUseImageMagick ) { + # use ImageMagick + + if ( $this->mime == 'image/jpeg' ) { + $quality = "-quality 80"; // 80% + } elseif ( $this->mime == 'image/png' ) { + $quality = "-quality 95"; // zlib 9, adaptive filtering + } else { + $quality = ''; // default + } - $src_image = call_user_func( $loader, $this->imagePath ); - if ( $truecolor ) { - $dst_image = imagecreatetruecolor( $width, $height ); + # Specify white background color, will be used for transparent images + # in Internet Explorer/Windows instead of default black. + + # Note, we specify "-size {$width}" and NOT "-size {$width}x{$height}". + # It seems that ImageMagick has a bug wherein it produces thumbnails of + # the wrong size in the second case. + + $cmd = wfEscapeShellArg($wgImageMagickConvertCommand) . + " {$quality} -background white -size {$width} ". + wfEscapeShellArg($this->imagePath) . + // Coalesce is needed to scale animated GIFs properly (bug 1017). + ' -coalesce ' . + // For the -resize option a "!" is needed to force exact size, + // or ImageMagick may decide your ratio is wrong and slice off + // a pixel. + " -resize " . wfEscapeShellArg( "{$width}x{$height}!" ) . + " -depth 8 " . + wfEscapeShellArg($thumbPath) . " 2>&1"; + wfDebug("reallyRenderThumb: running ImageMagick: $cmd\n"); + wfProfileIn( 'convert' ); + $err = wfShellExec( $cmd, $retval ); + wfProfileOut( 'convert' ); + } elseif( $wgCustomConvertCommand ) { + # Use a custom convert command + # Variables: %s %d %w %h + $src = wfEscapeShellArg( $this->imagePath ); + $dst = wfEscapeShellArg( $thumbPath ); + $cmd = $wgCustomConvertCommand; + $cmd = str_replace( '%s', $src, str_replace( '%d', $dst, $cmd ) ); # Filenames + $cmd = str_replace( '%h', $height, str_replace( '%w', $width, $cmd ) ); # Size + wfDebug( "reallyRenderThumb: Running custom convert command $cmd\n" ); + wfProfileIn( 'convert' ); + $err = wfShellExec( $cmd, $retval ); + wfProfileOut( 'convert' ); } else { - $dst_image = imagecreate( $width, $height ); + # 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 = array( + 'image/gif' => array( 'imagecreatefromgif', 'palette', 'imagegif' ), + 'image/jpeg' => array( 'imagecreatefromjpeg', 'truecolor', array( &$this, 'imageJpegWrapper' ) ), + 'image/png' => array( 'imagecreatefrompng', 'bits', 'imagepng' ), + 'image/vnd.wap.wmbp' => array( 'imagecreatefromwbmp', 'palette', 'imagewbmp' ), + 'image/xbm' => array( 'imagecreatefromxbm', 'palette', 'imagexbm' ), + ); + if( !isset( $typemap[$this->mime] ) ) { + $err = 'Image type not supported'; + wfDebug( "$err\n" ); + return $err; + } + list( $loader, $colorStyle, $saveType ) = $typemap[$this->mime]; + + if( !function_exists( $loader ) ) { + $err = "Incomplete GD library configuration: missing function $loader"; + wfDebug( "$err\n" ); + return $err; + } + if( $colorStyle == 'palette' ) { + $truecolor = false; + } elseif( $colorStyle == 'truecolor' ) { + $truecolor = true; + } elseif( $colorStyle == 'bits' ) { + $truecolor = ( $this->bits > 8 ); + } + + $src_image = call_user_func( $loader, $this->imagePath ); + if ( $truecolor ) { + $dst_image = imagecreatetruecolor( $width, $height ); + } else { + $dst_image = imagecreate( $width, $height ); + } + imagecopyresampled( $dst_image, $src_image, + 0,0,0,0, + $width, $height, $this->width, $this->height ); + call_user_func( $saveType, $dst_image, $thumbPath ); + imagedestroy( $dst_image ); + imagedestroy( $src_image ); } - imagecopyresampled( $dst_image, $src_image, - 0,0,0,0, - $width, $height, $this->width, $this->height ); - call_user_func( $saveType, $dst_image, $thumbPath ); - imagedestroy( $dst_image ); - imagedestroy( $src_image ); } # @@ -1712,7 +1745,7 @@ class Image function getExifData() { global $wgRequest; - if ( $this->metadata === '0' ) + if ( $this->metadata === '0' || $this->mime == 'image/vnd.djvu' ) return array(); $purge = $wgRequest->getVal( 'action' ) == 'purge'; @@ -2210,6 +2243,52 @@ class Image return $revisions; } + + /** + * Select a page from a multipage document. Determines the page used for + * rendering thumbnails. + * + * @param $page Integer: page number, starting with 1 + */ + function selectPage( $page ) { + wfDebug( __METHOD__." selecting page $page \n" ); + $this->page = $page; + if ( ! $this->dataLoaded ) { + $this->load(); + } + if ( ! isset( $this->multiPageXML ) ) { + $this->multiPageXML = new SimpleXMLElement( $this->metadata ); + } + $o = $this->multiPageXML->BODY[0]->OBJECT[$page-1]; + $this->height = intval( $o['height'] ); + $this->width = intval( $o['width'] ); + wfDebug( __METHOD__." >>>>METADATA>>>>\n".$o->asXML() . "\n<<<<<<<\n\n" ); + wfDebug( __METHOD__." >>>>XML OBJECT>>>>\n". print_r($o,true) . "\n<<<<<<<\n\n" ); + } + + /** + * Returns 'true' if this image is a multipage document, e.g. a DJVU + * document. + * + * @return Bool + */ + function isMultipage() { + return ( $this->mime == 'image/vnd.djvu' ); + } + + /** + * Returns the number of pages of a multipage document, or NULL for + * documents which aren't multipage documents + */ + function pageCount() { + if ( ! $this->isMultipage() ) { + return null; + } + if ( ! isset( $this->multiPageXML ) ) { + $this->multiPageXML = new SimpleXMLElement( $this->metadata ); + } + return count( $this->multiPageXML->xpath( '//OBJECT' ) ); + } } //class diff --git a/includes/ImageGallery.php b/includes/ImageGallery.php index ae2e4a7098..7ff456b666 100644 --- a/includes/ImageGallery.php +++ b/includes/ImageGallery.php @@ -82,6 +82,7 @@ class ImageGallery */ function add( $image, $html='' ) { $this->mImages[] = array( &$image, $html ); + wfDebug( "ImageGallery::add " . $image->getName() . "\n" ); } /** @@ -157,8 +158,7 @@ class ImageGallery # The image is blacklisted, just show it as a text link. $thumbhtml = '
' . $sk->makeKnownLinkObj( $nt, htmlspecialchars( $nt->getText() ) ) . '
'; - } - else if( !( $thumb = $img->getThumbnail( 120, 120, $wgGenerateThumbnailOnParse ) ) ) { + } else if( !( $thumb = $img->getThumbnail( 120, 120, $wgGenerateThumbnailOnParse ) ) ) { # Error generating thumbnail. $thumbhtml = '
' . htmlspecialchars( $img->getLastError() ) . '
'; diff --git a/includes/ImagePage.php b/includes/ImagePage.php index 88a0a12ad3..440caea36d 100644 --- a/includes/ImagePage.php +++ b/includes/ImagePage.php @@ -187,6 +187,12 @@ class ImagePage extends Article { if ( $this->img->exists() ) { # image + $page = $wgRequest->getIntOrNull( 'page' ); + if ( ! is_null( $page ) ) { + $this->img->selectPage( $page ); + } else { + $page = 1; + } $width = $this->img->getWidth(); $height = $this->img->getHeight(); $showLink = false; @@ -236,9 +242,53 @@ class ImagePage extends Article { $url = $this->img->getViewURL(); $showLink = true; } + + if ( $this->img->isMultipage() ) { + $wgOut->addHTML( '
' ); + } + $wgOut->addHTML( '' ); + + if ( $this->img->isMultipage() ) { + $count = $this->img->pageCount(); + + if ( $page > 1 ) { + $label = $wgOut->parse( wfMsg( 'imgmultipageprev' ), false ); + $link = $sk->makeLinkObj( $this->mTitle, $label, 'page='. ($page-1) ); + $this->img->selectPage( $page - 1 ); + $thumb1 = $sk->makeThumbLinkObj( $this->img, $link, $label, 'none' ); + } else { + $thumb1 = ''; + } + + if ( $page < $count ) { + $label = wfMsg( 'imgmultipagenext' ); + $this->img->selectPage( $page + 1 ); + $link = $sk->makeLinkObj( $this->mTitle, $label, 'page='. ($page+1) ); + $thumb2 = $sk->makeThumbLinkObj( $this->img, $link, $label, 'none' ); + } else { + $thumb2 = ''; + } + + $select = '
' ; + $select .= $wgOut->parse( wfMsg( 'imgmultigotopre' ), false ) . + ' ' . $wgOut->parse( wfMsg( 'imgmultigotopost' ), false ) . + '
'; + + $wgOut->addHTML( '
' . + "$select
$thumb1\n$thumb2
" ); + } } else { #if direct link is allowed but it's not a renderable image, show an icon. if ($this->img->isSafeFile()) { diff --git a/includes/Linker.php b/includes/Linker.php index 6cc7976fbd..d34971fff9 100644 --- a/includes/Linker.php +++ b/includes/Linker.php @@ -456,11 +456,16 @@ class Linker { /** @todo document */ function makeImageLinkObj( $nt, $label, $alt, $align = '', $width = false, $height = false, $framed = false, - $thumb = false, $manual_thumb = '' ) + $thumb = false, $manual_thumb = '', $page = null ) { global $wgContLang, $wgUser, $wgThumbLimits, $wgGenerateThumbnailOnParse; $img = new Image( $nt ); + + if ( ! is_null( $page ) ) { + $img->selectPage( $page ); + } + if ( !$img->allowInlineDisplay() && $img->exists() ) { return $this->makeKnownLinkObj( $nt ); } @@ -468,7 +473,7 @@ class Linker { $url = $img->getViewURL(); $error = $prefix = $postfix = ''; - wfDebug( "makeImageLinkObj: '$width'x'$height'\n" ); + wfDebug( "makeImageLinkObj: '$width'x'$height', \"$label\"\n" ); if ( 'center' == $align ) { @@ -564,7 +569,6 @@ class Linker { */ function makeThumbLinkObj( $img, $label = '', $alt, $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) { global $wgStylePath, $wgContLang, $wgGenerateThumbnailOnParse; - $url = $img->getViewURL(); $thumbUrl = ''; $error = ''; @@ -583,7 +587,7 @@ class Linker { // Use image dimensions, don't scale $boxwidth = $width; $boxheight = $height; - $thumbUrl = $url; + $thumbUrl = $img->getViewURL(); } else { if ( $boxheight === false ) $boxheight = -1; @@ -626,7 +630,7 @@ class Linker { $s = "
"; if( $thumbUrl == '' ) { // Couldn't generate thumbnail? Scale the image client-side. - $thumbUrl = $url; + $thumbUrl = $img->getViewURL(); } if ( $error ) { $s .= htmlspecialchars( $error ); diff --git a/includes/MimeMagic.php b/includes/MimeMagic.php index 30861ba3ec..435ab5d9ec 100644 --- a/includes/MimeMagic.php +++ b/includes/MimeMagic.php @@ -504,6 +504,15 @@ class MimeMagic { # see http://www.php.net/manual/en/ref.mime-magic.php for details. $m= mime_content_type($file); + + if ( $m == 'text/plain' ) { + // mime_content_type sometimes considers DJVU files to be text/plain. + $deja = new DjVuImage( $file ); + if( $deja->isValid() ) { + wfDebug("$fname: (re)detected $file as image/vnd.djvu\n"); + $m = 'image/vnd.djvu'; + } + } } else wfDebug("$fname: no magic mime detector found!\n"); diff --git a/includes/Parser.php b/includes/Parser.php index ca08deb759..604cb44767 100644 --- a/includes/Parser.php +++ b/includes/Parser.php @@ -4086,9 +4086,11 @@ class Parser $mwWidth =& MagicWord::get( 'img_width' ); $mwCenter =& MagicWord::get( 'img_center' ); $mwFramed =& MagicWord::get( 'img_framed' ); + $mwPage =& MagicWord::get( 'img_page' ); $caption = ''; $width = $height = $framed = $thumb = false; + $page = null; $manual_thumb = '' ; foreach( $part as $key => $val ) { @@ -4098,6 +4100,9 @@ class Parser # use manually specified thumbnail $thumb=true; $manual_thumb = $match; + } elseif ( ! is_null( $match = $mwPage->matchVariableStartToEnd($val) ) ) { + # Select a page in a multipage document + $page = $match; } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) { # remember to set an alignment, don't render immediately $align = 'right'; @@ -4136,7 +4141,8 @@ class Parser # Linker does the rest $sk =& $this->mOptions->getSkin(); - return $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $width, $height, $framed, $thumb, $manual_thumb ); + return $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $width, $height, + $framed, $thumb, $manual_thumb, $page ); } /** diff --git a/languages/MessagesDe.php b/languages/MessagesDe.php index d4fc06ddb8..2ae0a9429e 100644 --- a/languages/MessagesDe.php +++ b/languages/MessagesDe.php @@ -1889,6 +1889,14 @@ ta[\'ca-nstab-category\'] = new Array(\'c\',\'Kategorieseite anzeigen\');', 'loginlanguagelabel' => 'Sprache: $1', + +# Multipage image navigation +'imgmultipageprev' => '← vorige Seite', +'imgmultipagenext' => 'nächste Seite →', +'imgmultigo' => 'OK', +'imgmultigotopre' => 'Gehe zu Seite', +'imgmultigotopost' => '', + ); diff --git a/skins/common/common.css b/skins/common/common.css index 09409fd6fa..c17396a6e0 100644 --- a/skins/common/common.css +++ b/skins/common/common.css @@ -383,4 +383,26 @@ table.collapsed tr.collapsable { table.gallery td.galleryheader { text-align: center; font-weight: bold; -} \ No newline at end of file +} + +div.multipageimagenavbox { + border: solid 1px silver; + padding: 4px; + margin: 1em; + -moz-border-radius: 6px; + background: #f0f0f0; +} + +div.multipageimagenavbox div.thumb { + border: none; + margin-left: 2em; + margin-right: 2em; +} + +div.multipageimagenavbox hr { + margin: 6px; +} + +table.multipageimage td { + text-align: center; +} diff --git a/skins/monobook/main.css b/skins/monobook/main.css index 5b5d0cdfc9..9ba74029a0 100644 --- a/skins/monobook/main.css +++ b/skins/monobook/main.css @@ -1444,3 +1444,24 @@ div#searchTarget ul li:before { content: "\00BB \0020"; } +div.multipageimagenavbox { + border: solid 1px silver; + padding: 4px; + margin: 1em; + -moz-border-radius: 6px; + background: #f0f0f0; +} + +div.multipageimagenavbox div.thumb { + border: none; + margin-left: 2em; + margin-right: 2em; +} + +div.multipageimagenavbox hr { + margin: 6px; +} + +table.multipageimage td { + text-align: center; +} diff --git a/thumb.php b/thumb.php index d4e561e69e..bc794ebfb4 100644 --- a/thumb.php +++ b/thumb.php @@ -17,13 +17,20 @@ require_once( 'Image.php' ); require_once( 'StreamFile.php' ); // Get input parameters +$p=null; if ( get_magic_quotes_gpc() ) { $fileName = stripslashes( $_REQUEST['f'] ); $width = stripslashes( $_REQUEST['w'] ); + if ( isset( $_REQUEST['p'] ) ) { // optional page number + $page = stripslashes( $_REQUEST['p'] ); + } } else { $fileName = $_REQUEST['f']; $width = $_REQUEST['w']; + if ( isset( $_REQUEST['p'] ) ) { // optional page number + $page = $_REQUEST['p'] ; + } } $pre_render= isset($_REQUEST['r']) && $_REQUEST['r']!="0"; @@ -31,12 +38,18 @@ $pre_render= isset($_REQUEST['r']) && $_REQUEST['r']!="0"; // Some basic input validation $width = intval( $width ); +if ( ! is_null( $page ) ) { + $page = intval( $page ); +} $fileName = strtr( $fileName, '\\/', '__' ); // Work out paths, carefully avoiding constructing an Image object because that won't work yet $imagePath = wfImageDir( $fileName ) . '/' . $fileName; $thumbName = "{$width}px-$fileName"; +if ( ! is_null( $page ) ) { + $thumbName = 'page' . $page . '-' . $thumbName; +} if ( $pre_render ) { $thumbName .= '.png'; } @@ -55,6 +68,9 @@ wfProfileIn( 'thumb.php-render' ); $img = Image::newFromName( $fileName ); if ( $img ) { + if ( ! is_null( $page ) ) { + $img->selectPage( $page ); + } $thumb = $img->renderThumb( $width, false ); } else { $thumb = false; -- 2.20.1