#!/usr/bin/perl ################## # copyright and GPL (http://www.gnu.org/licenses/gpl.html) # Barry Hughes # 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 , 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 = < $title END if($type =~ /dirlist/) { $output .= dirlist(); } elsif($type =~ /thumbindex/) { $output .= thumbindex(); } elsif($type =~ /show/) { $output .= show(); } else { $output .= error(); } # Foot if($logo) { $output .= < 

END } $output .= < 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 = < ../  Previous Dir

$title

END foreach(sort <*>) { next if($_ =~ /\./); push(@dirs,$_); } $dirnumber = 1; foreach(@dirs) { if($dirnumber eq 1) { $output .= "\n"; } $dir = $_; $dirlist .= < END if($ENV{PATH_INFO}) { $dirlist .= "\n"; my $name = $_; $name =~ s/_/ /g; $dirlist .= "

$name
\n"; } else { $dirlist .= "\n"; my $name = $_; $name =~ s/_/ /g; $dirlist .= "

$name
\n"; } $dirlist .= "
\n"; if($dirnumber eq 4) { $dirlist .= "

\n"; $dirnumber = 1; } else { $dirnumber++; } } $dirlist .= <
END return $dirlist; } sub error { my $link = $ENV{SCRIPT_NAME}; my $error = <The directory $title does not exist, please click here to return to the main dir END return $error; } sub thumbindex { @dirs = qw/images comments thumbnails/; foreach(@dirs) { if(-e $_) { next; } mkdir($_); } open(TITLE, "title"); my $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); }