JeLuF's image resizing code
authorErik Moeller <erik@users.mediawiki.org>
Mon, 12 Jan 2004 00:55:01 +0000 (00:55 +0000)
committerErik Moeller <erik@users.mediawiki.org>
Mon, 12 Jan 2004 00:55:01 +0000 (00:55 +0000)
LocalSettings.sample
includes/GlobalFunctions.php
includes/ImagePage.php
includes/MagicWord.php
includes/Skin.php
languages/Language.php
stylesheets/cologneblue.css
stylesheets/nostalgia.css
stylesheets/wikistandard.css

index 67b1b4e..758631a 100644 (file)
@@ -38,6 +38,15 @@ $wgDBsqlpassword     = "sqlpass";
 $wgDBminWordLen                = 3;     # Match this to your MySQL fulltext
 $wgDBtransactions   = false; # Set to true if using InnoDB tables
 
+# This is the location of the convert program
+# from the ImageMagick toolbox. You need it for 
+# the image resizing functionality.
+#
+# Set $wgUseImageResize to true if you want to use this feature
+# 
+$wgUseImageResize              = false;
+$wgImageMagickConvertCommand    = "/usr/bin/convert";
+
 # Turn this on during database maintenance
 # $wgReadOnly = true;
 
index 63ad667..e945a31 100644 (file)
@@ -99,12 +99,43 @@ function wfImageUrl( $img )
        return wfUrlencode( $url );
 }
 
-function wfImageArchiveUrl( $name )
+function wfImagePath( $img )
+{
+       global $wgUploadDirectory;
+
+       $nt = Title::newFromText( $img );
+       if( !$nt ) return "";
+
+       $name = $nt->getDBkey();
+       $hash = md5( $name );
+
+       $url = "{$wgUploadDirectory}/" . $hash{0} . "/" .
+         substr( $hash, 0, 2 ) . "/{$name}";
+       return wfUrlencode( $url );
+}
+
+function wfThumbUrl( $img )
+{
+       global $wgUploadPath;
+
+       $nt = Title::newFromText( $img );
+       if( !$nt ) return "";
+
+       $name = $nt->getDBkey();
+       $hash = md5( $name );
+
+       $url = "{$wgUploadPath}/thumb/" . $hash{0} . "/" .
+         substr( $hash, 0, 2 ) . "/{$name}";
+       return wfUrlencode( $url );
+}
+
+
+function wfImageArchiveUrl( $name, $subdir="archive" )
 {
        global $wgUploadPath;
 
-       $hash = md5( substr( $name, 15) );
-       $url = "{$wgUploadPath}/archive/" . $hash{0} . "/" .
+       $hash = md5( $name );
+       $url = "{$wgUploadPath}/{$subdir}/" . $hash{0} . "/" .
          substr( $hash, 0, 2 ) . "/{$name}";
        return $url;
 }
@@ -429,13 +460,13 @@ function wfImageDir( $fname )
        return $dest;
 }
 
