#!/usr/bin/perl
#
# $Header: /devel/cvsroot/www.kgarner.com/code/photo_html/makehtml.pl,v 1.5 2000/11/28 00:21:25 kgarner Exp $
#
# The cheesy make a thumbnail and html perl script.
#
# This script depends on ImageMagick.  ImageMagick can be found at
# http://www.wizards.dupont.com/cristy/ImageMagick.html
# It is now also dependant on PerlMagick.  PerlMagick can be found at
# http://www.wizards.dupont.com/cristy/www/perl.html
# We're also now dependant on Image::Info (which is in turn dependant on
# IO::String.)  Check your local CPAN mirror. 
#
# Copyright 1998-2000
# Licensed under the GNU General Public License
#    See http://www.gnu.org/copyleft/gpl.html for the GPL, if I contained it
#    here in full, it would easier be longer then the script itself.  You
#    have a web browser, go use it!
# Author: Keith T. Garner & Dru Henke
#
# Changes:
# $Log: makehtml.pl,v $
# Revision 1.5  2000/11/28 00:21:25  kgarner
# Another web page update.  Very small, but hey.
#
# Revision 3.30  2000/11/03 22:04:08  kgarner
# Made things a bit nicer with dereference notation.
#
# Revision 3.29  2000/11/01 18:16:01  kgarner
# IMPORTANT NOTE: The format of the caption file has changed.  Its now:
# "filename<tab>Photo name<tab>Photo caption\n".  This should allow our
# next and last buttons to be more pleasing to the eye.
#
# Revision 3.28  2000/10/30 18:45:13  kgarner
# Using Image::Info now to get Image size in most cases.  It only uses
# metadata, so it'll be less memory intensive if thumbfiles already
# exist.  Needs Image::Info and IO::String
#
# Revision 3.27  2000/10/10 22:39:59  kgarner
# We can now set the page title.  We're rad.
#
# Revision 3.26  2000/08/01 23:43:37  kgarner
# We now support caption order.  Go -o
#
# Revision 3.25  2000/08/01 21:54:01  kgarner
# added pngs and fixed a typeo
#
# Revision 3.24  2000/01/01 22:03:45  kgarner
# Had a problem overwriting a variable.  Made the one in the function act local.
#
# Revision 3.23  1999/12/12 14:42:42  kgarner
# The wrappers are not linked together sideshow style.
#
# Revision 3.22  1999/12/04 14:59:25  kgarner
# The initial change to Image::Magick
#
# Revision 3.21  1999/11/27 23:44:51  kgarner
# Another in a series of improvments to scope variables down.
#
# Revision 3.20  1999/11/25 03:04:09  kgarner
# I added a ton of stuff to this new one.  I've added a few functions such
# as getImageSize, doHTMLheader, doHTMLcloser, and doWrapper.  We now actually
# support HTML wrapping instead of giving it as an option and not doing
# anything about it.  It looks like it'll work fine and I'm sure there are
# some tweaks I wanna do, but it looks like a good start.
# David Lemson gave me an idea about having images show up in the order
# they appear in the caption file.  I think I'd have to rewrite the main
# loop that does everything, but I have a feeling I'd like to do that
# anyway.  The side benefit of doing caption file order is that you can
# remove a file from the main page, but not from the web server.  I'm not
# sure if I can think of a case where *I* would use that, but its a worthy
# thing to add.

use File::Copy;
use Image::Magick;
use Image::Info qw(image_info dim);

# We'll put some nice defaults here
$TABLESIZE = 4;
$VERBOSE = 0;
$NOLABEL = 0;
$JAVASCRIPT = 0;
$HTMLWRAP = 0;
$CAPTION_FILE = "caption.txt";
$HEADER_FILE = "";
$FOOTER_FILE = "";
$USE_CAPTION_ORDER = 0;

sub usage {
    print STDERR "Usage: makehtml.pl [options] <filename>\n";
    print STDERR "Options:\n";
    print STDERR "\t-c<color>\tBackground color for generated page.\n";
    print STDERR "\t-C<file>\tUse <file> for caption file.  Default: caption.txt\n";
    print STDERR "\t-f<file>\tUse <file> for the footer.\n";
    print STDERR "\t-h\t\tThis help text\n";
    print STDERR "\t-H<file>\tUse <file> for the header.\n";
    print STDERR "\t-i<image path>\tBackground image for generated page.\n";
    print STDERR "\t-j\t\tMake the page using java script.\n";
    print STDERR "\t-l\t\tDo not leave label placeholder.\n";
    print STDERR "\t-o\t\tUse caption file order.\n";
    print STDERR "\t-t<n>\t\ttable width (default: 4 cells)\n";
    print STDERR "\t-T<title>\tset page title\n";
    print STDERR "\t-v\t\tverbose\n";
    print STDERR "\t-w\t\tWrap fullsize image files with HTML.\n";
}

