Apache-ImgIndex
view release on metacpan or search on metacpan
ImgIndex.pm view on Meta::CPAN
# Apache::ImgIndex
#
# James Pavlick, 2000
# mod_perl module for indexing directories of images
#
=head1 NAME
Apache::ImgIndex
=head1 SYNOPSIS
Add the following to your httpd.conf and restart. Then point your browser to
http://yoursite/photos
<Location /photos>
AllowOverride None
#Options -Indexes -Includes -FollowSymLinks
Order allow,deny
Allow from all
SetHandler perl-script
PerlHandler Apache::ImgIndex
PerlSetVar Rows 10
PerlSetVar Cols 5
PerlSetVar Thumb-size 50x20
PerlSetVar Show-names 1
PerlSetVar Hide-dirs 1
</Location>
Make sure /photos contains the full size images that you want to display.
=head1 DESCRIPTION
I<Apache::ImgIndex> is a simple mod_perl application for displaying photos.
I<Apache::ImgIndex> will automatically build thumbnails of the images. You
can also rotate and scale the images from the web interface.
=head1 CAVEATS
=over 2
=item B<*> Lots of work still to do
=cut
package Apache::ImgIndex;
use strict;
use Apache2;
#use Apache::compat;
use Apache::RequestRec;
use Apache::RequestIO;
use Apache::Const qw(:common HTTP_OK);
use Apache::Log;
use APR::Const qw(:filetype);
use APR::Finfo;
use Image::Magick ();
use DirHandle ();
use FileHandle ();
use File::Basename qw(fileparse);
use vars qw(%gOptions @gOutput $gOutputStarted $VERSION);
$VERSION = 0.02;
%gOptions = (
'thumb-size' => '100x75', # set thumbnail size
'force' => 0, # always rebuild thumbnails
'rows' => 5, # rows to display
'cols' => 4, # columns to display
'show-names' => 0, # show thumbnail names
'hide-dirs' => 0, # hide the photo directories list
'filter' => '.*', # display only directories that match
);
sub handler {
my($r) = shift;
# store output in this array
@gOutput = ();
$gOutputStarted = 0;
# set config values
my $val = '';
$gOptions{'thumb-size'} = $val if($val = $r->dir_config('Thumb-size'));
$gOptions{'force'} = $val if($val = $r->dir_config('Force'));
$gOptions{'rows'} = $val if($val = $r->dir_config('Rows'));
$gOptions{'cols'} = $val if($val = $r->dir_config('Cols'));
$gOptions{'show-names'} = $val if($val = $r->dir_config('Show-names'));
$gOptions{'hide-dirs'} = $val if($val = $r->dir_config('Hide-dirs'));
$gOptions{'doc-root'} = $r->document_root . $r->location;
$gOptions{'base-url'} = $r->location;
$gOptions{'filter'} = $val if($val = $r->dir_config('Filter'));
# do processing for a directory of images
if($r->finfo->filetype == DIR) {
if($r->args =~ /name=/) {
# show image detail html page
showImgDetail($r);
} else {
# show the thumbnail index html page
my ($name, $path, $ext) = fileparse($r->filename, qr{\.\w*$});
mkdir("$path/.thumbs") unless(-d "$path/.thumbs");
showImgThumbs($r);
}
}
# do processing on the image file itself
if($r->filename =~ /-thumb/) {
showThumbFile($r);
}
ImgIndex.pm view on Meta::CPAN
);
for(my $y = 0; $y <= int((@filelist - 1)/$perpage); $y++) {
$index = $perpage * $y;
my $pagenum = $y + 1;
($index == $start) ?
output(qq| <option value="$index" selected>page $pagenum\n|):
output(qq| <option value="$index">page $pagenum\n|);
}
output(
qq| </SELECT><BR>\n|,
qq| <font size="-1"><i>Total: </i>|, scalar @filelist, qq| images</font>\n|,
qq| </FORM>\n|,
qq| </TD>\n|
);
}
# next page
if($start + $perpage < $#filelist) {
$index = $start + $perpage;
output(qq| <TD width=100 align="center"><A href="$baseUri?start=$index">[next]</A></TD>\n|);
} else {
output(qq| <TD width=100> </TD>\n|);
}
output(
" </TR>\n",
" </TABLE>\n",
" </TD></TR>\n",
"</TABLE>\n",
"</CENTER>\n",
"</BODY>\n",
"</HTML>\n"
);
}
# showThumbFile
#
#
sub showThumbFile {
my $r = shift || return;
my %mimeType =
(jpg => 'image/jpeg', gif => 'image/gif', png => 'image/png');
my ($name, $path, $ext) = fileparse($r->filename, qr{\.\w*$});
my($w, $h) = split('x', $gOptions{'thumb-size'});
$name =~ s/^\.//g;
$path =~ s/\/$//g;
$ext =~ s/^\.//g;
(my $imgName = $name) =~ s/-thumb$//i;
my($thumbName) = "$name.$ext";
my($Img) = Image::Magick->new();
my($tw, $th) = (0, 0);
if(-f "$path/$thumbName") {
($tw, $th) = $Img->Ping("$path/$thumbName");
}
# build the thumbnail if it doesn't exist
if( ($w != $tw && $h != $th) || $gOptions{'force'} ) {
$Img->Read("$path/../$imgName.$ext");
$Img->Resize(geometry=>"$gOptions{'thumb-size'}");
$Img->Write("$path/$thumbName");
}
my $Fh = FileHandle->new();
$Fh->open("$path/$thumbName") || die("Can't open image file $path/$thumbName");
$r->content_type($mimeType{lc $ext});
output(<$Fh>);
undef $Img;
$Fh->close();
}
# showImgDetail
#
#
#
sub showImgDetail {
my($r) = shift;
my(%in) = map { my($key, $val) = split('=', $_); $key => $val }
(split('&', $r->args));
my($baseUri) = $r->uri;
# only rotate up to 360 degrees
if($in{'rot'} >= 360) { $in{'rot'} -= 360 };
# only allow scaling to 25% and 200% of image size
if($in{'scale'} < -75) { $in{'scale'} = -75 };
if($in{'scale'} > 100) { $in{'scale'} = 100 };
my $scale = $in{'scale'} + 100;
my $rotText = ($in{'rot'}) ? "(Rotated: $in{'rot'}°)" : '';
my $scaleText = ($in{'scale'}) ? "(Scaled: $scale%)" : '';
$r->content_type("text/html");
output(
"<HTML>\n",
"<HEAD>\n",
" <TITLE>Image: $in{'name'} $rotText $scaleText</TITLE>\n",
"</HEAD>\n",
qq|<BODY bgcolor="#ffffff">\n\n|,
"<CENTER>\n",
qq|<TABLE border=1>\n|,
qq| <TR><TD> </TD><TD align="center"><A href="$baseUri?start=$in{'start'}"><B>Image Index</B></A></TD><TD> </TR>\n|,
qq| <TR><TD align="center"><A href="$baseUri?start=$in{'start'}&name=$in{'name'}&rot=|,
$in{'rot'} + 270, qq|&scale=$in{'scale'}"><B>270</B></A></TD>|,
qq|<TD align="center"><A href="$baseUri?start=$in{'start'}&name=$in{'name'}&rot=$in{'rot'}&scale=|, $in{'scale'} - 25, qq|">-</A> Zoom <A href="$baseUri?start=$in{'start'}&name=$in{'name'}&rot=$in{'rot'}&scale=|, $in{'scale'} + 25, qq|"...
qq|<TD align="center"><A href="$baseUri?start=$in{'start'}&name=$in{'name'}&rot=|,
$in{'rot'} + 90, qq|&scale=$in{'scale'}"><B>90</B></A></TD></TR>\n|,
qq| <TR><TD> </TD><TD align="center"><A href="$baseUri?start=$in{'start'}&name=$in{'name'}&rot=|,
$in{'rot'} + 180, qq|&scale=$in{'scale'}"><B>180</B></A></TD><TD> </TD></TR>\n|,
"</TABLE>\n",
qq|<TABLE border=1 width="100%">\n|,
);
output(qq| <TR><TD align="center"><IMG src="$baseUri/$in{'name'}?|);
output(qq|rot=$in{'rot'}|) if($in{'rot'});
output(qq|&scale=$in{'scale'}|) if($in{'scale'});
output(qq|" border=0></TD></TR>\n|);
output(
"</TABLE>\n",
"</CENTER>\n",
"</BODY>\n",
"</HTML>\n",
);
}
# processImg
#
#
#
sub processImg {
my($r) = shift;
my(%in) = map { my($key, $val) = split('=', $_); $key => $val } (split('&', $r->args));
my($imgfile) = $r->filename;
my ($name, $path, $ext) = fileparse($imgfile, qr{\..*});
$path =~ s/\/$//g;
$ext =~ s/^\.//g;
# only rotate up to 360 degrees
if($in{'rot'} >= 360) { $in{'rot'} -= 360 };
# only allow scaling to 25% and 200% of image size
if($in{'scale'} < -75) { $in{'scale'} = -75 };
if($in{'scale'} > 100) { $in{'scale'} = 100 };
if(%in) {
my($tmpfile) = "/tmp/$name." . time . ".$$.$ext";
my $scale = $in{'scale'} + 100;
my($Img) = Image::Magick->new;
$Img->Read($imgfile);
$Img->Rotate(degrees=>$in{'rot'}) if($in{'rot'});
$Img->Scale(geometry=>"${scale}%x${scale}%") if($in{'scale'});
$Img->Write("$tmpfile");
my($fh) = FileHandle->new("$tmpfile");
unless($fh) {
$r->log_error("Couldn't open file '$tmpfile'");
return SERVER_ERROR;
}
local $/;
output(<$fh>);
$fh->close;
unlink $tmpfile;
} else {
return DECLINED;
}
}
# dirIndex
#
#
sub dirIndex {
my($dirlist) = shift;
my($dir) = shift;
my($filter) = $gOptions{'filter'};
my($dh) = DirHandle->new($dir);
my(@contents) = $dh->read;
$dh->close;
foreach my $item (sort @contents) {
# skip directories containing .private files
next if(-e "$dir/$item/.private");
# skip files/directories starting with .
next if($item =~ /^\.+/);
# skip directories that aren't in the "filter" list
next unless("$dir/$item" =~ /$filter/);
# Add the item to the the directory list if it's a directory
next unless(-d "$dir/$item");
$dirlist->{"$dir/$item"}{'name'} = $item;
}
}
# listDirectory
#
#
sub listDirectory {
my($dir) = shift;
( run in 1.516 second using v1.01-cache-2.11-cpan-fe3c2283af0 )