-function wfImageArchiveDir( $fname )
+function wfImageArchiveDir( $fname , $subdir="archive")
 {
        global $wgUploadDirectory;
 
        $hash = md5( $fname );
        $oldumask = umask(0);
-       $archive = "{$wgUploadDirectory}/archive";
+       $archive = "{$wgUploadDirectory}/{$subdir}";
        if ( ! is_dir( $archive ) ) { mkdir( $archive, 0777 ); }
        $archive .= "/" . $hash{0};
        if ( ! is_dir( $archive ) ) { mkdir( $archive, 0777 ); }
index 06f2927..c883bf7 100644 (file)
@@ -7,6 +7,10 @@
 class ImagePage extends Article {
 
        function view() {
+               if ( Namespace::getImage() == $this->mTitle->getNamespace() ) {
+                       $this->openShowImage();
+               }
+
                Article::view();
                
                # If the article we've just shown is in the "Image" namespace,
@@ -14,11 +18,40 @@ class ImagePage extends Article {
                # it describes.
 
                if ( Namespace::getImage() == $this->mTitle->getNamespace() ) {
+                       $this->closeShowImage();
                        $this->imageHistory();
                        $this->imageLinks();
                }
        }
+
+       function openShowImage()
+       {
+               global $wgOut, $wgUser;
+               $name = $this->mTitle->getText();
+               $path = wfImagePath( $name );
+               $url   = wfImageUrl( $name );
+               
+               list($width, $height, $type, $attr) = getimagesize( $path );
+
+               $sk = $wgUser->getSkin();
+
+               if ( $type != "" ) {
+                       # image
+                       $s .= "<center><img src=\"{$url}\" width=\"{$width}\" height=\"{$height}\"></center>";
+               } else {
+                       $s .= "<center>".$sk->makeMediaLink($name,"")."</center>";
+               }
+               $wgOut->AddHTML( $s );
+       }
        
+       function closeShowImage()
+       {
+               global $wgOut, $wgUser;
+               $sk = $wgUser->getSkin();
+               $s = "</center>";
+               $wgOut->AddHTML( $s );
+       }
+
        # If the page we've just displayed is in the "Image" namespace,
        # we follow it with an upload history of the image and its usage.
 
index f0ed86d..c8af12b 100644 (file)
@@ -26,6 +26,7 @@ class MagicWord {
                $this->mRegex = "";
                $this->mRegexStart = "";
                $this->mVariableRegex = "";
+               $this->mVariableStartToEndRegex = "";
                $this->mModified = false;
        }
 
@@ -59,6 +60,7 @@ class MagicWord {
                $this->mRegex = "/{$this->mBaseRegex}/{$case}";
                $this->mRegexStart = "/^{$this->mBaseRegex}/{$case}";
                $this->mVariableRegex = str_replace( "\\$1", "([A-Za-z0-9_\-]*)", $this->mRegex );
+               $this->mVariableStartToEndRegex = str_replace( "\\$1", "([A-Za-z0-9_\-]*)", "/^{$this->mBaseRegex}$/{$case}" );
        }
        
        # Gets a regex representing matching the word
@@ -79,7 +81,7 @@ class MagicWord {
                }
                return $this->mRegexStart;
        }
-       
+
        # regex without the slashes and what not
        function getBaseRegex()
        {
@@ -100,6 +102,22 @@ class MagicWord {
                return preg_match( $this->getRegexStart(), $text );
        }
 
+       # Returns NULL if there's no match, the value of $1 otherwise
+       # The return code is the matched string, if there's no variable
+       # part in the regex and the matched variable part ($1) if there
+       # is one.
+       function matchVariableStartToEnd( $text ) {
+               $matchcount = preg_match( $this->getVariableStartToEndRegex(), $text, $matches );
+               if ( $matchcount == 0 ) {
+                       return NULL;
+               } elseif ( count($matches) == 1 ) {
+                       return $matches[0];
+               } else {
+                       return $matches[1];
+               }
+       }
+
+
        # Returns true if the text matches the word, and alters the
        # input string, removing all instances of the word
        function matchAndRemove( &$text )
@@ -137,6 +155,15 @@ class MagicWord {
                return $this->mVariableRegex;
        }
 
+       # Matches the entire string, where $1 is a wildcard
+       function getVariableStartToEndRegex()
+       {
+               if ( $this->mVariableStartToEndRegex == "" ) {
+                       $this->initRegex();
+               } 
+               return $this->mVariableStartToEndRegex;
+       }
+
        # Accesses the synonym list directly
        function getSynonym( $i ) {
                return $this->mSynonyms[$i];
index f3a2474..4b1a81f 100644 (file)
@@ -1421,9 +1421,77 @@ class Skin {
        }
 
        function makeImageLinkObj( $nt, $alt = "" ) {
-               $link = $nt->getPrefixedURL();
-               $name = $nt->getDBKey();
-               $url = wfImageUrl( $name );
+               global $wgLang, $wgUseImageResize;
+               $link  = $nt->getPrefixedURL();
+               $name  = $nt->getDBKey();
+               $url   = wfImageUrl( $name );
+               $align = "";
+
+               if ( $wgUseImageResize ) {
+                       # Check if the alt text is of the form "options|alt text"
+                       # Options are:
+                       #  * thumbnail          make a thumbnail with enlarge-icon and caption, alignment depends on lang
+                       #  * left               no resizing, just left align. label is used for alt= only
+                       #  * right              same, but right aligned
+                       #  * none               same, but not aligned
+                       #  * ___px              scale to ___ pixels width, no aligning. e.g. use in taxobox
+       
+                       $part = explode( "|", $alt);
+       
+                       if ( count($part) > 1 ) {
+                               $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
+                               $mwLeft  =& MagicWord::get( MAG_IMG_LEFT );
+                               $mwRight =& MagicWord::get( MAG_IMG_RIGHT );
+                               $mwNone  =& MagicWord::get( MAG_IMG_NONE );
+                               $mwWidth =& MagicWord::get( MAG_IMG_WIDTH );
+                               $alt = $part[count($part)-1];
+       
+                               $thumb=false;
+       
+                               foreach( $part as $key => $val ) {
+                                       if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
+                                               $thumb=true;
+                                       } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
+                                               # remember to set an alignment, don't render immediately
+                                               $align = "right";
+                                       } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
+                                               # remember to set an alignment, don't render immediately
+                                               $align = "left";
+                                       } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
+                                               # remember to set an alignment, don't render immediately
+                                               $align = "none";
+                                       } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
+                                               # $match is the image width in pixels
+                                               $width = intval($match);
+                                       }
+                               }
+                       }
+       
+                       if ( $thumb ) {
+       
+                               # Create a thumbnail. Alignment depends on language
+                               # writing direction, # right aligned for left-to-right-
+                               # languages ("Western languages"), left-aligned
+                               # for right-to-left-languages ("Semitic languages")
+                               #
+                               # If  thumbnail width has not been provided, it is set
+                               # here to 180 pixels
+                               if ( $align == "" ) {
+                                       $align = $wgLang->isRTL() ? "left" : "right";
+                               }
+                               if ( ! isset($width) ) {
+                                       $width = 180;
+                               }
+                               return $this->makeThumbLinkObj( $nt, $alt, $align, $width );
+       
+                       } elseif ( isset($width) ) {
+                               
+                               # Create a resized image, without the additional thumbnail
+                               # features
+                               $url = $this->createThumb( $name, $width );
+                       }
+               } # endif $wgUseImageResize
+                       
                if ( empty( $alt ) ) {
                        $alt = preg_replace( '/\.(.+?)^/', '', $name );
                }
