use POSIX;
use AppConfig;
use Getopt::Long;
+use threads;
+use threads::shared;
use strict;
-# TODO: filename.txt for file comments
+# DONE: Removed some default values in config, allowing empty options
+# TODO: Stripping of image suffix for HTML file w/config option?
# TODO: Templating of EXIF
-# TODO: Priority/sorting of EXFI tags
+# TODO: Priority/sorting of EXIF tags
# TODO: Possibility for hide/show EXIF
-# TODO: RSS support? Delegate that to frontend?
-# TODO: Save reference to main-index thumbnail.
# TODO: Clear old generated files and meta on regen
# TODO: Use perlmagick et. al instead of convert/jhead..
+# BUG: The naive handling of filenames breaks on special characters
+
+my $version = "0.3";
# Runtime data
my $title = undef;
my $htmlonly = 0;
my $configfile = undef;
my $halp = undef;
+my $album_comment = undef;
+my $doexif = 1;
+my $threadcounter = 0;
+share ( $threadcounter );
GetOptions (
"title=s" => \$title,
"htmlonly!" => \$htmlonly,
+ "exif!" => \$doexif,
"config=s" => \$configfile,
"help" => \$halp
);
if ( $halp )
{
- print "\nplsgen version 0.1\n";
+ print "\nplsgen version " . $version . "\n";
print "Copyright Jon Langseth, BSD lisence\n\n";
print " --title='Your album title'\n";
print " Sets the album title. Title will be stored in .title\n";
print " --htmlonly\n";
print " Add this option to only generate HTML files\n";
print " No image operations will be performed with this option\n";
+ print " --noexif\n";
+ print " Forces EXIF data block not to be written to HTML output\n";
print " --config=/path/to/config\n";
print " Overrides default config file location.\n";
print " Default is to look for ./plsgen.cfg, then ../plsgen.cfg\n";
my $index_tpl_file = $config->index_tpl_file;
my $css_file = $config->css_file;
my $navigation_script = $config->navigation_script;
+my $up_arrow_navigate = $config->up_arrow_navigate;
+my $disable_rescale = $config->disable_rescale;
my $columns = $config->columns;
my $rows = $config->rows;
my $thumb_pre = $config->thumb_pre;
my $thumb_post = $config->thumb_post;
+my $thumb_maxwidth = $config->thumb_maxwidth;
+my $thumb_maxheight = $config->thumb_maxheight;
+my $view_maxwidth = $config->view_maxwidth;
+my $view_maxheight = $config->view_maxheight;
+my $comment_pre = $config->comment_pre;
+my $comment_post = $config->comment_post;
my $idx_prev_text = $config->idx_prev_text;
my $idx_next_text = $config->idx_next_text;
my $idx_ret_text = $config->idx_ret_text;
my $footer_tag = $config->footer_tag;
+my $concurrent = $config->concurrent_threads;
# Get or save the title, depending..
if ( (not $title) && ( -f ".title" ) )
close TF;
}
+# Get the album comment, if available
+if ( -f "comment.txt" )
+{
+ open CF, "<comment.txt";
+ while (<CF>) { $album_comment .= $_; }
+ close CF;
+}
+
mkdir "thumb";
mkdir "view";
# Glob file names to an array
my @images = glob("*png *.jpg *.JPG *.gif *.GIF");
# Keep count of total number of images
-my $imagecount = $#images;
+my $imagecount = $#images+1;
my ($current, $previous, $next);
my $indexcount = 1;
else { $indexfile = "index" . $indexcount . ".html"; }
my $navscript = gen_navscript( $previous, $next, $indexfile );
my $position = $i . " of " . $imagecount;
- my $prev_text = "<a href='" . $previous . ".html'><img src='thumb/" . $previous . "' /></a>";
- my $next_text = "<a href='" . $next . ".html'><img src='thumb/" . $next . "' /></a>";
+ my $prev_text = "<a href='" . $previous . ".html'><img src='thumb/" . $previous . "' alt='Previous image' /></a>";
+ my $next_text = "<a href='" . $next . ".html'><img src='thumb/" . $next . "' alt='Next image' /></a>";
my $cur_index_text = "<a href='". $indexfile ."'>" . $idx_ret_text . "</a>";
- my $current_display = "view/" . $current;
+ my $current_display = $current;
+ $current_display = "view/" . $current unless $disable_rescale;
+
+ # Check for, and load comment from FILENAME.txt here..
+ my $comment = undef;
+ if ( -f $current . ".txt" )
+ {
+ open CF, "<" . $current . ".txt";
+ while (<CF>) { $comment .= $_; }
+ close CF;
+ }
+ if ( $comment )
+ {
+ $comment = $comment_pre . $comment . $comment_post;
+ }
printf ("Processing image %s: %s\n", $position, $current);
{
system("jhead -autorot " . $current . ">/dev/null") unless $htmlonly;
}
- my $exif_text = get_exifblock($exif);
+ my $exif_text = get_exifblock($exif) if $doexif;
-# - - Create thumbnail image (resize to new image)
- system("convert " . $current . " -geometry '160x120>' thumb/" . $current) unless $htmlonly;
-# - - Create normal display image (resize to new image)
- system("convert " . $current . " -geometry '800x600>' view/" . $current) unless $htmlonly;
+## - - Create thumbnail and normal view images, support threading
+ if ( not $htmlonly )
+ {
+ $threadcounter++;
+ my $thread = threads->create (
+ \&scale_image_t,
+ $current, $thumb_maxwidth, $thumb_maxheight,
+ $view_maxwidth, $view_maxheight, $disable_rescale);
+ if ( $threadcounter >= $concurrent )
+ {
+ foreach my $thr ( threads->list() ) { $thr->join(); }
+ }
+ }
+# - - Save a reference to the "primary image"
+ if ( not -f ".indeximage" )
+ {
+ open IM, ">.indeximage";
+ print IM $current;
+ close IM;
+ }
# - - Create full view HTML file
my $cur_html;
open TEMPLATE, "<" . $full_tpl_file or die "UNABLE TO LOAD TEMPLATE $full_tpl_file\n";
{
if ( $previous ) { $_ =~ s/%\{previous\}/$prev_text/; }
else { $_ =~ s/%\{previous\}//; }
-
if ( $next ) { $_ =~ s/%\{next\}/$next_text/; }
else { $_ =~ s/%\{next\}//; }
-
$_ =~ s/%\{index\}/$cur_index_text/;
$_ =~ s/%\{title\}/$title/;
$_ =~ s/%\{main_meta\}/$main_meta/;
$_ =~ s/%\{position\}/$position/;
$_ =~ s/%\{current\}/$current/;
$_ =~ s/%\{current_display\}/$current_display/;
+ $_ =~ s/%\{comment\}/$comment/;
$_ =~ s/%\{exif\}/$exif_text/;
$_ =~ s/%\{gallery_timestamp\}/$gentime/;
$_ =~ s/%\{navscript\}/$navscript/;
close HTML;
# - - Append image thumbnail code to current index content
- $thumbs .= $thumb_pre . "<a href='" . $current . ".html'><img src='thumb/" . $current . "' /></a>" . $thumb_post;
+ $thumbs .= $thumb_pre . "<a href='" . $current . ".html'><img src='thumb/" . $current . "' alt='View " . $current . "' /></a>" . $thumb_post;
if ( $i % ($rows*$columns) == 0 )
{
$thumbs .= "</div>";
# - - On each Y, terminate index file/group:
- make_index( $index_tpl_file, $indexcount, $indexes, $thumbs);
+ make_index( $index_tpl_file, $indexcount, $indexes, $thumbs, $album_comment );
$thumbs = "<div class='thumbnails'>";
$indexcount++;
}
}
}
$thumbs .= "</div>";
-make_index( $index_tpl_file, $indexcount, $indexes, $thumbs);
+make_index( $index_tpl_file, $indexcount, $indexes, $thumbs, $album_comment );
+
+printf ("Waiting for %d threads to finish\n", $threadcounter) if $threadcounter;
+foreach my $thr ( threads->list() ) { $thr->join(); }
# Done.
my $idxcount = shift;
my $lastidx = shift;
my $thumbs = shift;
+ my $comment = shift;
my $gentime = localtime;
my $html;
$next_text = "<a href='" . $next_file . "'>" . $idx_next_text . "</a>";
}
+ if ( $comment )
+ {
+ $comment = $comment_pre . $comment . $comment_post;
+ }
+
my $position = $indexcount . " of " . $lastidx;
my $navscript = gen_navscript( $prev_file, $next_file );
$_ =~ s/%\{previous\}/$prev_text/;
$_ =~ s/%\{next\}/$next_text/;
$_ =~ s/%\{title\}/$title/;
+ $_ =~ s/%\{comment\}/$comment/;
$_ =~ s/%\{position\}/$position/;
$_ =~ s/%\{main_meta\}/$main_meta/;
$_ =~ s/%\{navigation_script\}/$navigation_header/;
my $info = $exifTool->ImageInfo($image);
$exif->{'Make'} = $info->{'Make'};
$exif->{'Model'} = $info->{'Model'};
- #$exif->{'Orientation'} = $info->{'Orientation'};
+ $exif->{'Orientation'} = $info->{'Orientation'};
$exif->{'ExposureTime'} = $info->{'ExposureTime'};
$exif->{'FNumber'} = $info->{'FNumber'};
$exif->{'ISO'} = $info->{'ISO'};
$exif->{'ExposureCompensation'} = $info->{'ExposureCompensation'};
$exif->{'Flash'} = $info->{'Flash'};
$exif->{'FocalLength'} = $info->{'FocalLength'};
- #$exif->{'ColorSpace'} = $info->{'ColorSpace'};
- #$exif->{'FileSource'} = $info->{'FileSource'};
$exif->{'ExposureMode'} = $info->{'ExposureMode'};
$exif->{'Macro'} = $info->{'Macro'};
$exif->{'LensType'} = $info->{'LensType'};
my $flipflop = 0;
foreach my $tag ( keys %$exif )
{
+ next if $tag =~ m/Orientation/;
my $val = $exif->{$tag};
next unless $val;
$block .= "<tr class='exiflight'>" if $flipflop;
my $scriptbuffer = "<script type='text/javascript'>\n";
$scriptbuffer .= "\tnav_reg_prev('" . $prev . "');\n" if $prev;
$scriptbuffer .= "\tnav_reg_next('" . $next . "');\n" if $next;
- $scriptbuffer .= "\tnav_reg_index('" . $index . "');\n" if $index;
+ if ( $up_arrow_navigate == 1 )
+ {
+ $scriptbuffer .= "\tnav_reg_index('" . $index . "');\n" if $index;
+ }
$scriptbuffer .= "\tnav_reg_onkeypress();\n";
$scriptbuffer .= "</script>\n";
return $scriptbuffer;
}
+sub scale_image_t
+{
+ my $current = shift;
+ my $thumb_maxwidth = shift;
+ my $thumb_maxheight = shift;
+ my $view_maxwidth = shift;
+ my $view_maxheight = shift;
+ my $disable_rescale = shift;
+
+ my $tgeom = $thumb_maxwidth . "x" . $thumb_maxheight;
+ my $vgeom = $view_maxwidth . "x" . $view_maxheight;
+ # - - Create thumbnail image (resize to new image)
+ system("convert " . $current . " -geometry '" . $tgeom . ">' thumb/" . $current);
+ # - - Create normal display image (resize to new image)
+ system("convert " . $current . " -geometry '" . $vgeom . ">' view/" . $current) unless $disable_rescale;
+ $threadcounter--;
+
+}
+
sub get_config
{
# My standard way of implementing AppConfig use ...
CASE => 1,
ERROR => \&cfg_error,
GLOBAL => {
- DEFAULT => "<unset>",
+ DEFAULT => "<undef>",
ARGCOUNT => AppConfig::ARGCOUNT_ONE
},
}
$cfg->full_tpl_file("/usr/local/share/plsgen/full.tpl");
$cfg->define('index_tpl_file');
$cfg->index_tpl_file("/usr/local/share/plsgen/index.tpl");
+
$cfg->define('css_file');
$cfg->css_file("../style.css");
$cfg->define('navigation_script');
$cfg->navigation_script("../nav.js");
+
+ $cfg->define('up_arrow_navigate');
+ $cfg->up_arrow_navigate(1);
+
$cfg->define('columns');
$cfg->columns(4);
$cfg->define('rows');
$cfg->rows(3);
+
+ $cfg->define('concurrent_threads');
+ $cfg->concurrent_threads(1);
+
+ $cfg->define('thumb_maxwidth');
+ $cfg->thumb_maxwidth(160);
+ $cfg->define('thumb_maxheight');
+ $cfg->thumb_maxheight(120);
+ $cfg->define('view_maxwidth');
+ $cfg->view_maxwidth(800);
+ $cfg->define('view_maxheight');
+ $cfg->view_maxwidth(600);
+ $cfg->define('disable_rescale');
+ $cfg->disable_rescale(0);
+
$cfg->define('thumb_pre');
- $cfg->thumb_pre("<div class='thumb'>");
$cfg->define('thumb_post');
- $cfg->thumb_post("</div>");
+
+ $cfg->define('comment_pre');
+ $cfg->define('comment_post');
+
$cfg->define('idx_prev_text');
- $cfg->idx_prev_text("← Back");
$cfg->define('idx_next_text');
- $cfg->idx_next_text("Next →");
$cfg->define('idx_ret_text');
- $cfg->idx_ret_text("To index");
+
$cfg->define('footer_tag');
- $cfg->footer_tag('plsgen : Perl Simple Gallery Generator 0.1');
+ $cfg->footer_tag('plsgen : Perl Simple Gallery Generator ' . $version);
$cfg->file($filename) if -f $filename;
return $cfg;