# &captinLoad($use_caption_order)
# if $use_caption_order is 1, we use caption order
# if its 0, we don't.
sub captionLoad {
    my $caption_order = shift;
    my $filename = "";
    my $caption = "";
    my $photoname = "";
    my @myfiles;

    if ($caption_order) {
        open(CAPTION, $CAPTION_FILE) || die("Can't open caption file, how can",
            " I determine the order if there isn't one?");
    }
    else {
        # If we can't open the caption file, and we're not using caption
        # order, its not a big deal.
        open(CAPTION, $CAPTION_FILE);
    }

    while (<CAPTION>) {
        # If we begin with a '#' and we'll consider it a comment
        if (/^#/) {
            next;
        }
        ($filename, $photoname, $caption) = split(/\t/,$_,3);
        chop($caption);
        $captions{$filename} = {
                                 "photoname" => $photoname,
                                 "caption" => $caption
                               };
        if ($caption_order) {
            push(@myfiles, $filename);
        }
    }
    close(CAPTION);

    if ($caption_order) {
        return @myfiles;
    }
}

# &doHeader(FILE, $header_file);
sub doHeader {
    my $FILE = shift;
    my $header_file = shift;

    open(HEADER, $header_file);
    while (<HEADER>) {
        print $FILE $_;
    }
    close(HEADER);
    print $FILE "<hr>\n";
}

sub doFooter {
    print HTMLFILE "<hr>\n";
    open(FOOTER, $FOOTER_FILE);
    while (<FOOTER>) {
        print HTMLFILE $_;
    }
    close(FOOTER);
}

# &doHTMLheader(FILE, title);
sub doHTMLheader {
    my $FILE = shift;
    my $title = shift;

    print $FILE "<html>\n";
    print $FILE "<head>\n";
    print $FILE "\t<title>$title</title>\n";
    print $FILE "</head>\n";
    print $FILE "<body";
    if ($BGCOLOR) {
        print $FILE " BGCOLOR=\"$BGCOLOR\"";
    }
    if ($BGIMAGE) {
        print $FILE " BACKGROUND=\"$BGIMAGE\"";
    }
    print $FILE ">\n";
}

# &doHTMLcloser(FILE);
sub doHTMLcloser {
    my $FILE = shift;

    print $FILE "</body>\n</html>\n";
}

# This function takes a filename as an arguement as an array and returns a
# two variable array of ($width, $height)
sub getImageSize {
    my $filename = shift;
    my $width = 0;
    my $height = 0;

    my $info = image_info($filename);

    if (my $error = $info->{error}) {
        die "Can't parse image info: $error\n";
    }

    ($width, $height) = dim($info);

    return ($width, $height);
}

# This function takes a filename as an argument and produces some HTML to
# wrap it up.
# &doWrapper($count, @files);
sub doWrapper {
    my $place = shift;
    my $fileArray = shift;

    my $imageName = @$fileArray[$place];
    my $wrapperName = $imageName . ".html";

    my $width = 0;
    my $height = 0;
    my $caption = $captions{$imageName}->{"caption"};
    my $lastname = "";
    my $nextname = "";

    ($width, $height) = &getImageSize($imageName);

    open(WRAP, "> $wrapperName");
    &doHTMLheader(WRAP, $caption);

    print WRAP "<center>\n";

    if($place > 0 && (my $lastfile = @$fileArray[$place - 1])) {
        if ($captions{$lastfile}->{"photoname"} ne "") {
            $lastname = $captions{$lastfile}->{"photoname"};
        }
        else {
            $lastname = $lastfile;
        }
        print WRAP "<a href=\"$lastfile.html\">last: $lastname</a>\&nbsp;\&nbsp;";
    }

    print WRAP "<a href=\"$filename\">index</a>";
    
    if (my $nextfile = @$fileArray[$place + 1]) {
        if ($captions{$nextfile}->{"photoname"} ne "") {
            $nextname = $captions{$nextfile}->{"photoname"};
        }
        else {
            $nextname = $nextfile;
        }
        print WRAP "\&nbsp;\&nbsp;<a href=\"", $nextfile, ".html\">next: $nextname</a>";
    }

    print WRAP "<br><hr>";

    print WRAP "<h1>$caption</h1>\n<p>\n";
    print WRAP "\t<img src=\"$imageName\" height=$height width=$width ",
        "border=\"no\">\n<p>";
    print WRAP "<h1>$caption</h1>\n<p>\n";
    print WRAP "</center>\n";
    &doHTMLcloser(WRAP);
    close(WRAP);


    return $wrapperName;
}