@@ -1432,6 +1500,63 @@ class Skin {
                $u = wfLocalUrlE( $link );
                $s = "<a href=\"{$u}\" class='image' title=\"{$alt}\">" .
                  "<img border=\"0\" src=\"{$url}\" alt=\"{$alt}\"></a>";
+               if ( "" != $align ) {
+                       $s = "<div class=\"float{$align}\">{$s}</div>";
+               }
+               return $s;
+       }
+
+       function createThumb( $name, $width ) {
+               global $wgUploadDirectory;
+               global $wgImageMagickConvertCommand;
+               $imgPath   = wfImagePath( $name );
+               $thumbName = $width."px-".$icon.$name;
+               $thumbPath = wfImageArchiveDir( $thumbName, "thumb" )."/".$thumbName;
+               $thumbUrl  = wfImageArchiveUrl( $thumbName, "thumb" );
+
+               if (     (! file_exists( $thumbPath )) 
+                    ||  ( filemtime($thumbPath) < filemtime($imgPath) ) ) {
+                       $cmd  =  $wgImageMagickConvertCommand .
+                                       " -quality 95 -geometry {$width}x ".
+                                       escapeshellarg($imgPath) . " " .
+                                       escapeshellarg($thumbPath);
+                       $conv = shell_exec( $cmd );
+               }
+               return $thumbUrl;
+       }
+
+       function makeThumbLinkObj( $nt, $label = "", $align = "right", $boxwidth = 180 ) {
+               global $wgUploadPath;
+               $name = $nt->getDBKey();
+               $image = Title::makeTitle( Namespace::getImage(), $name );
+               $link = $image->getPrefixedURL();
+               $url  = wfImageUrl( $name );
+               $path = wfImagePath( $name );
+
+               list($width, $height, $type, $attr) = getimagesize( $path );
+               $cwidth   = $boxwidth;
+               $cheight  = intval( $height/($width/$cwidth) );
+               if ($cheight > $boxwidth*1.5) {
+                       $cheight = $boxwidth*1.3;
+                       $cwidth  = intval( $width/($height/$cheight) );
+               }
+               if ( $cwidth > $width ) {
+                       $cwidth  = $width;
+                       $cheight = $height;
+               }
+               
+               $thumbUrl = $this->createThumb( $name, $cwidth );
+
+               $u = wfLocalUrlE( $link );
+
+               $more = wfMsg( "thumbnail-more" );
+               
+               $s = "<div class=\"thumbnail-{$align}\" style=\"width:{$boxwidth}px;\">" .
+                 "<a href=\"{$u}\" class=\"internal\" title=\"{$label}\">" .
+                 "<img border=\"0\" src=\"{$thumbUrl}\" alt=\"{$label}\" width=\"{$cwidth}\" height=\"{$cheight}\"></a>" .
+                 "<a href=\"{$u}\" class=\"internal\" title=\"{$more}\">" .
+                   "<img border=\"0\" src=\"{$wgUploadPath}/magnify-clip.png\" width=\"26\" height=\"24\" align=\"right\" alt=\"{$more}\"></a>" .
+                 "<p>{$label}</div></p>";
                return $s;
        }
 
