#!/usr/bin/perl use strict; use File::Copy; # Config variables. my %cfgv; my $config = ".autothumb"; my $thumbprefix = "_"; my $htaccess = ".htaccess"; my $gimp = "/usr/bin/gimp"; #my $gimp = "/usr/local/software/gimp1.2.5/bin/gimp"; $gimp .= " --batch-interpreter plug_in_script_fu_eval"; # Strings inserted in all generated files. my $lock = "==This page was automatically generated by AutoThumb=="; my $lock1 = "==This index page was automatically generated by AutoThumb=="; my $version = "Autothumb perl v1.0 "; # Globalish variables. my $css = ""; my $body_opts = ""; my $state = "init"; my $cols = 0; my $errors = ""; my $colred=""; my $colgreen=""; my $colnorm=""; #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # Main program. # The original autothumb accepted this usage, but it is no longer supported: # Usage: # autothumb [x-max-size y-max-size JPGquality columns] [JPG files] my $file = $ENV{"HOME"} . "/" . $config; &ConfigDefaults(); &ConfigRead($file); &ConfigRead($config); &ProcessDescriptions(); print "\n"; print "$colgreen" . "Page title:$colnorm \t$cfgv{\"TITLE\"}\n"; print "$colgreen" . "Page subtitle:$colnorm \t$cfgv{\"SUBTITLE\"}\n"; print "$colgreen" . "Index page:$colnorm \t$cfgv{\"INDEX\"}\n"; print "$colgreen" . "CSS file:$colnorm \t$cfgv{\"CSS_FILE\"}\n"; print "$colgreen" . "Uses subpages:$colnorm \t$cfgv{\"SUBPAGES\"}\n"; print "$colgreen" . "Subpage prefix:$colnorm \t$cfgv{\"SUBPAGE_PREFIX\"}\n"; print "$colgreen" . "Is an overview:$colnorm \t$cfgv{\"OVERVIEW\"}\n"; print "$colgreen" . "Description file:$colnorm $cfgv{\"DESCRIPTIONS\"}\n"; if ($cfgv{"CHARSET"}) { print "$colgreen" . "Character set:$colnorm \t$cfgv{\"CHARSET\"}\n"; } if ($cfgv{"EXIF_CMD"}) { print "$colgreen" . "EXIF command:$colnorm \t$cfgv{\"EXIF_CMD\"}\n"; } if ($errors) { &Error("\nThe following error(s) have occurred:\n$errors"); } print "All done!\n"; exit; #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # Returns 1 if the fie was generated by autothumb, 0 otherwise. # If the file does not exist, then 1 is returned. sub CheckGeneratedFile($) { if (! -e $_[0]) { return 1; } if (!open(HTMLIN, "<$_[0]")) { &Error("The file $_[0] cannot be read! Not overwriting!\n"); return 0; } my $buffy; while ($buffy = ) { chop $buffy; if ($buffy =~ /$lock/) { close(HTMLIN); return 1; } if ($buffy =~ /$lock1/) { close(HTMLIN); return 1; } } close(HTMLIN); &Error("The file $_[0] was not generated by autothumb! " . "Not overwriting!\n"); return 0; } #------------------------------------------------------------------------------ sub OpenHTML($) { my $file = "/dev/null"; local *FH; if (&CheckGeneratedFile($_[0])) { $file = $_[0]; } open(FH, ">$file"); # Print a header in each file to mark it as generated. print FH <<"EOF"; EOF # Return the filehandle. return *FH; } #------------------------------------------------------------------------------ sub CloseHTML($) { close($_[0]); } #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ sub PrintIndexHead($) { my $fh = shift; my $charset = "iso-8859-1"; if ($cfgv{"CHARSET"}) { $charset = $cfgv{"CHARSET"}; } # Print HTML header. print $fh <<"EOF"; $css $cfgv{"TITLE"} EOF # Determine what titles are defined, and output appropriate lines. my $h1a = '

'; my $h1b = '

'; if ($cfgv{"TITLE_HEX"}) { $h1a = '

\n"; } if ($cfgv{"SUBTITLE"}) { $tmp .= "

