#!/usr/bin/perl # # # Copyright 2003-2010 - Matt Drown (panzer@dhp.com) # # TravelGen v1.04 (version numbers, we don't need no stinkin' version numbers) # # #Sat Feb 20 18:18:53 PST 2010 #-Fixed in main output #-Updated link/vlink/alink colors to make more sense in defaults #-Fixed the regex associated with html iptc swapping to be greedy, to # prevent more then expected text to be removed. # #Wed Nov 5 21:57:25 PST 2008 #-Moved the next/previous to right hand side, bringing text/exif to top #-Changed default css to be sans-serif fonts. # #Sat Sep 6 13:48:00 PDT 2008 #-Added ".caption" style sheet #-fixed next/previous to go to parent when end of file list and not loop. # this was a problem due to $html causing a break in the prev/next list #-added "thumbaddborder" option # #Wed Sep 3 23:42:38 PDT 2008 #-All kinds of changes not documented, just added correct magic to spit GPS # coords in proper format from exiftool, for parsing by google maps. #-Added "thumbtrimborder" option # #Mon Sep 19 09:53:53 PDT 2005 #-Strips all crap out of thumbnails, and adds height/width marks in html # source now. This should speed up xfers. # #Wed Mar 26 00:12:39 PST 2003 # Travel Log Generator (formely GenTravel) # A static HTML thumbnail generator with some options to make it more like # a travel log. The ability to add highilighted pictures and comments # around groups of pictures. # use strict; use Image::Magick; use File::Basename; use File::Path; ### Define all the variables, and the user definable variables my $run_configfile = "travelgen.cfg"; my $run_outputfile = "index.html"; my $run_topleveldir = ""; my %run_vars = ( thumbnaildir => $run_topleveldir."travelgen_th", thumbnailprefix => "", thumbnailsuffix => "", thumbnailsize => "100", thumbnailqual => "60", reduceddir => $run_topleveldir."travelgen_re", reducedprefix => "", reducedsuffix => "", reducedsize => "640", reducedqual => "90", highlightdir => $run_topleveldir."travelgen_hi", highlightprefix => "", highlightsuffix => "", highlightsize => "800", highlightqual => "90", highlightalign => "left", captiondir => $run_topleveldir."travelgen_hi", captionprefix => "", captionsuffix => "", captionsize => "800", captionqual => "90", regenthumbs => "no", thumbcentercrop => "no", thumbtrimborder => "no", thumbtrimbordersize => "20", thumbaddborder => "no", thumbaddbordersize => "3", thumbaddbordercolor => "#000000", bodytext => "", csstext => "\n", cellpadding => "5", imagesperrow => "5", displayfilesize => "yes", includeoriginal => "yes", displayfilename => "yes", exif => "yes", html => "yes", htmlcss => "\n", htmlbody => "", exifhtml => "yes", center => "yes", title => "My Pictures", linkname => "Next Page", imgsrcoptions => "border=0", titleprefix => "

", titlesuffix => "

", footer => "\n", exiftag => "(DateTimeDigitized)
f/(FNumber) - (ExposureTime) sec - ISO (ISO)
\n(FocalLength) / (Lens)
\n(Title)
", exifhtmltag => "