# process the options
while ($ARGV[0] =~ /^-/) {
    $_ = shift;
    if (/^-t(.*)/) {
        $TABLESIZE = ($1 ? $1 : shift);
        if (!($TABLESIZE!=0)) {
            # Not a number or it is 0, both of which would be wrong.
            die "Illegal value for tablesize.\n";
        }
    }
    elsif (/^-T(.*)/) {
        $PAGE_TITLE = ($1 ? $1 : shift);
    }
    elsif (/^-v/) {
        $VERBOSE = 1;
    }
    elsif(/^-l/) {
        $NOLABEL = 1;
    }
    elsif(/^-j/) {
        $JAVASCRIPT = 1;
    }
    elsif(/^-w/) {
        $HTMLWRAP = 1;
    }
    elsif(/^-i(.*)/) {
        $BGIMAGE = ($1 ? $1 : shift);
        if ($BGIMAGE =~ /^-/) {
            warn "Goofy filename: ", $BGIMAGE, "\n";
        }
    }
    elsif(/^-c(.*)/) {
        $BGCOLOR = ($1 ? $1 : shift);
        if ($BGCOLOR =~ /^-/) {
            warn "Goofy color name: ", $BGCOLOR, "\n";
        }
    }
    elsif(/^-C(.*)/) {
        $CAPTION_FILE = ($1 ? $1 : shift);
        if ($CAPTION_FILE =~ /^-/) {
            warn "Goofy filename: ", $CAPTION_FILE, "\n";
        }
    }
    elsif(/^-f(.*)/) {
        $FOOTER_FILE = ($1 ? $1 : shift);
        if ($FOOTER_FILE =~ /^-/) {
            warn "Goofy filename: ", $CAPTION_FILE, "\n";
        }
    }
    elsif(/^-H(.*)/) {
        $HEADER_FILE = ($1 ? $1 : shift);
        if ($HEADER_FILE =~ /^-/) {
            warn "Goofy filename: ", $CAPTION_FILE, "\n";
        }
    }
    elsif(/^-o/) {
        $USE_CAPTION_ORDER = 1;
    }
    elsif(/^-h/) {
        &usage;
        exit;
    }
    else {
        &usage;
        die ("Unrecognized switch: $_\n");
    }
}

# Open up the file or die.   (My favorite perl syntax.)
$filename = $ARGV[0];
if (!$filename) {
    &usage;
    exit(4);
}
open(HTMLFILE, "> $filename") || die("Can't open the file $filename");

# Init the counter used in the loop.
$count = 0;

# create proper HTML header
if ($PAGE_TITLE) {
    &doHTMLheader(HTMLFILE, $PAGE_TITLE);
}
else {
    &doHTMLheader(HTMLFILE, "Thumbnails");
}

# get the html ready for java script
if ($JAVASCRIPT) {
    print HTMLFILE "<script language=\"javascript\">\n";
    print HTMLFILE "function\nlinkwindow(uniformrl)\n{\n";
    print HTMLFILE "\twindow.name = \"pictureindex\";\n";
    print HTMLFILE "\tvar windowconfig = \"status=0,scrollbars=1,resizeable=1\";\n";
    print HTMLFILE "\tvar windowvar = window.open(uniformrl, \"pictures\", windowconfig);\n";
    print HTMLFILE "}\n";
    print HTMLFILE "</script>\n";
}

# Load and add the header here
if ($HEADER_FILE ne "") {
    &doHeader(HTMLFILE, $HEADER_FILE);
}

# Get the html ready to be a table
print HTMLFILE "<table cols=$TABLESIZE>\n";