\n"; $tmp .= " $cfgv{\"SUBTITLE\"}\n"; $tmp .= "

\n"; } else { $tmp .= "

\n"; } if ($tmp) { print $fh "
\n"; print $fh "$tmp"; print $fh "
\n"; } } #------------------------------------------------------------------------------ sub PrintIndexEnd($) { my $fh = shift; print $fh <<"EOF";
  EOF } #------------------------------------------------------------------------------ # PrintData($fh, $link, $image, $thumb, $comment) sub PrintData($$$$$) { my $fh = shift; my $link = shift; my $image = shift; my $thumb = shift; my $comment = shift; # Strip all html tags from the caption and use it for the alt text. # If no comment is available, use the image filename as the alt text. my $alt_text = $comment; $alt_text =~ s/<[^>]*>//g; if (!$alt_text) { $alt_text = $image; } # Use ImageMagick to determine the size of the thumbnail. my $width = &System("identify -format \"%w\" $thumb"); my $height = &System("identify -format \"%h\" $thumb"); chop $width; chop $height; print $fh <<"EOF";
$alt_text
$comment
EOF } #------------------------------------------------------------------------------ sub PrintTableStart($) { my $fh = shift; if (($state eq "table") || ($state eq "tr")) { return; } my $cs = $cfgv{"CELLSPACING"}; my $cp = $cfgv{"CELLPADDING"}; # Print HTML header. print $fh <<"EOF";
EOF # Update state. $state = "table"; $cols = 0; } #------------------------------------------------------------------------------ # PrintTableData($fh, $link, $image, $thumb, $comment) sub PrintTableData($$$$$) { my $fh = $_[0]; my $maxw = $cfgv{"WIDTH"} + 10; &PrintTableStart($fh); print $fh "\n"; # Start a new row in the index file if necessary. if (($state ne "tr") && ($cols == 0)) { print $fh " \n"; $state = "tr"; } print $fh " \n"; # End table row if necessary. $cols++; if ($cols == $cfgv{"HTMLCOLS"}) { print $fh " \n"; $state = "table"; $cols = 0; } } #------------------------------------------------------------------------------ sub PrintTableEnd($) { my $fh = shift; if ($state eq "tr") { print $fh " \n"; $state = "table"; } if ($state eq "table") { print $fh "
\n"; &PrintData(@_); print $fh "
\n"; print $fh "
\n\n"; $state = "none"; } } #------------------------------------------------------------------------------ # $prev, $curr, $next, $image, $comment sub PrintSubpage() { my $prev = shift; my $curr = shift; my $next = shift; my $image = shift; my $comment = shift; # If no current subpage, then return. if (!$curr) { return; } my $delay; if ($cfgv{"DELAY"}) { $delay = ' 0; $i--) { my $str = $strs[$i]; $str =~ s/ .*/>/; $str = "##i; $fmtc .= $str; } $fmto .= "\n"; $fmtc .= "\n"; } my $command = $cfgv{"EXIF_CMD"}; $command =~ s//$image/g; $exif = &System($command); chop $exif; $exif = "\n$fmto$exif$fmtc"; } # Print subpage. print $fh <<"EOF"; $delay$css $image
$prev_text $cfgv{"UP_TEXT"} $next_text

$image

$comment

EOF # Print second set of navigation links at the bottom if option is set. if ($cfgv{"SUBPAGE_NAV_BOTTOM"}) { print $fh <<"EOF";