(Title)
f/(FNumber) - (ExposureTime) sec - ISO (ISO) - (Lens) @ (FocalLength)
\n" ); my @run_ignorelist = ($run_configfile, $run_outputfile, "(.*).html", "(.*).cfg", "(.*).txt", "(.*)travelgen(.*)" ); #######################Code########################### #Define some local vars my $linenumber=0; my $outputfile; my $bogus; my $command; my $command_args; my $file; my $textline; my @filelist=(); my $page; my $temptext; my $htmlnext="none"; my $htmlprev="none"; my $abort = 0; ## Later we'll actually parse command line options, right now, we're not # Open the config file, and start slurping in commands open CONFIG, "<$run_configfile" or die "Can't open $run_configfile: $!\n"; while() { $linenumber++; chop (my $line = $_); if ($line =~ /^#/) { next; } if (length($line) eq 0) { next; } if ($abort ne 0) { next; } if ($line =~ /^\$(.*)$/) { ($bogus, $line) = split (/^\$/, $line); ($command, $command_args) = split (/\s+/, $line, 2 ); #if running a command, then proccess the thumbnails if (scalar(@filelist) > 0) { $page .= ProcGenThumbs(*filelist); @filelist=(); } print "Command to execute = $command - $command_args\n"; if ($command =~ /var/i) { $page .= ProcVar(split (/\s+/, $command_args, 2)); } if ($command =~ /title/i) { $page .= ProcTitle($command_args); } if (($command =~ /ref/i) || ($command =~ /link/i)) { $page .= ProcLink(split (/\s+/, $command_args, 2)); } if ($command =~ /outputfile/i) { if (defined $outputfile) { $page .= ProcFooter(); ProcCloseOutputFile($page, $outputfile); } $outputfile = ProcOutputFile($command_args); $page = ProcHeader(); } if ($command =~ /highlight/i) { $temptext = ""; while() { chop (my $textline = $_); if ($textline =~ /^\$END/i) { last; } $temptext .= $textline."\n"; } $page .= ProcHighlight($temptext, split (/\s+/, $command_args, 4)); } if ($command =~ /caption/i) { $page .= ProcCaption(split (/\s+/, $command_args, 3)); } if (($command =~ /text/i) || ($command =~ /html/i)) { $temptext = ""; while() { chop (my $textline = $_); if ($textline =~ /^\$END/i) { last; } $temptext .= $textline."\n"; } $page .= ProcText($command, $temptext); } if ($command =~ /abort/i) { $abort = 1; } } else { push (@filelist, glob($line)); } } if (scalar(@filelist) > 0) { $page .= ProcGenThumbs(*filelist); $page .= ProcFooter(); } ProcCloseOutputFile($page, $outputfile); ### End of Main Program #### ############################################################## sub ProcOutputFile { my $of = shift; if (length($of) eq 0) { die "OutputFile needs an argument on linenumber: $linenumber\n"; } local *OUTPUTFILE; open (OUTPUTFILE, ">$of") or die "Can't write $of: $!\n"; return *OUTPUTFILE; } sub ProcHeader { my $html; $html = "\n\n"; $html .= "".$run_vars{"title"}."\n"; $html .= $run_vars{"csstext"}; $html .= "\n"; $html .= $run_vars{"bodytext"}."\n"; return ($html); } sub ProcFooter { return ($run_vars{"footer"}); } sub ProcCloseOutputFile { my $html = shift; my $fh = shift; print $fh $html; close $fh; } sub ProcDir { my $dir = shift; my @filelist; my @dirlist; my $filetemp; my $dirhandle; my $greptemp; opendir $dirhandle, "$dir/"; @dirlist = grep !/^\./, (readdir $dirhandle); foreach $greptemp (@run_ignorelist) { @dirlist = grep !/$greptemp/, @dirlist; } foreach $filetemp (@dirlist) { if ( -d "$dir/$filetemp") { push (@filelist, ProcDir("$dir/$filetemp")); } else { push (@filelist, "$dir/$filetemp"); } } closedir $dirhandle; return (@filelist); } sub min { my $left = shift; my $right = shift; if ($left < $right) { return $left; } else { return $right; } } #Debugging is fun, isn't it? sub ProcGenThumbsdebug { my $filelist = shift; my @realfilelist = (); my $filetemp; foreach $filetemp (@filelist) { print "Testing if $filetemp is a directory\n"; if (-d $filetemp) { push (@realfilelist, ProcDir ($filetemp)); } else { push (@realfilelist, $filetemp); } } foreach $filetemp (@realfilelist) { print "done - $filetemp\n"; } } sub ProcGenThumbs { my $filelist = shift; my $html2; my $html; my @realfilelist = (); my $filetemp; my $filetempx; my $filetempy; my $thumbtemp; my $thumbtempx; my $thumbtempy; my $reducetemp; my $reducetempx; my $reducetempy; my $htmltemp; my $columns; my $colwidth; my $counter; my $index; my $temp; my $image; my $nextfile; my $prevfile; foreach $filetemp (@filelist) { if ( -d $filetemp) { push (@realfilelist, ProcDir($filetemp)); } else { push (@realfilelist, $filetemp); } } if (scalar(@realfilelist) eq 0) { return(""); } $columns = min(scalar(@realfilelist), $run_vars{"imagesperrow"}); $colwidth = 100 / $columns; $html .= "\n"; $html .= ""; for ($temp = 0; $temp < $columns ; $temp++) { $html .= ""; } $html .= "\n"; $counter=0; for ($index=0; $index < @realfilelist ; $index++) { $filetemp = @realfilelist[$index]; # $nextfile = @realfilelist[$index +1]; # $prevfile = @realfilelist[$index - 1]; # Make sure that start/end of filelist goes back up if (!defined(@realfilelist[$index +1])) { $nextfile=".."; } else { $nextfile = @realfilelist[$index +1]; } if ($index eq 0) { $prevfile=".."; } else { $prevfile = @realfilelist[$index - 1]; } # print "Main LOOP - $filetemp\n"; if (($counter%$run_vars{"imagesperrow"}) eq 0) { $html .= "\n"; } $counter++; $thumbtemp=ProcBuildJpeg($filetemp, $run_vars{"thumbnailsize"}, $run_vars{"thumbnailqual"}, $run_vars{"thumbnaildir"}, $run_vars{"thumbnailprefix"}, $run_vars{"thumbnailsuffix"}, $run_vars{"thumbcentercrop"}, $run_vars{"thumbtrimborder"}, $run_vars{"thumbaddborder"}); $reducetemp=ProcBuildJpeg($filetemp, $run_vars{"reducedsize"}, $run_vars{"reducedqual"}, $run_vars{"reduceddir"}, $run_vars{"reducedprefix"}, $run_vars{"reducedsuffix"}, "no", #centercrop "no", #trimborder "no" #addborder ); $image = Image::Magick->new; ($filetempx, $filetempy) = $image->Ping($filetemp); ($reducetempx, $reducetempy) = $image->Ping($reducetemp); ($thumbtempx, $thumbtempy) = $image->Ping($thumbtemp); $html .= "\n"; if (($counter%$run_vars{"imagesperrow"}) eq 0) { $html .= "\n"; } } if (($counter%$run_vars{"imagesperrow"}) != 0) { $html .= "\n"; } $html .= "
\n"; # if displayfilesize == no, then don't show ANY sizes # if displayfilesize == yes, then display all sizes if ($reducetemp eq $filetemp) { if ($run_vars{"html"} eq "yes") { $htmltemp=ProcBuildHtml($filetemp, $filetempx, $filetempy, $prevfile, $nextfile); # $html .= ""; $html .= ""; } else { # $html .= ""; $html .= ""; } $html .= ""; # $html .= ""; if ($run_vars{"displayfilesize"} eq "yes") { $html .= "
$filetempx x $filetempy

