#!/usr/bin/perl
##################
# copyright and GPL (http://www.gnu.org/licenses/gpl.html)
# Barry Hughes <bazza@bazza.com>
# photo galleries that are a little more automatic and sensible
# than just filename lists, or running a script that takes 3 years to
# generate everything, this only generates the served images when
# they're viewed. if you're not running your web server with suexec, you'll
# need to create the dirs yourself, and make sure the user the web server is
# running as will need write access to "images" and "thumbnails"
# Additions: weird ratio support, checking of URL specified sizes, and
# switching width to height if image is portrait rather than landscape
# thanks to the Loony <eaganj@bazza.com>, updated next/previous links
# idea semi stolen from zgal (http://zgal.sf.net)
# This version will also browse directories if you want
use Cwd;
use Date::Manip;
use Image::Info qw(image_info);
use Image::Magick;
# Some config stuffs
$thumbwidth = "100";
@imagewidths = qw/640 800 1024 1600/;
$imagesperrow;
$imagesperrow = 4;
$defaultwidth = "640";
$base_dir = "/var/www/bazza/photos";
$relative_path = "";
# Overlay image, this is a png, and is mostly transparent
$wmark = "watermark.png";
# Logo for bottom of pages (from webroot)
$logo = "/bazza.com.jpg";
# Dir icon when dir browsing
$dirimage = "/dir.png";
# Directories
$images = "images";
$comments = "comments";
$thumbs = "thumbnails";
$originals = "originals";
@subdirs = qw/images comments thumbnails/;
if($ENV{HTTP_USER_AGENT} =~ /^Mozilla\/4/) {
if($ENV{HTTP_USER_AGENT} =~ /MSIE/) {
$style = "style=\"border:1px solid #000000\"";
} else {
$style = " ";
}
} else {
$style = "style=\"border:1px solid #000000\"";
}
my $type;
if ($ENV{PATH_INFO} =~ /^\/+/) { &error; }
unless($ENV{PATH_INFO}) {
if(-d "$originals") { $type = "thumbindex"; } else { $type = "dirlist"; }
} elsif($ENV{PATH_INFO} =~ /^\/thumb/) {
$type = "thumb";
} elsif($ENV{PATH_INFO} =~ /^\/show/) {
$type = "show";
} elsif($ENV{PATH_INFO} =~ /^\/view/) {
$type = "view";
} else {
$type = "thumbindex";
}
if($type =~ /thumbindex/) {
my $checkdir = "$ENV{REQUEST_URI}/";
$checkdir =~ s/\/\//\//g;
$checkdir =~ s/$ENV{SCRIPT_NAME}\///;
unless(-d "$checkdir$originals") {
$type = "dirlist";
chdir($checkdir) or $type = "error";
} else {
chdir($checkdir);
}
}
if($type =~ /dirlist/) {
$title = $ENV{REQUEST_URI};
$title =~ s/$0//;
$title =~ s/\/\//\//g;
} elsif($type =~ /thumbindex/) {
$title = $ENV{REQUEST_URI};
$title =~ s/$ENV{SCRIPT_NAME}\///;
} elsif($type =~ /thumb/) {
thumb();
die;
} elsif($type =~ /view/) {
view();
die;
}
# Header
my $output = <<END;
Content-Type: text/html
<html>
<head>
<style type="text/css">
A:link { COLOR: #0080C0; }
A:visited { COLOR: red; }
A:hover { COLOR: #000099; }
A:active { COLOR: red; }
A { text-decoration: none; }
</style>
<title>$title</title></head>
<script language=javascript src="/.js/awstats_misc_tracker.js"></script>
<body bgcolor="#FFFFFF">
END
if($type =~ /dirlist/) {
$output .= dirlist();
} elsif($type =~ /thumbindex/) {
$output .= thumbindex();
} elsif($type =~ /show/) {
$output .= show();
} else {
$output .= error();
}
# Foot
if($logo) {
$output .= <<END;
<p> <p>
<p>
<center><a href="http://bazza.com/"><img src="$logo" border="0"></a></center>
END
}
$output .= <<END;
</body>
</html>
END
print $output;
sub dirlist {
my @updir = split("/",$ENV{REQUEST_URI});
my $foo = pop(@updir);
my $updir = join("/",@updir);
my $pwd = cwd();
#unless($pwd =~ /$ENV{DOCUMENT_ROOT}/) { die;}
my $dirlist = <<END;
<font face="Arial, Helvetica" size="-1">
<a href="$updir">../</a> <a href="$updir">Previous Dir</a>
<center><p>$title<p></center>
<table align="center" cellpadding="10" $style bgcolor="#ffffff">
END
foreach(sort <*>) {
next if($_ =~ /\./);
push(@dirs,$_);
}
$dirnumber = 1;
foreach(@dirs) {
if($dirnumber eq 1) { $output .= "<tr align=\"center\">\n"; }
$dir = $_;
$dirlist .= <<END;
<td width="200" align= "center" valign="top">
<font face="Arial, Helvetica" size="-1">
END
if($ENV{PATH_INFO}) {
$dirlist .= "<a href=\"$ENV{SCRIPT_NAME}$ENV{PATH_INFO}/$_\"><img src=\"$dirimage\" border=\"0\"></a>\n";
my $name = $_;
$name =~ s/_/ /g;
$dirlist .= "<p><a href=\"$ENV{SCRIPT_NAME}$ENV{PATH_INFO}/$_\">$name</a><br>\n";
} else {
$dirlist .= "<a href=\"$ENV{SCRIPT_NAME}/$_\"><img src=\"$dirimage\" border=\"0\"></a>\n";
my $name = $_;
$name =~ s/_/ /g;
$dirlist .= "<p><a href=\"$ENV{SCRIPT_NAME}/$_\">$name</a><br>\n";
}
$dirlist .= "</font></td>\n";
if($dirnumber eq 4) {
$dirlist .= "</tr>\n";
$dirnumber = 1;
} else {
$dirnumber++;
}
}
$dirlist .= <<END;
</tr>
</table>
END
return $dirlist;
}
sub error {
my $link = $ENV{SCRIPT_NAME};
my $error = <<END;
<font face="Arial, Helvetica">The directory $title does not exist, please click <a href="$link">here</a> to return to the main dir
</font>
END
return $error;
}
sub thumbindex {
@dirs = qw/images comments thumbnails/;
foreach(@dirs) {
if(-e $_) { next; }
mkdir($_);
}
open(TITLE, "title");
my $title = <TITLE>;
my @updir = split("/",$ENV{REQUEST_URI});
my $foo = pop(@updir);
my $updir = join("/", @updir);
my $thumbindex = <<END;
<font face="Arial, Helvetica" size="-1"><a href="$updir">../</a> <a href="$updir">Previous Dir</a><p>
<center><p>$title<p></center>
<table align="center" cellpadding="10" $style bgcolor="#eeeeee">
END
chdir("$originals");
foreach(<*>) {
next unless($_ =~ /jpg/);
push(@images,$_);
}
$imagenumber = 1;
foreach(@images) {
my $cmt = $_;
$cmt =~ s/.jpg//;
if(-e "../$comments/$cmt.txt") {
open(COMMENT, "../$comments/$cmt.txt");
$comment = <COMMENT>;
}
if($imagenumber eq 1) { $thumbindex .= "<tr align=\"center\">\n"; }
$image = $_;
$image =~ s/\.jpg//;
if(-e "../$thumbs/$image.jpg") {
my $path = $ENV{REQUEST_URI};
$path =~ s/index.cgi//;
$path =~ s/\/\//\//g;
$thumb = "$path/$thumbs/$image.jpg";
} else {
$thumb = "$ENV{SCRIPT_NAME}/thumb$ENV{PATH_INFO}/$_";
}
$thumbindex .= <<END;
<td width="200" valign="top">
<font face="Arial, Helvetica" size="-1">
<a href="$ENV{SCRIPT_NAME}/show$ENV{PATH_INFO}/$image-$defaultwidth.jpg"><img src="$thumb" border="0" $style></a>
<p>$_<br>
END
foreach(@imagewidths) {
my $width = $_;
my $ratio = &get_ratio;
my $height;# = int($width * $ratio);
if ($ratio > 1) {
$height = $width;
$width = int($height / $ratio);
} else {
$height = int($width * $ratio);
}
$thumbindex .= <<END;
<a href="$ENV{SCRIPT_NAME}/show$ENV{PATH_INFO}/$image-$_.jpg">$width x $height</a><br>
END
}
if($comment) { $thumbindex .= "$comment\n"; }
undef $comment;
close(COMMENT);
$thumbindex .= "</font></td>\n";
if($imagenumber eq 4) {
$thumbindex .= "</tr>\n";
$imagenumber = 1;
} else {
$imagenumber++;
}
}
$thumbindex .= <<END;
</tr>
</table>
END
return $thumbindex;
}
sub get_ratio {
my $path = $ENV{PATH_TRANSLATED};
$path =~ s/$ENV{DOCUMENT_ROOT}//;
$path =~ s/\/thumb//;
$path =~ s/\/view//;
$path =~ s/\/show//;
$path =~ s/$image\.jpg//;
$path =~ s/$image-$width\.jpg//;
$path =~ s/\/\//\//;
$path .= "/";
my $info = image_info("$base_dir$path$originals/$image.jpg");
$output .= "$info->{error}\n";
# print "$info->{error}\n";
my $height = $info->{height};
my $width = $info->{width};
# print "originals: $height x $width\n";
my $ratio = $height / $width;
return($ratio);
}
sub test {
print "Content-Type: text/plain\n\n";
print "$< $>\n\n";
foreach(sort keys %ENV) {
print "$_ = $ENV{$_}\n";
}
}
sub thumb {
# print "Content-Type: text/plain\n\n";
my @image = split("/", $ENV{PATH_INFO});
$image = $image[$#image];
$image =~ s/\.jpg//;
$thumbx = $thumbwidth;
my $ratio = &get_ratio;
if ($ratio > 1) {
$thumby = $thumbx;
$thumbx = int($thumby / $ratio);
} else {
$thumby = int($thumbx * $ratio);
}
print "Content-Type: image/jpeg\n\n";
$tmb = Image::Magick->new;
my $path = $ENV{PATH_TRANSLATED};
$path =~ s/$ENV{DOCUMENT_ROOT}//;
$path =~ s/\/thumb//;
$path =~ s/$image.jpg//;
$path =~ s/\/\//\//;
$tmb->Read("$base_dir$path$originals/$image.jpg");
$tmb->Resize(width=>$thumbx,height=>$thumby);
$tmb->Write("$base_dir$path$thumbs/$image.jpg");
binmode STDOUT;
$tmb->Write('jpg:-');
}
sub view {
my @image = split("/", $ENV{PATH_INFO});
$image = $image[$#image];
$image =~ s/\.jpg//;
($image, $width) = split("-", $image);
my $ratio = &get_ratio;
if ($ratio > 1) {
$height = $width;
$width = int($height / $ratio);
} else {
$height = int($width * $ratio);
}
my $path = $ENV{PATH_TRANSLATED};
$path =~ s/$ENV{DOCUMENT_ROOT}//;
$path =~ s/\/view//;
$path =~ s/$image-$width.jpg//;
$path =~ s/$image-$height.jpg//;
$path =~ s/\/\//\//;
print "Content-Type: image/jpeg\n\n";
$img = Image::Magick->new;
$img->Read("$base_dir$path$originals/$image.jpg");
$watermark = Image::Magick->new;
unless(-e "$base_dir$path/nomark") {
$watermark->Read($wmark);
$img->Composite(compose=>"Atop", image=>$watermark, gravity=>"SouthEast");
}
$img->Resize(width=>"$width",height=>"$height");
if ($height / $width > 1) {
$img->Write("$base_dir$path$images/$image-$height.jpg");
} else {
$img->Write("$base_dir$path$images/$image-$width.jpg");
}
binmode STDOUT;
$img->Write('jpg:-');
}
sub show {
my @image = split("/", $ENV{PATH_INFO});
$image = $image[$#image];
$image =~ s/\.jpg//;
($image, $width) = split("-", $image);
foreach(@imagewidths) {
if($width =~ /$_/) {
$goodwidth = "1";
}
}
my $index = $ENV{PATH_INFO};
$index =~ s/\/show//;
$index =~ s/\/$image-$width.jpg//g;
$index = "$ENV{SCRIPT_NAME}$index";
my $path = $ENV{PATH_INFO};
$path =~ s/show\///;
$path =~ s/$image-$width.jpg//g;
if(-e "$base_dir$path$images/$image-$width.jpg") {
my $dir = $relative_path;
if($goodwidth) {
$view = "$dir$path$images/$image-$width.jpg";
} else {
$view = "$dir$path$images/$image-$defaultwidth.jpg";
}
} else {
if($goodwidth) {
$view = "$ENV{SCRIPT_NAME}/view$path$image-$width.jpg";
} else {
$view = "$ENV{SCRIPT_NAME}/view$path$image-$defaultwidth.jpg";
}
}
my $show .= <<END;
<font face="Arial, Helvetica" size="-1"><a href="$index">Back to Index</a>
<center>
<table cellpadding="0" cellspacing="0" border=0>
<tr><td></td>
<td bgcolor="#FFFFFF" colspan="3" width="$width" align="centre">
<center>
<img src="$view" $style>
</center>
</td>
<td></td></tr>
END
chdir("$base_dir$path$originals");
foreach(<*>) {
my $orig = $_;
$orig =~ s/.jpg//;
push (@images, $orig);
}
for my $i (0..$#images) {
if($images[$i] =~ /$image/) {
if($i) {
($prev, $next) = ($images[$i-1], $images[$i+1]);
} else {
($prev, $next) = (undef,$images[$i+1]);
}
}
}
if($prev) {
$show .= " <tr><td bgcolor=\"#eeeeee\" width=\"100\" valign=\"center\">\n";
$show .= " <center><a href=\"$ENV{SCRIPT_NAME}/show$path$prev-$width.jpg\"><img src=\"$dir$path$thumbs/$prev.jpg\" $style></a><br>\n";
$show .= " <a href=\"$ENV{SCRIPT_NAME}/show$path$prev-$width.jpg\"><font face=\"Arial, Helvetica\" size=\"-1\">Previous</a></center>\n";
$show .= " </td>\n";
} else {
$show .= " <td bgcolor=\"#eeeeee\" width=\"100\"><font color=\"#eeeeee\">No previous image</font></td>\n";
}
$show .= <<END;
<td bgcolor="#eeeeee" align="center" width="150"><font face="Arial, helvetica" size="-1">View At:<p>
END
foreach(@imagewidths) {
my $width = $_;
my $ratio = &get_ratio;
my $height;# = int($width * $ratio);
if ($ratio > 1) {
$height = $width;
$width = int($height / $ratio);
} else {
$height = int($width * $ratio);
}
$show .= " <a href=\"$ENV{SCRIPT_NAME}/show$path$image-$_.jpg\">$width x $height</a><br>\n";
}
$show .= " </td>";
$info = image_info("$base_dir$path$originals/$image.jpg");
$datetime = $info->{DateTimeDigitized};
$datetime =~ s/:/-/;
$datetime =~ s/:/-/;
$datetime =~ ParseDate($datetime);
$takendate = UnixDate($datetime, "%a %b %e %H:%M:%S %Y");
$show .= <<END;
<td bgcolor="#eeeeee" align="left" width="200">
<br><font size="-1">Original Size: $info->{width}x$info->{height}</font>
<br><font size="-1">Flash: $info->{Flash}</font>
<br><font size="-1">Taken with: $info->{Model}</font>
<br><font size="-1">ISO: $info->{ISOSpeedRatings}</font>
<br><font size="-1">Shutter Speed: $info->{ExposureTime}</font>
END
# If you're not me, you probably don't want this hack, the date was generally
# wrong on my finepix, so we're just not going to show my ineptness :)
if($info->{Model} =~ /EOS/) {
($fstop1, $fstop2) = split ('/', $info->{FNumber});
$fstop = $fstop1 / $fstop2;
$show .= <<END;
<br><font size="-1">Taken: $takendate</font>
<br><font size="-1">F Stop: $fstop</font>
END
$show .= " </td>\n";
}
$show .= "<td bgcolor=\"#eeeeee\" valign=\"top\">\n";
if(-e "$base_dir$path$comments/$image.txt") {
$show .= "<font face=\"Arial, Helvetica\" size=\"-1\">";
open(COMMENT, "$base_dir$path$comments/$image.txt");
$show .= <COMMENT>;
} else { $show .= "<font color=\"#eeeeee\">no comment</font>"; }
$show .= "</td>";
if($next) {
$show .= " <td bgcolor=\"#eeeeee\" width=\"100\" valign=\"center\">\n";
$show .= " <center><a href=\"$ENV{SCRIPT_NAME}/show$path$next-$width.jpg\"><img src=\"$dir$path$thumbs/$next.jpg\" $style></a><br>\n";
$show .= " <a href=\"$ENV{SCRIPT_NAME}/show$path$next-$width.jpg\"><font face=\"Arial, helvetica\" size=\"-1\">Next</a></center>\n";
$show .= " </td>\n";
} else {
$show .= " <td bgcolor=\"#eeeeee\" width=\"100\" valign=\"center\"><font color=\"#eeeeee\">no next image</font></td>\n";
}
$show .= <<END;
</tr>
</table>
END
return($show);
}
syntax highlighted by Code2HTML, v. 0.9.1