$prev_text $cfgv{"UP_TEXT"} $next_text EOF } # Print rest of page. print $fh <<"EOF";
$exif EOF &CloseHTML($fh); } #------------------------------------------------------------------------------ sub PrintReferrer($) { my $fh = shift; my $date = &System("date"); print $fh <<"EOF";
Generated $date by AutoThumb II.
EOF } #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ sub CalculateGimpRGB() { my($r, $g, $b, $tmp); # If a background colour is defined in the CSS file, override BG_HEX # for gimp drop shadow calculations. my $bg_col = $cfgv{"BG_HEX"}; $tmp = &Grep(qr/background-color/, $cfgv{"CSS_FILE"}); $tmp =~ s/^.*background-color\s*:\s*//; $tmp =~ s/\s*;.*$//s; if ($tmp) { $bg_col = $tmp; } # If no background colour is defined, default to #000000. if (!$bg_col) { $bg_col = "#000000"; } $bg_col =~ s/^#//; ($r, $g, $b) = unpack("a2a2a2", $bg_col); $r = hex($r); $g = hex($g); $b = hex($b); # Calculate the individual RGB values if not specified. if (!$cfgv{"BG_R"}) { $cfgv{"BG_R"} = $r; } if (!$cfgv{"BG_G"}) { $cfgv{"BG_G"} = $g; } if (!$cfgv{"BG_B"}) { $cfgv{"BG_B"} = $b; } } #------------------------------------------------------------------------------ sub CalculateBodyOpts() { if ($cfgv{"FG_HEX"}) { $body_opts .= ' text="' . $cfgv{"FG_HEX"} . '"'; } if ($cfgv{"BG_HEX"}) { $body_opts .= ' bgcolor="' . $cfgv{"BG_HEX"} . '"'; } if ($cfgv{"LINK_HEX"}) { $body_opts .= ' link="' . $cfgv{"LINK_HEX"} . '"'; } if ($cfgv{"VLINK_HEX"}) { $body_opts .= ' vlink="' . $cfgv{"VLINK_HEX"} . '"'; } if ($cfgv{"ALINK_HEX"}) { $body_opts .= ' alink="' . $cfgv{"ALINK_HEX"} . '"'; } } #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # &CreateThumbnail($image, $thumb) # returns 1 if thumbnail created, 0 if it already exists. sub CreateThumbnail($$) { my $image = shift; my $thumb = shift; if (-e $thumb) { return 0; } my $cmd = $gimp . " -c -i -d -b '(script-fu-autothumb2 "; $cmd .= '"'; $cmd .= $image; $cmd .= '" '; $cmd .= $cfgv{"WIDTH"}; $cmd .= ' '; $cmd .= $cfgv{"HEIGHT"}; $cmd .= ' '; $cmd .= ($cfgv{"KEEP_AR"} ? "TRUE" : "FALSE"); $cmd .= ' '; $cmd .= $cfgv{"QUALITY"}; $cmd .= ' "'; $cmd .= $thumb; $cmd .= '" FALSE '; $cmd .= $cfgv{"BG_R"}; $cmd .= ' '; $cmd .= $cfgv{"BG_G"}; $cmd .= ' '; $cmd .= $cfgv{"BG_B"}; $cmd .= ' '; $cmd .= ($cfgv{"SHADOW"} ? "TRUE" : "FALSE"); $cmd .= ')'; $cmd .= "' '(gimp-quit 0)'"; system($cmd); return 1; #$GIMP -c -i -d -b # '(script-fu-autothumb2 "$IMAGE" $WIDTH $HEIGHT $KEEP_AR # $QUALITY "$THUMB" FALSE $BG_R $BG_G $BG_B $SHADOW) # (gimp-quit 0)' } #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ sub ProcessDescriptions() { my $buffy; my $ip_prev = ""; my $ip_curr = ""; my $ip_next = ""; my($image, $comment); # How many nested comments blocks we're in. my $commentlevel = 0; # Prefix all directories with this. my $prefixdir = ""; $state = "init"; # Check for description file; exit if not found. print "Reading $cfgv{\"DESCRIPTIONS\"}.\n"; if (! -e $cfgv{"DESCRIPTIONS"}) { &Error("$cfgv{\"DESCRIPTIONS\"} not found! Exiting...\n"); exit; } # Determine CSS information. if ($cfgv{"CSS_FILE"}) { $css = ' tag. &CalculateBodyOpts(); #---------------------------------------------------------------------- # Start writing index file. my $tmpfile = "/tmp/" . $cfgv{"INDEX"} . ".$$"; my $fh = &OpenHTML($tmpfile); &PrintIndexHead($fh); # Write the first two EXTLINKs before the pictures. print $fh " $cfgv{\"EXTLINK1\"}\n"; print $fh " $cfgv{\"EXTLINK2\"}\n"; ## Commented out because I don't think this was ever used. ### This is for backwards compatability. Print all _pre tags first. ##$tmp = &Grep(qr/^_pre\s/, $cfgv{"DESCRIPTIONS"}); ##$tmp =~ s/_pre\s/ /g; ##print $fh $tmp; # Iterate through description file. open(IN, "<$cfgv{\"DESCRIPTIONS\"}"); while ($buffy = ) { my $tableoff = 0; # Remember the previous values so we can write to the subpage. my $pimage = $image; my $pcomment = $comment; chop $buffy; $buffy =~ s/^\s+//; # Handle some block directives. # Block comments. if (($buffy eq "{c") || ($buffy eq "{comment")) { $commentlevel++; next; } if (($buffy eq "}c") || ($buffy eq "}comment")) { $commentlevel--; next; } if ($commentlevel) { next; } # Block dir if ($buffy =~ s/^{dir://) { $prefixdir = $buffy; if ($prefixdir !~ /\/$/) { $prefixdir .= "/"; } next; } if ($buffy eq "}dir") { $prefixdir = ""; next; } # Block br if ($buffy eq "{br") { &PrintTableEnd($fh); $state = "blockbr"; next; } if ($buffy eq "}br") { $state = "none"; next; } if ($state eq "blockbr") { print $fh "$buffy\n"; next; } # Block p if ($buffy eq "{p") { &PrintTableEnd($fh); $state = "blockp"; next; } if ($buffy eq "}p") { # Close with

