#!/usr/bin/perl # GenIndex 12/27/03 # (c) 2003 by Stephen A. Ness # Generate thumbnails and HTML index page for given directory (default: current directory). # Usage: GenIndex [ -d ] [ -f ] [ -i ] [-ln ] [ -r ] [ -v ] [ dir ] # -d print debug info # -f force thumbnail regeneration even if it already exists # -i create image index only (don't index directories or ordinary files) # -ln generate n levels of parent links (if not in /home/photo) # -r generate subdirectory indices recursively # -v print verbose info # Uses EzThumbs and jpginfo. $version = "1.4"; # version number # Configuration. # Cf. also gen_links, which has wired-in knowledge about /home/photo. # Cf. also wired-in info in $html_hd and $html_ft. $index = "index.html"; # default index filename # Directories where index.html is maintained by hand; avoid clobbering these. $avoid = "\/home\/photo|\/home\/photo\/san\/\\d\\d\\d\\d"; $exclude = "$index|g$indexl|thumbs|Thumbs.db|_xlk|xxx"; # file/dir names to exclude from index $html_exts = "gif|htm|html|txt"; # extensions which support hrefs $image_exts = "jpeg|jpg|tif"; # FIX_ME EzThumbs does not deal with GIFs, so gif in html_exts instead # Parameters for thumbnail size and index page image layout. # For uniformity, make all thumbnails 100 pixels high. # Most pictures are 3x4 (portrait) or 4x3 (landscape) aspect ratio, # so most thumbnails are 75x100 or 133x100. # The generated HTML index page contains a table of pix; # each table entry consists of a thumbnail image with filename below. # Thumbnails may span multiple columns or (in the case of panoramas) # may even be wider than the table. $col_w = 150; # HTML table column width $row_h = 125; # HTML table row height $row_w = 900; # HTML table row width $ncols = int($row_w / $col_w); # number of columns per table row # Executable and parameters for EzThumbs invocation. $EzThumbs = "/u/EasyThumbnails/EZThumbs"; $tn_dir = "thumbs"; $tn_h = 100; $tn_pfx = "tn_"; $tn_q = "75"; $tn_w = 10000; # so EzThumbs will always generate thumbnail height 100 pixels # Executable and switches for jpginfo invocation. $jpginfo = "perl /home/photo/bin/jpginfo -c -t"; # Executable for recursive GenIndex invocation. $GenIndex = "perl /home/photo/bin/GenIndex"; # Subroutines. # Examine contents of current directory and build file and directory lists. # Exclude all ".*" files, [g]index.html, Thumbs.db, subdirectory thumbs or _xlk. # This respects case sensitivity, so it misses e.g. "FOO.JPG" as image file. # @dirs directories # @ifiles image files (.jpeg, .jpg, .tif) # @ofiles other files sub check_dir { $ofile = grep(/^($avoid)$/, $dir) ? "g$index" : $index; # output filename (index.html or gindex.html) print "[$dir:]\n" if $vflag; opendir(DIR, ".") || die "cannot open \".\"\n"; @files = grep(!/^($exclude)$/, grep(!/^\./, readdir(DIR))); closedir(DIR); @dirs = grep(-d, @files); @files = grep(-f, @files); @ifiles = grep(/\.($image_exts)$/, @files); @ofiles = grep(!/\.($image_exts)$/, @files); } # Generate an image thumbnail (if necessary) and write an href in the index. sub do_image { local ($f) = @_; mkdir($tn_dir, 0755) unless -d $tn_dir; # create thumbnail directory if necessary print "$f:\n" if $vflag; $tn = "$tn_dir/$tn_pfx$f"; # thumbnail filename $tn =~ s/\.(jpeg|tif)$/.jpg/; # EzThumbs generates tn_foo.jpg for foo.jpeg and foo.tif # Generate the thumbnail via EzThumbs if it does not exist or if fflag. `$EzThumbs $f /D=$tn_dir /P=$tn_pfx /H=$tn_h /W=$tn_w /Q=$tn_q` if $fflag || ! -f $tn; chop($w = `$jpginfo $tn`); # get thumbnail width info via jpginfo $w =~ s/.*w=(\d+) .*/$1/; # grab thumbnail width spec die "$tn: unexpected thumbnail width $w\n" if $w == 0; print "width=$w row_w=$row_w row_rem=$row_rem in_row=$in_row in_table=$in_table\n" if $dflag; if ($w > $row_w) { # Very wide thumbnail, e.g. panorama; terminate table. &table_end if $in_table; print OUTF "\"$f\"
$f
\n"; return; } &row_end if $in_row && $w > $row_rem; # too wide for current row, flush &row_start unless $in_row; # start new row if necessary $span = int(($w + $col_w - 1) / $col_w); # column span of this thumbnail $row_rem -= $span * $col_w; # remaining space in this row $align = $span == 1 ? "center" : "left"; # center if single column, else left align print OUTF "\"$f\"
$f\n"; } # Generate links (in global $links) for bottom of index page based on the current directory. # Set $title appropriately. # Very hacky indeed, but does what I need for the present. # $dir is typically e.g. "/home/photo/san/yyyy/yymmdd", but not necessarily. # [path index: 0 1 2 3 4 5] sub gen_links { $links = ""; @path = split(/\//, $dir); $title = "$path[$#path] index"; if ((@path >= 3) && $path[0] eq "" && $path[1] eq "home" && $path[2] eq "photo") { # Generate links for /home/photo/... if (@path > 4) { $path[3] = "Steve's" if $path[3] eq "san"; $links .= join("", "$path[3] $path[4] photos
\n") if (@path > 5); $links .= join("", "$path[3] photos
\n"); } $links .= join ("", "All photos
\n"); } else { # Generate links for directory located elsewhere. $ldir = $dir; foreach $i (1 .. $level) { ($n = rindex($ldir, "/")) != -1 || die "bad ldir $ldir\n"; $ldir = substr($ldir, 0, $n); $links .= join("", "$ldir
\n"); } $links .= join ("", "All photos
\n"); } } # End a table row in the index. sub row_end { print OUTF "\n"; $in_row = $row_rem = 0; } # Start a table row in the index. sub row_start { &table_start unless $in_table; $in_row = 1; $row_rem = $row_w; print OUTF "\n"; } # End a table in the index. sub table_end { &row_end if $in_row; print OUTF "\n"; $in_table = 0; } # Start a table in the index. # Print a row of empty cells of height 1 at the start of the table # to force the browser to align subsequent cells evenly. sub table_start { $in_table = 1; print OUTF "\n"; print OUTF "\n"; print OUTF "\n" x $ncols; print OUTF "\n"; } # Main. # Process args. while(@ARGV) { $arg = shift @ARGV; if ($arg eq "-d") { $dflag = !$dflag; $flags .= " $arg"; next; } if ($arg eq "-f") { $fflag = !$fflag; $flags .= " $arg"; next; } if ($arg eq "-i") { $iflag = !$iflag; $flags .= " $arg"; next; } if ($arg =~ /^-l(\d+)/) { $level = $1; $flags .= " -l" . ($level + 1); next; } if ($arg eq "-r") { $rflag = !$rflag; $flags .= " $arg"; next; } if ($arg eq "-v") { $vflag = !$vflag; $flags .= " $arg"; next; } if ($dir_flag) { print STDERR "Warning: arg $arg ignored\n"; } else { ++$dir_flag; chdir $arg || die "cannot cd to \"$arg\"\n"; } } $flags .= " -l1" if $level == 0 && $rflag; # for recursive invocation `rm $tn_dir/*.jpg` if -d $tn_dir && $fflag; # remove old thumbnails if $iflag # Get the current time. ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); $year += 1900; $mon += 1; $date = sprintf("%d/%d/%02d", ($mon, $mday, $year - 2000)); # mm/dd/yy # Get the current directory. Arg processing above might have chdir'ed. chop($dir = `pwd`); &gen_links; # generate links for bottom of index page &check_dir; # generate directory/other/image lists # HTML header and footer. $html_hd = join("\n", "", "", "", "", "", "", "$title", "", "", "", "", "", "", "", "

