#!/usr/bin/perl

#
# webgallery v1.2
#   by anders-webgallery@evantide.com
#
# creates a web friendly version of jpg pictures (typically from 
# a digital camera) that look like the following example:
# http://www.anders.com/pictures/public/01-haiti-views/
# webgallery takes the path to the pictures as an argument. the 
# path is broken down with : marks and included with the pictures
# in the html as the title to the album. then the program recurses 
# up the directory tree createing (or overwriteing after asking) 
# the index.html files for each directory below that directory that
# contains pictures (more precisely, an index.html file) i keep my
# pictures in directories like this: pictures/2001/02-27-lake_tahoe
# and run the script from the pictures/ directory so i get the full
# date as the album title and i get a roll-up of all my albums for
# the year in the pictures/2001/ directory and a roll-up of all the
# years in the pictures/ directory.
#
# requires the perl module Image::Magick which requires ImageMagick 
# 5.2.9 which are both available from http://www.imagemagick.org/
#
# requires a file called "template.inc" which will be used as a
# template for html pages. instances of @@body will be replaced 
# with the main page content and instences of @@title will be 
# replaced with the album title. if no "template.txt" exists in 
# the album directory, then successivly higher directories will 
# be searched untill one is found. if no "template.inc" is 
# found, the script will exit.
#
# the image conversion progress indicator: [rswsw] bares some
# explanation. r = "read" s = "size" and w = "write". the image
# gets read into memory, sized to the $max_image_size, written as
# name_sm.jpg, sized to $max_thumbnail_size and written as name.gif.
#
# more complete installation instructions are available at:
#   http://www.anders.com/projects/webgallery/install.html
#
# settings:
#   set the following to your likeing

$max_image_size      = "1024x768";
$max_thumbnail_size  = "128x96";

$thumbnails_per_line = 5;

$table_cellpadding   = 10;
$table_cellspacing   = 5;
$table_border        = 0;

$sm_quality       = 70;
$thumb_quality    = 50;

#
# end of editable stuff
#
################################################################

$| = 1; # make each print statement autoflush

use Image::Magick;

if ( ! $ARGV[0] || ! -d $ARGV[0] )  {
  print "usage: webgallery directory/to/convert\n";

}
else {
  $body  = "<table border=\"$table_border\" cellpadding=\"$table_cellpadding\" cellspacing=\"$table_cellspacing\">\n <tr>\n";
  $count = 0;
  @parts = split /\//, $ARGV[0];

  $title     = join ": ", @parts;
  $directory = join "/",  @parts;

  opendir ( D, $directory ) || die "can't open $_: $!\n";  
  @entries = readdir ( D );
  closedir ( D );

  foreach $entry ( sort @entries ) {
    if ( $entry =~ /.jpg$/i ) {
      $tmp1 = $entry;
      $tmp1 =~ s/.jpg$//i;
      $tmp2 = $tmp1;
      $tmp2 =~ s/_sm$//;
      $tmp3 = $tmp1;
      $tmp3 =~ s/_thumb$//;
      if ( ($tmp1 =~ /_sm$/ && ( -e "$directory/$tmp2.jpg" || -e "$directory/$tmp2.JPG" )) || ($tmp1 =~ /_thumb$/) )  {
        print "skipping $directory/$entry\n";

      }
      else  {
        convert ( "$directory/$entry" );

        $name = $entry;
        $name =~ s/.jpg$//i;

        $image = Image::Magick->new;
        $error = $image->Read ( "$directory/$name\_thumb.jpg" );

        if ( $error ne "" ) {
          print "\n\n$error\n";
          exit;

        }

        $width = $image->Get ( 'width' );
        $height = $image->Get ( 'height' );

        undef $image;

        if ( ! ( $count % $thumbnails_per_line ) && ( $count > 0 ) )  {
          $body .= " </tr>\n <tr>\n";

        }

        $count ++;

        $body .= "  <td align=\"center\"><a href=\"$name\_sm.jpg\">";
        $body .= "<img src=\"$name\_thumb.jpg\" width=\"$width\" height=\"$height\" border=\"0\"></a><br>";
        $body .= "<font size=\"1\">$name<br><a href=\"$entry\">original</a></font></td>\n";

      }

    }

  }

  if ( $count > 0 )  {
    $body .= " </tr>\n</table>";

    $template = find_template ( join "/", @parts );

    if ( ! $template )  {
      print "can't find a template.inc file! no gallery index.html will be written.\n";

    }
    else {
      $tmp_path = "$directory/index.html";
      if ( -e $tmp_path ) {
        print "overwrite $tmp_path? (Y/n) ";
        $result = <STDIN>;
        if ( $result eq "y" || $result eq "Y" || $result eq "\n" )  {
          print "writeing $tmp_path\n";
          open ( I, $template ) || die "could not open $template";
          open ( O, ">$tmp_path" ) or die "can't open $_\n";

          while ( $line = <I> )  {
            if ( $line =~ /@@\w+/ )  {

              $line =~ s/\@\@title/$title/g;
              $line =~ s/\@\@body/$body/g;

            }
            print O $line;

          }

          close ( O );
          close ( I );

        }

      }
      else {
        print "writeing $tmp_path\n";
        open ( I, $template ) || die "could not open $template";
        open ( O, ">$tmp_path" ) or die "can't open $_\n";

        while ( $line = <I> )  {
          if ( $line =~ /@@\w+/ )  {

            $line =~ s/\@\@title/$title/g;
            $line =~ s/\@\@body/$body/g;
 
          } 
          print O $line;

        }

        close ( O );
        close ( I );

      }

    }

  }

  while ( pop @parts )  {
    $path = join "/", @parts, "index.html";
    build_index ( $path );

  }

}