# Look at all the files in this directory or get the order from the caption
# file.
if ($USE_CAPTION_ORDER) {
    @files = &captionLoad(1);
}
else {
    &captionLoad(0);

    while (<*>) {
        # If we can tell right away we're not a jpeg or a gif.
        if (!(/\.jpg\Z/i || /\.gif\Z/i || /.png\Z/i) || (/\.thumb\.jpg\Z/i) ||
            (/\.thumb\.gif\Z/i) || (/\.thumb\.png\Z/i)) {
            next;
        }

        if (-f $_) {
            push(@files, $_);
        }
    }

}


$noF = @files;

for ($i = 0; $i < $noF; $i++) {
    # Let's take out any colons to make the filenames IE3/DOS complient
    # Lame hack alert
    $file = $files[$i];
    if (/:/) {
        $file =~ tr/:/_/;
        rename($files[$i], $file);
        $files[$i] = $file;
    }

    # figure out the thumbnail filename
    $thumbfile = $files[$i];
    $thumbfile =~ s/.jpg/.thumb.jpg/i;
    $thumbfile =~ s/.gif/.thumb.gif/i;

    # for now, if doing a substition on .jpg did not work....we assume its
    # probably not a jpeg or a gif and move on.  (Yes, I know, I should
    # probably open this up for more file formats as well.)
    if ($thumbfile eq $files[$i]) {
        next;
    }

    $image = new Image::Magick;

    # If the thumbfile exists, we don't need to make it.
    if (!(-e $thumbfile)) {
        $image->Read($files[$i]);
        $VERBOSE &&
            print "Thumbfile doesn't exist for ", $files[$i],
                "...creating....\n";

        $image->Mogrify("Scale", geometry=>"128x128>");
        $image->Write($thumbfile);
        # Let us get the size of the jpg so we know how big it is.
        ($ThumbWidth, $ThumbHeight) = $image->Get("width", "height");

    } else {
        $VERBOSE && print "Thumbfile for ", $files[$i], " found.\n";
        # Let us get the size of the jpg so we know how big it is.
        ($ThumbWidth, $ThumbHeight) = &getImageSize($thumbfile);
    }

    # If $count == 0 we are in the first place in a table.
    if ($count == 0) {
        print HTMLFILE "\t<tr>\n";
    }

    if ($HTMLWRAP) {
        $linkto = &doWrapper($i, *files{ARRAY});
    }
    else {
        $linkto = $files[$i];
    }

    # Spit out the next line in the table and increment the counter.
    if ($JAVASCRIPT) {
        print HTMLFILE "\t\t<td><center><a href=javascript:linkwindow",
            "(\"$linkto\")><img src=\"$thumbfile\" height=$ThumbHeight ",
            "width=$ThumbWidth border=\"no\"></a></center></td>\n";
    }
    else {
        print HTMLFILE "\t\t<td><center><a href=\"$linkto\"><img ",
            "src=\"$thumbfile\" height=$ThumbHeight width=$ThumbWidth ",
            "border=\"no\"></a></center></td>\n";
    }
    push(@linefiles, $files[$i]);
    $count++;

    # Fill in the table with "Picture" to act as a placeholder for
    # comments we may put in later.
    if ($count == $TABLESIZE) {
        print HTMLFILE "\t</tr>\n";
        if (!$NOLABEL) {
            foreach $i (@linefiles) {
                print HTMLFILE "\t\t<td><center>",$captions{$i}->{"caption"},"</center></td>\n";
            }
            print HTMLFILE "\t</tr>\n";
        }
        @linefiles = ();
        $count = 0;
    }
}

# if we stopped putting picture in the middle of a row
if ($count != 0) {
    print HTMLFILE "\t</tr>\n\t<tr>\n";
}

# since $count isn't 0, we must have stopped putting pictures in the middle
# of a row.  We need to put the correct number of "Picture" holders in place.
for ($i = 0; $i < $count; $i++) {
    !$NOLABEL && print HTMLFILE "\t\t<td><center>",
        $captions{$linefiles[$i]}->{"caption"},"</center></td>\n";
    if ($i == ($count - 1)) {
        print HTMLFILE "\t</tr>\n";
    }
}

# Finish off that table.
print HTMLFILE "</table>\n";

# Put the footer file here
if ($FOOTER_FILE ne "") {
    &doFooter;
}

# proper HTML close-out...
&doHTMLcloser(HTMLFILE);

# Close off that HTML file
close(HTMLFILE);