Index of $dir

", "
", "\n"); $html_ft = join("\n", "", "All content © $year by Stephen A. Ness.
", "Generated: $date", "
", "", "", "\n"); # Generate the index file. open(OUTF, ">$ofile") || die "cannot open \"$ofile\"\n"; print OUTF $html_hd; # print HTML header if (@dirs && !$iflag) { # generate subdirectory hrefs print OUTF "

Directories:

\n"; foreach $dir (@dirs) { system("cd $dir && $GenIndex $flags") if $rflag; print OUTF (-f "$dir/$index") ? "$dir
\n" : "$dir
\n"; } print OUTF "
\n"; } if (@ofiles && !$iflag) { # generate list of ordinary files (with hrefs if appropriate) print OUTF "

Files:

\n"; foreach $file (@ofiles) { print OUTF ($file =~ /\.($html_exts)$/) ? "$file
\n" : "$file
\n"; } print OUTF "
\n"; } if (@ifiles) { # generate table of image files print OUTF "

Image files:

\n"; print OUTF "Click on any image to enlarge, then use the back arrow on your browser to return.
\n"; $in_row = $in_table = 0; foreach $f (@ifiles) { &do_image($f); } # process image files &table_end if $in_table; print OUTF "
\n"; } print OUTF "$links
\n" if $links; # print links print OUTF $html_ft; # print HTML footer close(OUTF); # done # end of GenIndex