index 9e7c1bc..b5a7144 100644 (file)
@@ -20,6 +20,12 @@ define("MAG_SUBST", 12);
 define("MAG_MSGNW", 13);
 define("MAG_NOEDITSECTION", 14);
 define("MAG_END", 15);
+define("MAG_IMG_THUMBNAIL",  16);
+define("MAG_IMG_RIGHT",      17);
+define("MAG_IMG_LEFT",       18);
+define("MAG_IMG_NONE",       19);
+define("MAG_IMG_WIDTH",      20);
+
 
 #--------------------------------------------------------------------------
 # Language-specific text
@@ -300,7 +306,13 @@ this</a> (alternative: like this<a href=\"\" class=\"internal\">?</a>).",
        MAG_MSG                  => array( 0,    "{{MSG:$1}}"             ),
        MAG_SUBST                => array( 0,    "{{SUBST:$1}}"           ),
     MAG_MSGNW                => array( 0,    "{{MSGNW:$1}}"           ),
-       MAG_END                  => array( 0,    "__END__"                )
+       MAG_END                  => array( 0,    "__END__"                ),
+    MAG_IMG_THUMBNAIL         => array( 1, "thumbnail", "thumb"),
+    MAG_IMG_RIGHT             => array( 1, "right" ),
+    MAG_IMG_LEFT              => array( 1, "left" ),
+    MAG_IMG_NONE              => array( 1, "none" ),
+    MAG_IMG_WIDTH             => array( 1, "$1px" )
+
 );
 
 # All special pages have to be listed here: a description of ""
@@ -1302,7 +1314,12 @@ amusement.",
 # Namespace 8 related
 
 "allmessages"  => "All_messages",
-"allmessagestext"      => "This is a list of all messages available in the MediaWiki: namespace"
+"allmessagestext"      => "This is a list of all messages available in the MediaWiki: namespace",
+
+# Thumbnails
+
+"thumbnail-more"      => "Enlarge"
+
 );
 
 #--------------------------------------------------------------------------