\n"; } else { $html .= "
\n"; } } elsif ($run_vars{"includeoriginal"} eq "yes") { if ($run_vars{"html"} eq "yes") { $htmltemp=ProcBuildHtml($reducetemp, $reducetempx, $reducetempy, $prevfile, $nextfile); $html .= ""; } else { $html .= ""; } $html .= ""; if ($run_vars{"displayfilesize"} eq "yes") { $html .= "
$reducetempx x $reducetempy
/ "; if ($run_vars{"html"} eq "yes") { $htmltemp=ProcBuildHtml($filetemp, $filetempx, $filetempy, $prevfile, $nextfile); $html .= ""; } else { $html .= ""; } $html .= "$filetempx x $filetempy
\n"; } else { $html .= "
\n"; } } else { if ($run_vars{"html"} eq "yes") { $htmltemp=ProcBuildHtml($reducetemp, $reducetempx, $reducetempy, $prevfile, $nextfile); $html .= ""; } else { $html .= ""; } $html .= ""; if ($run_vars{"displayfilesize"} eq "yes") { $html .= "
$reducetempx x $reducetempy

\n"; } else { $html .= "
\n"; } } if ($run_vars{"displayfilename"} eq "yes") { $html .= basename($filetemp)."
\n"; } if ($run_vars{"exif"} eq "yes") { $html .= ProcExifData($filetemp,$run_vars{"exiftag"}); } $html .= "\n
\n"; if ($run_vars{"center"} eq "yes") { $html = "