###################################################
# subroutines
###################################################

#
# convert ( $file );
#   builds smaller "*_sm.jpg" and "*.gif" versions of $file
#

sub convert  {
  my ( $file ) = @_;
  my $tmp = $file;

  $tmp =~ s/.jpg$//i;
  $tmp =~ s/_sm$//i;
  $tmp =~ s/_thumb$//i;
#print $tmp;
  if ( ! -e "$tmp\_sm.jpg" || ! -e "$tmp\_thumb.jpg" )  {
    print "converting $file [";

    my $image = Image::Magick->new;

    print "r";
    $error = $image->Read( $file );

    if ( $error ne "" ) {
      print "\n\n$error\n";
      exit;

    }

    $file =~ s/.jpg//i;

    if ( ! -e "$file\_sm.jpg" )  {
      print "s";
      $error = $image->Resize( geometry=>$max_image_size );

      if ( $error ne "" ) {
        print "\n\n$error\n";
        exit;

      }
#zacatek bordelu
     $error = $image->Set( quality=>$sm_quality );

      if ( $error ne "" ) {
        print "\n\n$error\n";
        exit;

      }
#konec drastickeho zasahu

      print "w";
      $error = $image->Write( "$file\_sm.jpg" );

      if ( $error ne "" ) {
        print "\n\n$error\n";
        exit;

      }


    }
    if ( ! -e "$tmp\_thumb.jpg" )  {
      print "s";
      $error = $image->Resize( geometry=>$max_thumbnail_size );

      if ( $error ne "" ) {
        print "\n\n$error\n";
        exit;

      }

#zacatek bordelu
     $error = $image->Set( quality=>$thumb_quality );

      if ( $error ne "" ) {
        print "\n\n$error\n";
        exit;

      }
#konec drastickeho zasahu

      print "w";
      $error = $image->Write( "$file\_thumb.jpg" );

      if ( $error ne "" ) {
        print "\n\n$error\n";
        exit;

      }

    }
    print "]\n";

    undef $image;

  }

}

#
# build_index ( "somewhere/index.html" );
#   builds an index of all directories that contain an index.html
#   file. asks before overwriteing anything.

sub build_index  {
  my ( $index ) = @_;

  if ( -e $index ) {
    print "overwrite $index? (Y/n) ";
    $result = <STDIN>;
    if ( $result eq "y" || $result eq "Y" || $result eq "\n" )  {
      write_index ( $index );

    }

  }
  else {
    write_index ( $index );

  }

}

#
# write_index ( "somehwere/index.html" );
#   used by build_index. creates the index.html file
#

sub write_index  {
  my ( $index ) = @_;
  my $directory = $index;
  my $path;
  my $template;
  my $count = 0;
  my $body = "<ul>\n";
  my $title;
  my @tmp;

  $directory =~ s/index.html$//;

  if ( $directory eq "" )  {
    $directory = "./";

  }

  opendir ( D, $directory ) || die "can't open $_: $!\n";
  @entries = readdir ( D );
  closedir ( D );

  foreach $entry ( sort @entries )  {
    $path = "$directory$entry";     
    if ( ! ( $entry =~ /^\./ ) && -d "$path" && -e "$path/index.html" )  {
      $count ++;
      $body .= " <li><a href=\"$entry/\">$entry</a></li>\n";

    }                            
     
  }  
  $body .= "</ul>";
  @tmp = split /\//, $directory;
  $title = join ": ", @tmp;

  if ( $count > 0 )  {
    $template = find_template ( $directory );

    if ( $template )  {
      print "writeing $index\n";

      open ( I, $template ) || die "could not open $template";
      open ( O, ">$directory/index.html" ) or die "can't open $_\n";

      while ( $line = <I> )  {
        if ( $line =~ /@@\w+/ )  {
          $line =~ s/\@\@title/$title/g;
          $line =~ s/\@\@body/$body/g;

        }
        print O $line;

      }
      close ( O );
      close ( I );

    }
    else {
      print "can't find a template.inc file! giving up.\n";

    }

  }

}

#
# $template = find_template ( "some/path/to/scan" );
#   recurses up the tree looking for a file called template.inc and returns
#   the path if one exists.
#

sub find_template  {
  my @path = split /\//, $_[0];
  my $template;
  my $tmp_path;

  push @path, "dummy";

  while ( pop @path && ! $template ) {
    $tmp_path = join "/", @path, "template.inc";
    if ( -e $tmp_path ) {   
      $template = $tmp_path;

    } 

  }
  return ( $template );

}