index 4d2c000..982d0d0 100644 (file)
@@ -94,3 +94,43 @@ a.stub { color:#772233; text-decoration:none; }
 small { font-size: 75%; }
 #toc { border:1px solid #8888aa; background-color:#f7f8ff;padding:5px;font-size:95%; }
 
+
+/* Images */
+div.floatright { float: right; margin: 0 0 1em 1em; }
+div.floatright p { font-style: italic; }
+div.floatleft { float: left; margin: 0.3em 0.5em 0.5em 0; }
+div.floatleft p { font-style: italic; }
+
+
+/* thumbnails */
+div.thumbnail-none, div.thumbnail-right, div.thumbnail-left {
+       padding: 2px;
+       border:1px solid #8888aa;
+       background:#CCCCCC;
+       margin: 0.3em 0 0.5em;
+       font-size: 85%;
+}
+
+div.thumbnail-none p, div.thumbnail-right p, div.thumbnail-left p {
+       margin-top:3px; margin-bottom:3px;
+}
+
+div.thumbnail-right {
+       float: right;
+       margin-left:0.5em;
+}
+
+div.thumbnail-left {
+       float: left;
+       margin-right:0.5em;
+}
+
+/* table standards */
+table.rimage {
+        float:right;
+        width:1pt;
+        margin-left:1em;
+        margin-bottom:1em;
+        text-align:center;
+        font-size:smaller;
+        }
index 231342b..4543ca1 100644 (file)
@@ -12,3 +12,43 @@ h2, h3, h4, h5, h6 { margin-bottom: 0; }
 p.subtitle { padding-top: 0; margin-top: 0; }
 #toc { border:1px solid #8888aa; background-color:#f7f8ff;padding:5px;font-size:95%; }
 
+
+/* Images */
+div.floatright { float: right; margin: 0 0 1em 1em; }
+div.floatright p { font-style: italic; }
+div.floatleft { float: left; margin: 0.3em 0.5em 0.5em 0; }
+div.floatleft p { font-style: italic; }
+
+
+/* thumbnails */
+div.thumbnail-none, div.thumbnail-right, div.thumbnail-left {
+       padding: 2px;
+       border:1px solid #8888aa;
+       background:#CCCCCC;
+       margin: 0.3em 0 0.5em;
+       font-size: 85%;
+}
+
+div.thumbnail-none p, div.thumbnail-right p, div.thumbnail-left p {
+       margin-top:3px; margin-bottom:3px;
+}
+
+div.thumbnail-right {
+       float: right;
+       margin-left:0.5em;
+}
+
+div.thumbnail-left {
+       float: left;
+       margin-right:0.5em;
+}
+
+/* table standards */
+table.rimage {
+        float:right;
+        width:1pt;
+        margin-left:1em;
+        margin-bottom:1em;
+        text-align:center;
+        font-size:smaller;
+        }
\ No newline at end of file
index d4e20a7..ec6f84e 100644 (file)
@@ -38,8 +38,35 @@ td { empty-cells:show; }
 td.bottom { border-top: 1px solid gray; }
 td.top { border-bottom: 1px solid gray; }
 /* images */
-div.floatright { float:right;margin:0 0 1em 1em; }
+div.floatright { float: right; margin: 0 0 1em 1em; }
 div.floatright p { font-style: italic; } 
+div.floatleft { float: left; margin: 0.3em 0.5em 0.5em 0; }
+div.floatleft p { font-style: italic; } 
+
+/* thumbnails */
+div.thumbnail-none, div.thumbnail-right, div.thumbnail-left {
+       padding: 2px;
+       border:1px solid #8888aa;
+       background:#CCCCCC;
+       margin: 0.3em 0 0.5em;
+       font-size: 85%;
+       text-align: center;
+}
+
+div.thumbnail-none p, div.thumbnail-right p, div.thumbnail-left p {
+       margin-top:3px; margin-bottom:3px;
+       text-align: left;
+}
+
+div.thumbnail-right {
+       float: right;
+       margin-left:0.5em;
+}
+
+div.thumbnail-left {
+       float: left;
+       margin-right:0.5em;
+}
 
 /* table standards */
 table.rimage {
@@ -49,25 +76,4 @@ table.rimage {
        margin-bottom:1em;
        text-align:center;
        font-size:smaller;
-       }
-
-table.country {
-       border-width:1;
-       border-style:solid;
-       padding:2;
-       border-spacing:0;
-       float:right;
-       width:300px;
-       }
-
-table.flag {
-       background-color:#efefef;
-       border-width:0;
-       border-spacing:0;
-       padding:2;
-       }
-
-td.flag {
-       text-align:center;
-       width:140px;
-       }
+       }
\ No newline at end of file