# gallerythumbs Blosxom Plugin # (c) 2004, Terrence Ezrol # Version 0.01 # Documentation at perldoc gallerythumbs or end of file # Short Description: # a gallery thumbnail generator plugin for blosxom # (will allow downloads of original image with aid from the # binary plugin or clones package gallerythumbs; # To resize images we require Image::Magick use Image::Magick; ###################### Settings ##################### #max width my $maxwidth = 300; #max height my $maxheight = 199; #file format my $ftype = "jpeg"; ##################################################### # directories used by this plugin # where are the thumbnails saved my $thumbs_dir="$blosxom::plugin_state_dir/thumbs"; # where is the stat file (index file) my $thumbs_stat="$thumbs_dir/thumbs.db"; # Where is the lock file my $thumbs_lock="$thumbs_dir/lock"; # Possible image filetypes my @filetypes = ("png","jpg","jpeg","gif"); # Hash of the thumbnail statistics, (key = entry name) my %tnames = (); sub start{ # Load in the file database _loaddb(); # if the user wants a thumbnail image if($blosxom::path_info =~ /\.tmb$/){ my $f = $tnames{"/". $`}->[0]; $f = "$thumbs_dir/$f.$ftype"; # Send the user the thumbnail if it exists. if(-e "$f"){ open(FILE,"$f"); binmode(FILE); my $size=(stat(FILE))[7]; my $dat=""; # give information on the file, including a 24h cache time print("Content-Length: $size\n"); print("Cache-Control: max-age=86400, s-maxage=86400\n"); print("Content-type: image/$ftype\n\n"); #send the file in small blocks while($size > 1024){ $dat=""; read(FILE,$dat,1024); print($dat); $size=$size-1024; } #send the last (partial) block of the file $dat=""; read(FILE,$dat,$size); print($dat); #exit so blosxom dosn't return any output. exit; } } 1; #return true to blosxom; } sub story{ my (undef, undef, undef, undef, undef, $body_ref) = @_; # what is the file w/o the extension my $base=$blosxom::datadir . $blosxom::path . "/" . $blosxom::fn; my $tmb=""; #make sure the thumbnail text is blank. # search all filetypes foreach my $ft (@filetypes){ # see if the image exists if(-e "$base.$ft"){ # form the hash key my $key = "$blosxom::path/$blosxom::fn"; unless($tname{$key}){ #we don't have this thumbnail generate it _lock(); my $file = "$base.$ft"; _GenThumb($key,$file); # reload our database to make sure it is correct $tnames=(); _loaddb(); _unlock(); } #load and format the thumbnail template $tmb = &$blosxom::template($path, "thumbnail", $blosxom::flavour) or ""; $tmb =~ s/\$image::width/$tnames{"$key"}->[1]/eg; $tmb =~ s/\$image::height/$tnames{"$key"}->[2]/eg; $tmb =~ s/\$image::iname/$blosxom::fn . "." . $ft/eg; $tmb=&$blosxom::interpolate($tmb); } } # add the thumbnail section to the beginning of the story. $$body_ref=$tmb . $$body_ref; } #### _loaddb: ##### # loads the index/database out of the stats file sub _loaddb{ # if the database directory doesn't exist create it. unless(-d $thumbs_dir){ mkdir($thumbs_dir); } # check the existence of the stat file. if(-e "$thumbs_stat"){ open(DB,"<",$thumbs_stat); my $line = ; chop($line); if($line ne ("$maxwidth" . "x" . "$maxheight" . ".$ftype")){ my $oldtype=".png"; if($line=~/\.(.*)$/){ $oldtype=$1; } #thumbnails are invalid (settings changed?) _lock(); # delete old thumbnails while($line = ){ if($line=~/^([^-]*)-/){ unlink("$thumbs_dir/$1.$oldtype"); } } close DB; #remove stats file unlink($thumbs_stat); _unlock(); } # otherwise load the entries into a hash. else{ while($line=){ chop($line); if($line=~/^([^-]*)-([\d]*)x([\d]*)-/){ $tnames{$'}=[$1,$2,$3]; } } close DB; } } } # protection lock sub _lock{ my $sleep=0; my $l; do{ #if we failed to get a lock sleep for a second sleep(1) if($sleep); $sleep=1; # put our pid at the end of the (hopefully new) file open(LOCK,">>",$thumbs_lock); print LOCK "$$\n"; close(LOCK); # if the first line of the file has out pid we have the lock open(LOCK,"<",$thumbs_lock); $l=; chop($l); close(LOCK); }while($l ne $$); } # remove our lock (just remove the lock file) sub _unlock{ unlink($thumbs_lock); } # Generate the missing thumbnail sub _GenThumb{ my ($key,$file)=@_; my %thumbs; # now that the database is locked. make sure we have the most # recent version if(open(DB,"<",$thumbs_stat)){ my $line=; while($line = ){ chop($line); if($line=~/^([^-]*)-([\d]*)x([\d]*)-/){ $thumbs{$'}=[$1,$2,$3]; } } close(DB); } # and just in case make sure the key is really missing unless($thumbs{$key}){ # open the stat file for writing, and add the preferences line open(DB,">",$thumbs_stat); print(DB "$maxwidth" . "x" . "$maxheight.$ftype\n"); my $image = Image::Magick->new; my $gen = ""; #read in the image $image->Read($file); if($image->Get('columns') > $maxwidth || $image->Get('rows') > $maxheight){ #if ether dimension is larger than the thumbnail #max, Scale the image for the thumbnail. $image->Scale("$maxwidth" . "x" . "$maxheight"); } do{ #find a filename for the thumbnail my @codes = ("a","b","c","d","e","f","g","h","i","j","k","l","m", "n","o","p","q","r","s","t","u","v","w","x","y","z"); #file names are pid+10 random letters. $gen="$$"; for(my $i;$i<10;$i++){ $gen .= "" . $codes[rand($#codes + 1)]; } }while(-e "$thumbs_dir/$gen.$ftype"); #we have a file name, write the file $image->write("$thumbs_dir/$gen.$ftype"); #get width/height $thumbs{$key}=[$gen,$image->Get('columns'),$image->Get('rows')]; #write out the stats/index database file foreach my $e(keys(%thumbs)){ my $exists = 0; #remove any thumbnails that have become invalid. foreach my $t(@filetypes){ if(-e "$blosxom::datadir$e.$t"){ $exists=1; } } if($exists == 1){ print(DB "" . $thumbs{$e}->[0] . "-" . $thumbs{$e}->[1] . "x" . $thumbs{$e}->[2] . "-" . $e . "\n"); }else{ # actual remove the invalid thumbnails. unlink("$thumbs_dir/" . $thumbs{$e}->[0] . ".$ftype"); } } close DB; } } #plugin returns true 1; __END__ =head1 NAME Blosxom Plug-in: gallerythumbs =head1 SYNOPSIS This is a plugin for blosxom to generate a thumbnail of an image related to a story. With the proper flavor this thumbnail can be viewed and a link to the actual image is possible. A simple example of usage is if you want to make a story about image.jpg if you put image.jpg in your blog directories, and create in the same directory image.txt, a thumbnail of image.jpg will be created, and the content of the thumbnail flavor will be prefixed to your story. This thumbnail flavor should show the image image.tmb (which will be returned by this plugin, if you give that url to blosxom.) =head1 CONFIGURATION =head2 PLUGIN SETTINGS set the three configuration variables at the top of the code: my $maxwidth = ; my $maxheight = ; my $ftype = =head2 FLAVORS for any flavor you want the thumbnail visible in, you need a thumbnail flavor. for example you might want to make 2 flavor files (thumbnail.html and thumbnail.rss) with the following:
$fn's Thumbnail
Full Size
The variables available are: $image::width = width of thumbnail $image::height = height of thumbnail $image::iname = the file name of the original image ($fn.) after those variables are substituted, the file is sent through the same code as other flavors, allowing for all your favorite variables. Since this flavor generates relative links (ie. link to thumbnail and to the full image don't have path information, you will ether need to use the blossom plugin rellink or add the path info) also you will need the binary (or equivalent) plugin to download the images. =head1 VERSION v0.01 =head1 AUTHOR Terrence Ezrol =head1 ALSO SEE gallerythumbs: http://devnull.name/blog/blosxom/gallerythumbs rellink: http://devnull.name/blog/blosxom/rellink binary: http://www.blosxom.com/plugins/display/binary.htm Blosxom: http://www.blosxom.com/ =head1 BUGS If you find a bug in this plugin, please goto the plugins website and leave a comment. http://devnull.name/blog/bloxom/gallerythumbs =head1 LICENSE =head2 GALLERYTHUMBS gallerythumbs Copyright 2004, Terrence Ezrol Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =head2 BLOSXOM For licensing information on Blosxom please goto http://www.blosxom.com/license.html