if necessary. if ($state eq "blockp_text") { print $fh "

\n\n"; } $state = "none"; next; } if ($state eq "blockp") { # Open text with

. if ($buffy) { print $fh "

\n"; $state = "blockp_text"; } print $fh "$buffy\n"; next; } if ($state eq "blockp_text") { # If a blank line is encountered, close with

. if (!$buffy) { $buffy = "

\n"; $state = "blockp"; } print $fh "$buffy\n"; next; } if (!$buffy) { next; } #-------------------------------------------------------------- # Handle the _nt: (no table) directive. if ($buffy =~ s/^_nt:\s*//) { $tableoff = 1; } # Handle _br. if ($buffy eq "_br") { &PrintTableEnd($fh); next; } if ($buffy =~ s/^_br\s+//) { &PrintTableEnd($fh); if ($buffy) { print $fh " $buffy\n"; } next; } # Ignore _css since that's already been processed. if (($buffy =~ /^_css\s/) || ($buffy =~ /^_css$/)) { next; } # Skip any line that starts with _. if ($buffy =~ /^_/) { if ($buffy !~ /^__/) { $buffy =~ s/\s.*//; &Error("Description tag $buffy " . "is not supported!\n"); } next; } #-------------------------------------------------------------- ($image, $comment) = split /\s+/, $buffy, 2; # This should never happen, but we'll check anyway. if ($image eq $cfgv{"INDEX"}) { next; } # Determine directory and filename. my $dir = $image; my $file = $image; $dir =~ s/[^\/]*$//; $file =~ s/^.*\///; my $overviewdir = $image; $overviewdir =~ s/\/.*$//; if ($dir !~ /^\//) { $overviewdir = $prefixdir . $overviewdir; $dir = $prefixdir . $dir; $image = $prefixdir . $image; } # Check for an existing thumbnail in the directory where the # image is before creating one in the current directory. my $thumb = $dir . $thumbprefix . $file; if (! -e $thumb) { $thumb = $thumbprefix . $file; } # Now we check if a thumbnail from the Olympus D-360L/gphoto2 # combination already exists. my $odthumb = $file; $odthumb =~ tr/abc/ABC/; $odthumb =~ s/^[Pp]//; $odthumb = $dir . "thumb_P" . $odthumb; if (-e $odthumb) { $thumb = $odthumb; } print "Working on file: $image ($thumb)\n"; # Create the thumbnail. if (! &CreateThumbnail($image, $thumb)) { print "Thumb exists. Next.\n"; } # If no comment is defined and the .htaccess file exists, then # get the comment out of that file. if ((!$comment) && (-e $htaccess)) { $comment = &Grep(qr/$image/, $htaccess); chop $comment; $comment =~ s/^[^"]*"//; $comment =~ s/"[^"]*$//; } # Figure out the subpage filename. $ip_next = $image; $ip_next =~ s/\.jpg$//i; $ip_next =~ s/\.jpeg$//i; $ip_next = $cfgv{"SUBPAGE_PREFIX"} . $ip_next . ".html"; # Figure out where the index page should link. my $link; if ($cfgv{"SUBPAGES"}) { # Link to subpage if it exists. $link = $ip_next; } elsif ($cfgv{"OVERVIEW"}) { # Link to subdirectory if this is an overview page. #$link = $dir; $link = $overviewdir; $ip_next = ""; if ($cfgv{"APPEND_INDEX"}) { $link .= "/" . $cfgv{"INDEX"}; } } else { # Otherwise link to image. $link = $image; $ip_next = ""; } &PrintSubpage($ip_prev, $ip_curr, $ip_next, $pimage, $pcomment); # See if we need to close the table for this thumbnail. if ($tableoff) { &PrintTableEnd($fh); &PrintData($fh, $link, $image, $thumb, $comment); } else { &PrintTableData($fh, $link, $image, $thumb, $comment); } # Update the links for the next iteration. $ip_prev = $ip_curr; $ip_curr = $ip_next; } close(IN); # Print the last subpage. &PrintSubpage($ip_prev, $ip_curr, "", $image, $comment); # Finish off the index page. &PrintTableEnd($fh); # Write the last EXTLINK after the pictures. print $fh " $cfgv{\"EXTLINK3\"}\n"; if ($cfgv{"REFERRER"}) { &PrintReferrer($fh); } &PrintIndexEnd($fh); &CloseHTML($fh); if (&CheckGeneratedFile($cfgv{"INDEX"})) { print "Moving $tmpfile to $cfgv{\"INDEX\"}\n"; move($tmpfile, $cfgv{"INDEX"}); } else { &Error("$tmpfile not moved!\n"); } } #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ sub ConfigRead($) { my $buffy; open(IN, "<$_[0]"); while ($buffy = ) { chop $buffy; if ($buffy && !($buffy =~ /^#/)) { my $L; my $R; ($L, $R) = split /\s*=\s*/, $buffy, 2; # Remove quotes from values. if (($R =~ /^\".*\"$/) || ($R =~ /^\'.*\'$/)) { $R =~ s/^.//; chop $R; } # Execute anything that is backquoted. if ($R =~ /^\`.*\`$/) { $R =~ s/^.//; $R =~ s/\\`/`/g; chop $R; $R = &System($R); chop $R; } # Change all TRUE to 1, FALSE to 0. $R =~ s/^TRUE$/1/; $R =~ s/^FALSE$/0/; $cfgv{$L} = $R; } } close(IN); # If we're doing overviews, then it doesn't make any sense to create # subpages. if ($cfgv{"OVERVIEW"}) { $cfgv{"SUBPAGES"} = 0; } } #------------------------------------------------------------------------------ # Define default values. sub ConfigDefaults() { # Maximum width/height of thumbnails generated by gimp; jpeg quality. $cfgv{"WIDTH"} = "160"; $cfgv{"HEIGHT"} = "160"; $cfgv{"QUALITY"} = "0.75"; # Number of columns in html table of thumbnails. $cfgv{"HTMLCOLS"} = 4; # Number of seconds before next page is reloaded for slideshow. $cfgv{"DELAY"} = "0"; # Keep aspect ratio, create shadow effect. $cfgv{"KEEP_AR"} = "TRUE"; $cfgv{"SHADOW"} = "FALSE"; # HTML colours (background, foreground, links, title). $cfgv{"BG_R"} = ""; $cfgv{"BG_G"} = ""; $cfgv{"BG_B"} = ""; $cfgv{"BG_HEX"} = ""; $cfgv{"FG_HEX"} = ""; $cfgv{"LINK_HEX"} = ""; $cfgv{"VLINK_HEX"} = ""; $cfgv{"ALINK_HEX"} = ""; $cfgv{"TITLE_HEX"} = ""; $cfgv{"CELLSPACING"} = 20; $cfgv{"CELLPADDING"} = 0; $cfgv{"TITLE"} = "Index Page"; $cfgv{"SUBTITLE"} = "Impressions"; $cfgv{"INDEX"} = "index.html"; $cfgv{"CSS_FILE"} = ""; $cfgv{"PREV_TEXT"} = "<< Prev"; $cfgv{"UP_TEXT"} = "Index"; $cfgv{"NEXT_TEXT"} = "Next >>"; $cfgv{"REFERER"} = 1; $cfgv{"SUBPAGES"} = 1; $cfgv{"SUBPAGE_PREFIX"} = ""; $cfgv{"SUBPAGE_NAV_BOTTOM"} = 0; $cfgv{"OVERVIEW"} = 0; $cfgv{"APPEND_INDEX"} = 0; $cfgv{"DESCRIPTIONS"} = ".descriptions"; $cfgv{"CHARSET"} = ""; $cfgv{"EXIF_CMD"} = ""; $cfgv{"EXIF_FORMAT"} = ""; } #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # Execute a command to the system, and return the output. sub System($) { my $out = ""; my $buffy; open(PIPE, "/bin/sh -c \"$_[0]\" |"); while ($buffy = ) { $out .= $buffy; } close(PIPE); return $out; } #------------------------------------------------------------------------------ sub Grep(&$) { my $out = ""; my $buffy; my $func = shift; open(IN, "<$_[0]"); while ($buffy = ) { if ($buffy =~ $func ) { $out .= $buffy; } } close(IN); return $out; } #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ sub Error($) { print "$colred"; print "$_[0]"; print "$colnorm"; $errors .= $_[0]; } #------------------------------------------------------------------------------ #------------------------------------------------------------------------------