\n$html
\n"; } return ($html); } sub ProcBuildHtml { my $file = shift; my $filex = shift; my $filey = shift; my $prevfile = shift; my $nextfile = shift; my $parent; my $basefile; my $htmlfile; my $htmlout; print "Building HTML for - $file ($filex, $filey)\n"; #Check to see if there is a "/" in the filename #so we can pull the proper filename for the image if ($file =~ /\//) { $parent = reverse($file); ($basefile, $parent) = split (/\/(.*)$/, $parent); $basefile = reverse($basefile); $parent = reverse($parent); } else { $basefile = $file; $parent = ""; } if ($prevfile eq "..") { $prevfile = $parent; } else { $prevfile = $prevfile.".html"; } if ($nextfile eq "..") { $nextfile = $parent; } else { $nextfile = $nextfile.".html"; } $htmlfile=$file.".html"; # print "basefile= $basefile\n"; # print "htmlfile= $htmlfile\n"; $htmlout = "\n\n"; $htmlout .= "".$run_vars{"title"}."\n"; $htmlout .= $run_vars{htmlcss}."\n"; $htmlout .= $run_vars{htmlbody}."\n"; $htmlout .= ""; $htmlout .= ""; $htmlout .= "
"; #Left Text $htmlout .= ProcExifData($file,$run_vars{"exifhtmltag"}); $htmlout .= "
"; $htmlout .= "
"; #Right Text $htmlout .= "Previous/"; $htmlout .= "Next/"; $htmlout .= "Parent\n"; $htmlout .= "
"; $htmlout .= "\n"; $htmlout .= "\n"; open (OUT, ">$htmlfile") or die "Can't write $htmlfile: $!\n"; print OUT $htmlout; close (OUT); return ($htmlfile); } sub ProcBuildJpeg { #build a jpeg file from the source file, write it to disk, return file name #if it's smaller than the requested file, then return self, don't write my $file = shift; my $size = shift; my $qual = shift; my $dir = shift; my $prefix = shift; my $suffix = shift; my $centercrop = shift; my $thumbtrimborder = shift; my $thumbaddborder = shift; my $thumbtrimbordersize = $run_vars{"thumbtrimbordersize"}; my $thumbaddbordersize = $run_vars{"thumbaddbordersize"}; my $thumbaddbordercolor = $run_vars{"thumbaddbordercolor"}; my $thumb; my $thumbfile; my $thumbdir; my $image; my $timage; my $tx; my $ty; my $ix; my $iy; my $tempcc; if (!defined($prefix)) { $prefix = ""; } if (!defined($suffix)) { $prefix = ""; } if (!defined($centercrop)) { $centercrop = "no"; } if (!defined($thumbtrimborder)) { $thumbtrimborder = "no"; } #Check to see if there is a "/" in the filename #And if so, build the proper dir format if ($file =~ /\//) { $thumb = reverse($file); ($thumbfile, $thumb) = split (/\/(.*)$/, $thumb); $thumb = reverse($thumb); $thumbfile = reverse($thumbfile); $thumbdir = $thumb."/".$dir; $thumb = "$thumb/$dir/$prefix$thumbfile$suffix"; } else { $thumbdir = $dir; $thumb = "$dir/$prefix$file$suffix"; } if (! -e $thumbdir) { eval { &File::Path::mkpath($thumbdir, 0, 0755) }; if ($@) { print "Couldn't create $thumbdir:\n $@\n"; exit(); } } if (! -d $thumbdir) { dir ("$thumbdir is not a directory, and needs to be.\n"); } $image = Image::Magick->new; $timage = Image::Magick->new; ($tx, $ty) = $timage->Ping($thumb); ($ix, $iy) = $image->Ping($file); if ( ($run_vars{"regenthumbs"} eq "yes") || (($tx != $size) && ($ty != $size))) { if ($ix > $size || $iy > $size) { # print "Reading File - $file\n"; $image->Read(filename=>$file); # $image->UnsharpMask(radius=>0.7, amount=>1.5, threshold=>0); if ($centercrop eq "yes") { ($ix, $iy) = $image->Get('columns','rows'); #remove the border of 20 pixels $ix=$ix-($thumbtrimbordersize*2);$iy=$iy-($thumbtrimbordersize*2); if ($ix > $iy) { $tempcc = (($ix-$iy)/2); $image->Crop(geometry=>"${iy}x${iy}+${tempcc}+$thumbtrimbordersize"); } else { $tempcc = (($iy-$ix)/2); $image->Crop(geometry=>"${ix}x${ix}+$thumbtrimbordersize+${tempcc}"); } } #TrimThumbs - remove the black border before making thumbs if ($thumbtrimborder eq "yes") { ($ix, $iy) = $image->Get('columns','rows'); $ix=$ix-$thumbtrimbordersize*2; $iy=$iy-$thumbtrimbordersize*2; $image->Crop(geometry=>"${ix}x${iy}+$thumbtrimbordersize+$thumbtrimbordersize"); } # EndTrimThumbs if ($thumbaddborder eq "yes") { $size=$size-(2*$thumbaddbordersize); } $image->Scale(geometry=>"${size}x${size}"); $image->Set(quality=>$qual); $image->Strip(); if ($thumbaddborder eq "yes") { $image->Border(geometry=>"${ix}x${iy}", width=>"${thumbaddbordersize}", height=>"${thumbaddbordersize}", color=>"${thumbaddbordercolor}"); } $image->Write(filename=>"$thumb"); # print "Writing thumbnailfile - $thumb \n"; } else { # print "Doing Nothing to - $file\n"; $thumb=$file; } } return ($thumb); } sub ProcCaption { my $file = shift; my $filesize = shift; my $filequal = shift; my $filesave; my $filesavex; my $filesavey; my $image; my $html; if (!defined($filesize)) { $filesize = $run_vars{"captionsize"}; } if (!defined($filequal)) { $filequal = $run_vars{"captionqual"}; } $filesave=ProcBuildJpeg($file, $filesize, $filequal, $run_vars{"captiondir"}, $run_vars{"captionprefix"}, $run_vars{"captionsuffix"}, "no", #centercrop "no", #trimborder "no" #addborder ); $image = Image::Magick->new; ($filesavex, $filesavey) = $image->Ping($filesave); $html = "
"; $html .= "
\n"; $html .= ""; if ($filesave eq $file) { $html .= ""; } else { $html .= ""; } $html .= "
\n"; return ($html); } sub ProcHighlight { my $text= shift; my $file = shift; my $filealign = shift; my $filesize = shift; my $filequal = shift; my $filesave; my $filesavex; my $filesavey; my $image; my $html; my $htmltext; my $htmlpic; if (!defined($filealign)) { $filealign = $run_vars{"highlightalign"}; } if (!defined($filesize)) { $filesize=$run_vars{"highlightsize"}; } if (!defined($filequal)) { $filequal=$run_vars{"highlightqual"}; } $filesave=ProcBuildJpeg($file, $filesize, $filequal, $run_vars{"highlightdir"}, $run_vars{"highlightprefix"}, $run_vars{"highlightsuffix"}, "no", #centercrop "no", #trimborder "no" #addborder ); $image = Image::Magick->new; ($filesavex, $filesavey) = $image->Ping($filesave); $html .= "\n"; $html .= "\n"; $html .= "\n"; $htmltext = "\n"; $htmlpic ="
\n$text\n"; if ($run_vars{"includeoriginal"} eq "yes") { $htmlpic .= ""; } if ($filealign eq "left") { $htmlpic .= ""; } else { $htmlpic .= "src=\"$filesave\" "; $htmlpic .= "width=$filesavex height=$filesavey "; $htmlpic .= $run_vars{"imgsrcoptions"}.">"; } if ($run_vars{"includeoriginal"} eq "yes") { $htmlpic .= ""; } if ($filealign eq "left") { $html .= $htmlpic.$htmltext; } else { $html .= $htmltext.$htmlpic; } $html .= "
\n"; if ($run_vars{"center"} eq "yes") { $html = "
\n$html
\n"; } return($html); } sub ProcVar { my $var = shift; my $value = shift; $run_vars{"$var"}=$value; return(""); } sub ProcLink { my $linkaddr = shift; my $linkname = shift; my $html; if ($linkname eq "") { $linkname=$run_vars{"linkname"}; } $html = "$linkname\n"; return($html); } sub ProcText { my $command = shift; my $text = shift; if ($command =~ /html/i) { return ($text); } else { $text = $run_vars{"textheader"}.$text.$run_vars{"textfooter"}; } return ($text); } sub ProcTitle { my $text = shift; my $html; $html= $run_vars{"titleprefix"}.$text.$run_vars{"titlesuffix"}."\n"; return($html); } sub ProcExifData { my $file = shift; my $html = shift; my $tag; my $value; my $title; open EXIF, "exiftool -c '%.6f' -s -s \"$file\" 2>&1 |"; # $html = $run_vars{"exiftag"}; while() { chomp; if ($_ =~ /^([\w\s-]+):\s*(.*)\s*$/) { $tag = $1; $value = $2; $html =~ s/\($tag\)/$value/; } } $html =~ s/\(.+?\)//g; close EXIF; return ($html); }